Skip to content

Commit e7ec126

Browse files
committed
Add spans on parse errors
1 parent 8e8ee24 commit e7ec126

File tree

4 files changed

+242
-90
lines changed

4 files changed

+242
-90
lines changed

src/parser.rs

+72-32
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,24 @@ use core::fmt;
2424

2525
use log::debug;
2626

27-
use crate::dialect::*;
2827
use crate::keywords::{self, Keyword};
2928
use crate::tokenizer::*;
3029
use crate::{ast::*, span::Span};
30+
use crate::{dialect::*, span::Spanned};
3131

3232
#[derive(Debug, Clone, PartialEq)]
3333
pub enum ParserError {
34-
TokenizerError(String),
35-
ParserError(String),
34+
TokenizerError { message: String, span: Span },
35+
ParserError { message: String, span: Span },
3636
}
3737

3838
// Use `Parser::expected` instead, if possible
3939
macro_rules! parser_err {
40-
($MSG:expr) => {
41-
Err(ParserError::ParserError($MSG.to_string()))
40+
($MSG:expr, $SPAN: expr) => {
41+
Err(ParserError::ParserError {
42+
message: $MSG.to_string(),
43+
span: $SPAN,
44+
})
4245
};
4346
}
4447

@@ -84,7 +87,10 @@ impl From<WildcardExpr> for FunctionArgExpr {
8487

8588
impl From<TokenizerError> for ParserError {
8689
fn from(e: TokenizerError) -> Self {
87-
ParserError::TokenizerError(e.to_string())
90+
ParserError::TokenizerError {
91+
message: e.to_string(),
92+
span: e.span,
93+
}
8894
}
8995
}
9096

@@ -94,13 +100,22 @@ impl fmt::Display for ParserError {
94100
f,
95101
"sql parser error: {}",
96102
match self {
97-
ParserError::TokenizerError(s) => s,
98-
ParserError::ParserError(s) => s,
103+
ParserError::TokenizerError { message, .. } => message,
104+
ParserError::ParserError { message, .. } => message,
99105
}
100106
)
101107
}
102108
}
103109

110+
impl Spanned for ParserError {
111+
fn span(&self) -> Span {
112+
match self {
113+
ParserError::TokenizerError { span, .. } => *span,
114+
ParserError::ParserError { span, .. } => *span,
115+
}
116+
}
117+
}
118+
104119
#[cfg(feature = "std")]
105120
impl std::error::Error for ParserError {}
106121

@@ -396,7 +411,7 @@ impl<'a> Parser<'a> {
396411
// name, resulting in `NOT 'a'` being recognized as a `TypedString` instead of
397412
// an unary negation `NOT ('a' LIKE 'b')`. To solve this, we don't accept the
398413
// `type 'string'` syntax for the custom data types at all.
399-
DataType::Custom(..) => parser_err!("dummy"),
414+
DataType::Custom(..) => parser_err!("dummy", Span::new()),
400415
data_type => Ok(Expr::TypedString {
401416
data_type,
402417
value: parser.parse_literal_string()?,
@@ -1059,10 +1074,13 @@ impl<'a> Parser<'a> {
10591074
}
10601075
}
10611076
// Can only happen if `get_next_precedence` got out of sync with this function
1062-
_ => parser_err!(format!(
1063-
"No infix parser for token '{}'",
1064-
Token::Word { value, span }
1065-
)),
1077+
_ => parser_err!(
1078+
format!(
1079+
"No infix parser for token '{}'",
1080+
Token::Word { value, span },
1081+
),
1082+
span
1083+
),
10661084
},
10671085
Token::DoubleColon { .. } => self.parse_pg_cast(expr),
10681086
Token::ExclamationMark { .. } =>
@@ -1077,7 +1095,7 @@ impl<'a> Parser<'a> {
10771095
_ =>
10781096
// Can only happen if `get_next_precedence` got out of sync with this function
10791097
{
1080-
parser_err!(format!("No infix parser for token '{}'", tok))
1098+
parser_err!(format!("No infix parser for token '{}'", tok), tok.span())
10811099
}
10821100
}
10831101
}
@@ -1282,7 +1300,10 @@ impl<'a> Parser<'a> {
12821300

12831301
/// Report unexpected token
12841302
fn expected<T>(&self, expected: &str, found: Token) -> Result<T, ParserError> {
1285-
parser_err!(format!("Expected {}, found: {}", expected, found))
1303+
parser_err!(
1304+
format!("Expected {}, found: {}", expected, found),
1305+
found.span()
1306+
)
12861307
}
12871308

12881309
/// Look for an expected keyword and consume it if it exists
@@ -1415,7 +1436,10 @@ impl<'a> Parser<'a> {
14151436
let all = self.parse_keyword(Keyword::ALL);
14161437
let distinct = self.parse_keyword(Keyword::DISTINCT);
14171438
if all && distinct {
1418-
return parser_err!("Cannot specify both ALL and DISTINCT".to_string());
1439+
return parser_err!(
1440+
"Cannot specify both ALL and DISTINCT".to_string(),
1441+
self.peek_token().span()
1442+
);
14191443
} else {
14201444
Ok(distinct)
14211445
}
@@ -1600,10 +1624,14 @@ impl<'a> Parser<'a> {
16001624
let names = self.parse_comma_separated(Parser::parse_object_name)?;
16011625
let cascade = self.parse_keyword(Keyword::CASCADE);
16021626
let restrict = self.parse_keyword(Keyword::RESTRICT);
1603-
let purge = self.parse_keyword(Keyword::PURGE);
16041627
if cascade && restrict {
1605-
return parser_err!("Cannot specify both CASCADE and RESTRICT in DROP");
1628+
self.prev_token();
1629+
return parser_err!(
1630+
"Cannot specify both CASCADE and RESTRICT in DROP",
1631+
self.peek_token().span()
1632+
);
16061633
}
1634+
let purge = self.parse_keyword(Keyword::PURGE);
16071635
Ok(Statement::Drop {
16081636
object_type,
16091637
if_exists,
@@ -2182,10 +2210,15 @@ impl<'a> Parser<'a> {
21822210
// bigdecimal feature is enabled, and is otherwise a no-op
21832211
// (i.e., it returns the input string).
21842212
Token::Number {
2185-
ref value, long, ..
2213+
ref value,
2214+
long,
2215+
span,
21862216
} => match value.parse() {
21872217
Ok(n) => Ok(Value::Number(n, long)),
2188-
Err(e) => parser_err!(format!("Could not parse '{}' as number: {}", value, e)),
2218+
Err(e) => parser_err!(
2219+
format!("Could not parse '{}' as number: {}", value, e),
2220+
span
2221+
),
21892222
},
21902223
Token::SingleQuotedString { ref value, .. } => {
21912224
Ok(Value::SingleQuotedString(value.to_string()))
@@ -2213,9 +2246,12 @@ impl<'a> Parser<'a> {
22132246
/// Parse an unsigned literal integer/long
22142247
pub fn parse_literal_uint(&mut self) -> Result<u64, ParserError> {
22152248
match self.next_token() {
2216-
Token::Number { value, .. } => value.parse::<u64>().map_err(|e| {
2217-
ParserError::ParserError(format!("Could not parse '{}' as u64: {}", value, e))
2218-
}),
2249+
Token::Number { value, span, .. } => {
2250+
value.parse::<u64>().map_err(|e| ParserError::ParserError {
2251+
message: format!("Could not parse '{}' as u64: {}", value, e),
2252+
span,
2253+
})
2254+
}
22192255
unexpected => self.expected("literal int", unexpected),
22202256
}
22212257
}
@@ -2881,10 +2917,10 @@ impl<'a> Parser<'a> {
28812917
Keyword::FUNCTION => Ok(ShowCreateObject::Function),
28822918
Keyword::PROCEDURE => Ok(ShowCreateObject::Procedure),
28832919
Keyword::EVENT => Ok(ShowCreateObject::Event),
2884-
keyword => Err(ParserError::ParserError(format!(
2885-
"Unable to map keyword to ShowCreateObject: {:?}",
2886-
keyword
2887-
))),
2920+
keyword => Err(ParserError::ParserError {
2921+
message: format!("Unable to map keyword to ShowCreateObject: {:?}", keyword),
2922+
span: self.peek_token().span(),
2923+
}),
28882924
}?;
28892925

28902926
let obj_name = self.parse_object_name()?;
@@ -3076,10 +3112,10 @@ impl<'a> Parser<'a> {
30763112
| TableFactor::TableFunction { alias, .. } => {
30773113
// but not `FROM (mytable AS alias1) AS alias2`.
30783114
if let Some(inner_alias) = alias {
3079-
return Err(ParserError::ParserError(format!(
3080-
"duplicate alias {}",
3081-
inner_alias
3082-
)));
3115+
return Err(ParserError::ParserError {
3116+
message: format!("duplicate alias {}", inner_alias),
3117+
span: self.peek_token().span(),
3118+
});
30833119
}
30843120
// Act as if the alias was specified normally next
30853121
// to the table name: `(mytable) AS alias` ->
@@ -3287,7 +3323,11 @@ impl<'a> Parser<'a> {
32873323
let cascade = self.parse_keyword(Keyword::CASCADE);
32883324
let restrict = self.parse_keyword(Keyword::RESTRICT);
32893325
if cascade && restrict {
3290-
return parser_err!("Cannot specify both CASCADE and RESTRICT in REVOKE");
3326+
self.prev_token();
3327+
return parser_err!(
3328+
"Cannot specify both CASCADE and RESTRICT in REVOKE",
3329+
self.peek_token().span()
3330+
);
32913331
}
32923332

32933333
Ok(Statement::Revoke {

0 commit comments

Comments
 (0)