@@ -45,9 +45,6 @@ pub enum ParserError {
45
45
TokenizerError(String),
46
46
ParserError(String),
47
47
RecursionLimitExceeded,
48
- /// Error indicating that the parsing branch taken
49
- /// did not yield a meaningful result
50
- BranchAbandoned,
51
48
}
52
49
53
50
// avoid clippy type_complexity warnings
@@ -177,7 +174,6 @@ impl fmt::Display for ParserError {
177
174
ParserError::TokenizerError(s) => s,
178
175
ParserError::ParserError(s) => s,
179
176
ParserError::RecursionLimitExceeded => "recursion limit exceeded",
180
- ParserError::BranchAbandoned => "branch abandoned",
181
177
}
182
178
)
183
179
}
@@ -1013,45 +1009,48 @@ impl<'a> Parser<'a> {
1013
1009
Ok(Statement::NOTIFY { channel, payload })
1014
1010
}
1015
1011
1016
- fn parse_expr_by_keyword(&mut self, w: &Word) -> Result<Expr, ParserError> {
1012
+ fn parse_expr_prefix_by_reserved_word(
1013
+ &mut self,
1014
+ w: &Word,
1015
+ ) -> Result<Option<Expr>, ParserError> {
1017
1016
match w.keyword {
1018
1017
Keyword::TRUE | Keyword::FALSE if self.dialect.supports_boolean_literals() => {
1019
1018
self.prev_token();
1020
- Ok(Expr::Value(self.parse_value()?))
1019
+ Ok(Some( Expr::Value(self.parse_value()?) ))
1021
1020
}
1022
1021
Keyword::NULL => {
1023
1022
self.prev_token();
1024
- Ok(Expr::Value(self.parse_value()?))
1023
+ Ok(Some( Expr::Value(self.parse_value()?) ))
1025
1024
}
1026
1025
Keyword::CURRENT_CATALOG
1027
1026
| Keyword::CURRENT_USER
1028
1027
| Keyword::SESSION_USER
1029
1028
| Keyword::USER
1030
1029
if dialect_of!(self is PostgreSqlDialect | GenericDialect) =>
1031
1030
{
1032
- Ok(Expr::Function(Function {
1031
+ Ok(Some( Expr::Function(Function {
1033
1032
name: ObjectName(vec![w.to_ident()]),
1034
1033
parameters: FunctionArguments::None,
1035
1034
args: FunctionArguments::None,
1036
1035
null_treatment: None,
1037
1036
filter: None,
1038
1037
over: None,
1039
1038
within_group: vec![],
1040
- }))
1039
+ })))
1041
1040
}
1042
1041
Keyword::CURRENT_TIMESTAMP
1043
1042
| Keyword::CURRENT_TIME
1044
1043
| Keyword::CURRENT_DATE
1045
1044
| Keyword::LOCALTIME
1046
1045
| Keyword::LOCALTIMESTAMP => {
1047
- self.parse_time_functions(ObjectName(vec![w.to_ident()]))
1048
- }
1049
- Keyword::CASE => self.parse_case_expr(),
1050
- Keyword::CONVERT => self.parse_convert_expr(false),
1051
- Keyword::TRY_CONVERT if self.dialect.supports_try_convert() => self.parse_convert_expr(true),
1052
- Keyword::CAST => self.parse_cast_expr(CastKind::Cast),
1053
- Keyword::TRY_CAST => self.parse_cast_expr(CastKind::TryCast),
1054
- Keyword::SAFE_CAST => self.parse_cast_expr(CastKind::SafeCast),
1046
+ Ok(Some( self.parse_time_functions(ObjectName(vec![w.to_ident()]))? ))
1047
+ }
1048
+ Keyword::CASE => Ok(Some( self.parse_case_expr()?) ),
1049
+ Keyword::CONVERT => Ok(Some( self.parse_convert_expr(false)?) ),
1050
+ Keyword::TRY_CONVERT if self.dialect.supports_try_convert() => Ok(Some( self.parse_convert_expr(true)?) ),
1051
+ Keyword::CAST => Ok(Some( self.parse_cast_expr(CastKind::Cast)?) ),
1052
+ Keyword::TRY_CAST => Ok(Some( self.parse_cast_expr(CastKind::TryCast)?) ),
1053
+ Keyword::SAFE_CAST => Ok(Some( self.parse_cast_expr(CastKind::SafeCast)?) ),
1055
1054
Keyword::EXISTS
1056
1055
// Support parsing Databricks has a function named `exists`.
1057
1056
if !dialect_of!(self is DatabricksDialect)
@@ -1063,22 +1062,22 @@ impl<'a> Parser<'a> {
1063
1062
})
1064
1063
) =>
1065
1064
{
1066
- self.parse_exists_expr(false)
1065
+ Ok(Some( self.parse_exists_expr(false)?) )
1067
1066
}
1068
- Keyword::EXTRACT => self.parse_extract_expr(),
1069
- Keyword::CEIL => self.parse_ceil_floor_expr(true),
1070
- Keyword::FLOOR => self.parse_ceil_floor_expr(false),
1067
+ Keyword::EXTRACT => Ok(Some( self.parse_extract_expr()?) ),
1068
+ Keyword::CEIL => Ok(Some( self.parse_ceil_floor_expr(true)?) ),
1069
+ Keyword::FLOOR => Ok(Some( self.parse_ceil_floor_expr(false)?) ),
1071
1070
Keyword::POSITION if self.peek_token().token == Token::LParen => {
1072
- self.parse_position_expr(w.to_ident())
1071
+ Ok(Some( self.parse_position_expr(w.to_ident())? ))
1073
1072
}
1074
- Keyword::SUBSTRING => self.parse_substring_expr(),
1075
- Keyword::OVERLAY => self.parse_overlay_expr(),
1076
- Keyword::TRIM => self.parse_trim_expr(),
1077
- Keyword::INTERVAL => self.parse_interval(),
1073
+ Keyword::SUBSTRING => Ok(Some( self.parse_substring_expr()?) ),
1074
+ Keyword::OVERLAY => Ok(Some( self.parse_overlay_expr()?) ),
1075
+ Keyword::TRIM => Ok(Some( self.parse_trim_expr()?) ),
1076
+ Keyword::INTERVAL => Ok(Some( self.parse_interval()?) ),
1078
1077
// Treat ARRAY[1,2,3] as an array [1,2,3], otherwise try as subquery or a function call
1079
1078
Keyword::ARRAY if self.peek_token() == Token::LBracket => {
1080
1079
self.expect_token(&Token::LBracket)?;
1081
- self.parse_array_expr(true)
1080
+ Ok(Some( self.parse_array_expr(true)?) )
1082
1081
}
1083
1082
Keyword::ARRAY
1084
1083
if self.peek_token() == Token::LParen
@@ -1087,37 +1086,36 @@ impl<'a> Parser<'a> {
1087
1086
self.expect_token(&Token::LParen)?;
1088
1087
let query = self.parse_query()?;
1089
1088
self.expect_token(&Token::RParen)?;
1090
- Ok(Expr::Function(Function {
1089
+ Ok(Some( Expr::Function(Function {
1091
1090
name: ObjectName(vec![w.to_ident()]),
1092
1091
parameters: FunctionArguments::None,
1093
1092
args: FunctionArguments::Subquery(query),
1094
1093
filter: None,
1095
1094
null_treatment: None,
1096
1095
over: None,
1097
1096
within_group: vec![],
1098
- }))
1097
+ })))
1099
1098
}
1100
- Keyword::NOT => self.parse_not(),
1099
+ Keyword::NOT => Ok(Some( self.parse_not()?) ),
1101
1100
Keyword::MATCH if dialect_of!(self is MySqlDialect | GenericDialect) => {
1102
- self.parse_match_against()
1101
+ Ok(Some( self.parse_match_against()?) )
1103
1102
}
1104
1103
Keyword::STRUCT if dialect_of!(self is BigQueryDialect | GenericDialect) => {
1105
1104
self.prev_token();
1106
- self.parse_bigquery_struct_literal()
1105
+ Ok(Some( self.parse_bigquery_struct_literal()?) )
1107
1106
}
1108
1107
Keyword::PRIOR if matches!(self.state, ParserState::ConnectBy) => {
1109
1108
let expr = self.parse_subexpr(self.dialect.prec_value(Precedence::PlusMinus))?;
1110
- Ok(Expr::Prior(Box::new(expr)))
1109
+ Ok(Some( Expr::Prior(Box::new(expr) )))
1111
1110
}
1112
1111
Keyword::MAP if self.peek_token() == Token::LBrace && self.dialect.support_map_literal_syntax() => {
1113
- self.parse_duckdb_map_literal()
1112
+ Ok(Some( self.parse_duckdb_map_literal()?) )
1114
1113
}
1115
- Keyword::DEFAULT => Ok(Expr::Default),
1116
- _ => Err(ParserError::BranchAbandoned)
1114
+ _ => Ok(None)
1117
1115
}
1118
1116
}
1119
1117
1120
- fn parse_ident_expr (&mut self, w: &Word) -> Result<Expr, ParserError> {
1118
+ fn parse_expr_prefix_by_nonreserved_word (&mut self, w: &Word) -> Result<Expr, ParserError> {
1121
1119
match self.peek_token().token {
1122
1120
Token::LParen | Token::Period => {
1123
1121
let mut id_parts: Vec<Ident> = vec![w.to_ident()];
@@ -1233,23 +1231,33 @@ impl<'a> Parser<'a> {
1233
1231
1234
1232
let next_token = self.next_token();
1235
1233
let expr = match next_token.token {
1236
- // We first try to parse the word as the prefix of an expression.
1237
- // For example, the word INTERVAL in: SELECT INTERVAL '7' DAY
1238
- Token::Word(w) => match self.try_parse(|parser| parser.parse_expr_by_keyword(&w)) {
1239
- Ok(expr) => Ok(expr),
1240
- // Word does not indicate the start of a complex expression, try to parse as identifier
1241
- Err(ParserError::BranchAbandoned) => Ok(self.parse_ident_expr(&w)?),
1242
- // Word indicates the start of a complex expression, try to parse as identifier if the
1243
- // dialect does not reserve it, otherwise return the original error
1244
- Err(e) => {
1245
- if !self.dialect.is_reserved_for_identifier(w.keyword) {
1246
- if let Ok(expr) = self.try_parse(|parser| parser.parse_ident_expr(&w)) {
1247
- return Ok(expr);
1234
+ Token::Word(w) => {
1235
+ // Save the parser index so we can rollback
1236
+ let index_before = self.index;
1237
+ // We first try to parse the word as the prefix of an expression.
1238
+ // For example, the word INTERVAL in: SELECT INTERVAL '7' DAY
1239
+ match self.parse_expr_prefix_by_reserved_word(&w) {
1240
+ // No expression prefix associated with this word
1241
+ Ok(None) => Ok(self.parse_expr_prefix_by_nonreserved_word(&w)?),
1242
+ // This word indicated an expression prefix and parsing was successful
1243
+ Ok(Some(expr)) => Ok(expr),
1244
+ // This word indicated an expression prefix but parsing failed. Two options:
1245
+ // 1. Malformed statement
1246
+ // 2. The dialect may allow this word as identifier as well as indicating an expression
1247
+ Err(e) => {
1248
+ let index_after_error = self.index;
1249
+ if !self.dialect.is_reserved_for_identifier(w.keyword) {
1250
+ // Rollback before trying to parse using a different approach
1251
+ self.index = index_before;
1252
+ if let Ok(expr) = self.parse_expr_prefix_by_nonreserved_word(&w) {
1253
+ return Ok(expr);
1254
+ }
1248
1255
}
1256
+ self.index = index_after_error;
1257
+ return Err(e);
1249
1258
}
1250
- return Err(e);
1251
1259
}
1252
- }, // End of Token::Word
1260
+ } // End of Token::Word
1253
1261
// array `[1, 2, 3]`
1254
1262
Token::LBracket => self.parse_array_expr(false),
1255
1263
tok @ Token::Minus | tok @ Token::Plus => {
@@ -3680,24 +3688,6 @@ impl<'a> Parser<'a> {
3680
3688
}
3681
3689
}
3682
3690
3683
- /// Run a parser method `f`, reverting back to the current position if unsuccessful
3684
- /// but retaining the error message if such was raised by `f`
3685
- pub fn try_parse<T, F>(&mut self, mut f: F) -> Result<T, ParserError>
3686
- where
3687
- F: FnMut(&mut Parser) -> Result<T, ParserError>,
3688
- {
3689
- let index = self.index;
3690
- match f(self) {
3691
- Ok(t) => Ok(t),
3692
- // Unwind stack if limit exceeded
3693
- Err(ParserError::RecursionLimitExceeded) => Err(ParserError::RecursionLimitExceeded),
3694
- Err(e) => {
3695
- self.index = index;
3696
- Err(e)
3697
- }
3698
- }
3699
- }
3700
-
3701
3691
/// Parse either `ALL`, `DISTINCT` or `DISTINCT ON (...)`. Returns [`None`] if `ALL` is parsed
3702
3692
/// and results in a [`ParserError`] if both `ALL` and `DISTINCT` are found.
3703
3693
pub fn parse_all_or_distinct(&mut self) -> Result<Option<Distinct>, ParserError> {
0 commit comments