@@ -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
}
@@ -1029,45 +1025,48 @@ impl<'a> Parser<'a> {
1029
1025
Ok(Statement::NOTIFY { channel, payload })
1030
1026
}
1031
1027
1032
- fn parse_expr_by_keyword(&mut self, w: &Word) -> Result<Expr, ParserError> {
1028
+ fn parse_expr_prefix_by_reserved_word(
1029
+ &mut self,
1030
+ w: &Word,
1031
+ ) -> Result<Option<Expr>, ParserError> {
1033
1032
match w.keyword {
1034
1033
Keyword::TRUE | Keyword::FALSE if self.dialect.supports_boolean_literals() => {
1035
1034
self.prev_token();
1036
- Ok(Expr::Value(self.parse_value()?))
1035
+ Ok(Some( Expr::Value(self.parse_value()?) ))
1037
1036
}
1038
1037
Keyword::NULL => {
1039
1038
self.prev_token();
1040
- Ok(Expr::Value(self.parse_value()?))
1039
+ Ok(Some( Expr::Value(self.parse_value()?) ))
1041
1040
}
1042
1041
Keyword::CURRENT_CATALOG
1043
1042
| Keyword::CURRENT_USER
1044
1043
| Keyword::SESSION_USER
1045
1044
| Keyword::USER
1046
1045
if dialect_of!(self is PostgreSqlDialect | GenericDialect) =>
1047
1046
{
1048
- Ok(Expr::Function(Function {
1047
+ Ok(Some( Expr::Function(Function {
1049
1048
name: ObjectName(vec![w.to_ident()]),
1050
1049
parameters: FunctionArguments::None,
1051
1050
args: FunctionArguments::None,
1052
1051
null_treatment: None,
1053
1052
filter: None,
1054
1053
over: None,
1055
1054
within_group: vec![],
1056
- }))
1055
+ })))
1057
1056
}
1058
1057
Keyword::CURRENT_TIMESTAMP
1059
1058
| Keyword::CURRENT_TIME
1060
1059
| Keyword::CURRENT_DATE
1061
1060
| Keyword::LOCALTIME
1062
1061
| Keyword::LOCALTIMESTAMP => {
1063
- self.parse_time_functions(ObjectName(vec![w.to_ident()]))
1064
- }
1065
- Keyword::CASE => self.parse_case_expr(),
1066
- Keyword::CONVERT => self.parse_convert_expr(false),
1067
- Keyword::TRY_CONVERT if self.dialect.supports_try_convert() => self.parse_convert_expr(true),
1068
- Keyword::CAST => self.parse_cast_expr(CastKind::Cast),
1069
- Keyword::TRY_CAST => self.parse_cast_expr(CastKind::TryCast),
1070
- Keyword::SAFE_CAST => self.parse_cast_expr(CastKind::SafeCast),
1062
+ Ok(Some( self.parse_time_functions(ObjectName(vec![w.to_ident()]))? ))
1063
+ }
1064
+ Keyword::CASE => Ok(Some( self.parse_case_expr()?) ),
1065
+ Keyword::CONVERT => Ok(Some( self.parse_convert_expr(false)?) ),
1066
+ Keyword::TRY_CONVERT if self.dialect.supports_try_convert() => Ok(Some( self.parse_convert_expr(true)?) ),
1067
+ Keyword::CAST => Ok(Some( self.parse_cast_expr(CastKind::Cast)?) ),
1068
+ Keyword::TRY_CAST => Ok(Some( self.parse_cast_expr(CastKind::TryCast)?) ),
1069
+ Keyword::SAFE_CAST => Ok(Some( self.parse_cast_expr(CastKind::SafeCast)?) ),
1071
1070
Keyword::EXISTS
1072
1071
// Support parsing Databricks has a function named `exists`.
1073
1072
if !dialect_of!(self is DatabricksDialect)
@@ -1079,22 +1078,22 @@ impl<'a> Parser<'a> {
1079
1078
})
1080
1079
) =>
1081
1080
{
1082
- self.parse_exists_expr(false)
1081
+ Ok(Some( self.parse_exists_expr(false)?) )
1083
1082
}
1084
- Keyword::EXTRACT => self.parse_extract_expr(),
1085
- Keyword::CEIL => self.parse_ceil_floor_expr(true),
1086
- Keyword::FLOOR => self.parse_ceil_floor_expr(false),
1083
+ Keyword::EXTRACT => Ok(Some( self.parse_extract_expr()?) ),
1084
+ Keyword::CEIL => Ok(Some( self.parse_ceil_floor_expr(true)?) ),
1085
+ Keyword::FLOOR => Ok(Some( self.parse_ceil_floor_expr(false)?) ),
1087
1086
Keyword::POSITION if self.peek_token().token == Token::LParen => {
1088
- self.parse_position_expr(w.to_ident())
1087
+ Ok(Some( self.parse_position_expr(w.to_ident())? ))
1089
1088
}
1090
- Keyword::SUBSTRING => self.parse_substring_expr(),
1091
- Keyword::OVERLAY => self.parse_overlay_expr(),
1092
- Keyword::TRIM => self.parse_trim_expr(),
1093
- Keyword::INTERVAL => self.parse_interval(),
1089
+ Keyword::SUBSTRING => Ok(Some( self.parse_substring_expr()?) ),
1090
+ Keyword::OVERLAY => Ok(Some( self.parse_overlay_expr()?) ),
1091
+ Keyword::TRIM => Ok(Some( self.parse_trim_expr()?) ),
1092
+ Keyword::INTERVAL => Ok(Some( self.parse_interval()?) ),
1094
1093
// Treat ARRAY[1,2,3] as an array [1,2,3], otherwise try as subquery or a function call
1095
1094
Keyword::ARRAY if self.peek_token() == Token::LBracket => {
1096
1095
self.expect_token(&Token::LBracket)?;
1097
- self.parse_array_expr(true)
1096
+ Ok(Some( self.parse_array_expr(true)?) )
1098
1097
}
1099
1098
Keyword::ARRAY
1100
1099
if self.peek_token() == Token::LParen
@@ -1103,37 +1102,36 @@ impl<'a> Parser<'a> {
1103
1102
self.expect_token(&Token::LParen)?;
1104
1103
let query = self.parse_query()?;
1105
1104
self.expect_token(&Token::RParen)?;
1106
- Ok(Expr::Function(Function {
1105
+ Ok(Some( Expr::Function(Function {
1107
1106
name: ObjectName(vec![w.to_ident()]),
1108
1107
parameters: FunctionArguments::None,
1109
1108
args: FunctionArguments::Subquery(query),
1110
1109
filter: None,
1111
1110
null_treatment: None,
1112
1111
over: None,
1113
1112
within_group: vec![],
1114
- }))
1113
+ })))
1115
1114
}
1116
- Keyword::NOT => self.parse_not(),
1115
+ Keyword::NOT => Ok(Some( self.parse_not()?) ),
1117
1116
Keyword::MATCH if dialect_of!(self is MySqlDialect | GenericDialect) => {
1118
- self.parse_match_against()
1117
+ Ok(Some( self.parse_match_against()?) )
1119
1118
}
1120
1119
Keyword::STRUCT if dialect_of!(self is BigQueryDialect | GenericDialect) => {
1121
1120
self.prev_token();
1122
- self.parse_bigquery_struct_literal()
1121
+ Ok(Some( self.parse_bigquery_struct_literal()?) )
1123
1122
}
1124
1123
Keyword::PRIOR if matches!(self.state, ParserState::ConnectBy) => {
1125
1124
let expr = self.parse_subexpr(self.dialect.prec_value(Precedence::PlusMinus))?;
1126
- Ok(Expr::Prior(Box::new(expr)))
1125
+ Ok(Some( Expr::Prior(Box::new(expr) )))
1127
1126
}
1128
1127
Keyword::MAP if self.peek_token() == Token::LBrace && self.dialect.support_map_literal_syntax() => {
1129
- self.parse_duckdb_map_literal()
1128
+ Ok(Some( self.parse_duckdb_map_literal()?) )
1130
1129
}
1131
- Keyword::DEFAULT => Ok(Expr::Default),
1132
- _ => Err(ParserError::BranchAbandoned)
1130
+ _ => Ok(None)
1133
1131
}
1134
1132
}
1135
1133
1136
- fn parse_ident_expr (&mut self, w: &Word) -> Result<Expr, ParserError> {
1134
+ fn parse_expr_prefix_by_nonreserved_word (&mut self, w: &Word) -> Result<Expr, ParserError> {
1137
1135
match self.peek_token().token {
1138
1136
Token::LParen | Token::Period => {
1139
1137
let mut id_parts: Vec<Ident> = vec![w.to_ident()];
@@ -1249,23 +1247,33 @@ impl<'a> Parser<'a> {
1249
1247
1250
1248
let next_token = self.next_token();
1251
1249
let expr = match next_token.token {
1252
- // We first try to parse the word as the prefix of an expression.
1253
- // For example, the word INTERVAL in: SELECT INTERVAL '7' DAY
1254
- Token::Word(w) => match self.try_parse(|parser| parser.parse_expr_by_keyword(&w)) {
1255
- Ok(expr) => Ok(expr),
1256
- // Word does not indicate the start of a complex expression, try to parse as identifier
1257
- Err(ParserError::BranchAbandoned) => Ok(self.parse_ident_expr(&w)?),
1258
- // Word indicates the start of a complex expression, try to parse as identifier if the
1259
- // dialect does not reserve it, otherwise return the original error
1260
- Err(e) => {
1261
- if !self.dialect.is_reserved_for_identifier(w.keyword) {
1262
- if let Ok(expr) = self.try_parse(|parser| parser.parse_ident_expr(&w)) {
1263
- return Ok(expr);
1250
+ Token::Word(w) => {
1251
+ // Save the parser index so we can rollback
1252
+ let index_before = self.index;
1253
+ // We first try to parse the word as the prefix of an expression.
1254
+ // For example, the word INTERVAL in: SELECT INTERVAL '7' DAY
1255
+ match self.parse_expr_prefix_by_reserved_word(&w) {
1256
+ // No expression prefix associated with this word
1257
+ Ok(None) => Ok(self.parse_expr_prefix_by_nonreserved_word(&w)?),
1258
+ // This word indicated an expression prefix and parsing was successful
1259
+ Ok(Some(expr)) => Ok(expr),
1260
+ // This word indicated an expression prefix but parsing failed. Two options:
1261
+ // 1. Malformed statement
1262
+ // 2. The dialect may allow this word as identifier as well as indicating an expression
1263
+ Err(e) => {
1264
+ let index_after_error = self.index;
1265
+ if !self.dialect.is_reserved_for_identifier(w.keyword) {
1266
+ // Rollback before trying to parse using a different approach
1267
+ self.index = index_before;
1268
+ if let Ok(expr) = self.parse_expr_prefix_by_nonreserved_word(&w) {
1269
+ return Ok(expr);
1270
+ }
1264
1271
}
1272
+ self.index = index_after_error;
1273
+ return Err(e);
1265
1274
}
1266
- return Err(e);
1267
1275
}
1268
- }, // End of Token::Word
1276
+ } // End of Token::Word
1269
1277
// array `[1, 2, 3]`
1270
1278
Token::LBracket => self.parse_array_expr(false),
1271
1279
tok @ Token::Minus | tok @ Token::Plus => {
@@ -3716,24 +3724,6 @@ impl<'a> Parser<'a> {
3716
3724
}
3717
3725
}
3718
3726
3719
- /// Run a parser method `f`, reverting back to the current position if unsuccessful
3720
- /// but retaining the error message if such was raised by `f`
3721
- pub fn try_parse<T, F>(&mut self, mut f: F) -> Result<T, ParserError>
3722
- where
3723
- F: FnMut(&mut Parser) -> Result<T, ParserError>,
3724
- {
3725
- let index = self.index;
3726
- match f(self) {
3727
- Ok(t) => Ok(t),
3728
- // Unwind stack if limit exceeded
3729
- Err(ParserError::RecursionLimitExceeded) => Err(ParserError::RecursionLimitExceeded),
3730
- Err(e) => {
3731
- self.index = index;
3732
- Err(e)
3733
- }
3734
- }
3735
- }
3736
-
3737
3727
/// Parse either `ALL`, `DISTINCT` or `DISTINCT ON (...)`. Returns [`None`] if `ALL` is parsed
3738
3728
/// and results in a [`ParserError`] if both `ALL` and `DISTINCT` are found.
3739
3729
pub fn parse_all_or_distinct(&mut self) -> Result<Option<Distinct>, ParserError> {
0 commit comments