@@ -190,13 +190,10 @@ impl Parser {
190
190
}
191
191
"CASE" => self . parse_case_expression ( ) ,
192
192
"CAST" => self . parse_cast_expression ( ) ,
193
- "NOT" => {
194
- let p = self . get_precedence ( & Token :: make_keyword ( "NOT" ) ) ?;
195
- Ok ( ASTNode :: SQLUnary {
196
- operator : SQLOperator :: Not ,
197
- expr : Box :: new ( self . parse_subexpr ( p) ?) ,
198
- } )
199
- }
193
+ "NOT" => Ok ( ASTNode :: SQLUnary {
194
+ operator : SQLOperator :: Not ,
195
+ expr : Box :: new ( self . parse_subexpr ( Self :: UNARY_NOT_PREC ) ?) ,
196
+ } ) ,
200
197
// Here `w` is a word, check if it's a part of a multi-part
201
198
// identifier, a function call, or a simple identifier:
202
199
_ => match self . peek_token ( ) {
@@ -230,15 +227,14 @@ impl Parser {
230
227
} , // End of Token::SQLWord
231
228
Token :: Mult => Ok ( ASTNode :: SQLWildcard ) ,
232
229
tok @ Token :: Minus | tok @ Token :: Plus => {
233
- let p = self . get_precedence ( & tok) ?;
234
230
let operator = if tok == Token :: Plus {
235
231
SQLOperator :: Plus
236
232
} else {
237
233
SQLOperator :: Minus
238
234
} ;
239
235
Ok ( ASTNode :: SQLUnary {
240
236
operator,
241
- expr : Box :: new ( self . parse_subexpr ( p ) ?) ,
237
+ expr : Box :: new ( self . parse_subexpr ( Self :: PLUS_MINUS_PREC ) ?) ,
242
238
} )
243
239
}
244
240
Token :: Number ( _) | Token :: SingleQuotedString ( _) | Token :: NationalStringLiteral ( _) => {
@@ -510,10 +506,9 @@ impl Parser {
510
506
pub fn parse_between ( & mut self , expr : ASTNode , negated : bool ) -> Result < ASTNode , ParserError > {
511
507
// Stop parsing subexpressions for <low> and <high> on tokens with
512
508
// precedence lower than that of `BETWEEN`, such as `AND`, `IS`, etc.
513
- let prec = self . get_precedence ( & Token :: make_keyword ( "BETWEEN" ) ) ?;
514
- let low = self . parse_subexpr ( prec) ?;
509
+ let low = self . parse_subexpr ( Self :: BETWEEN_PREC ) ?;
515
510
self . expect_keyword ( "AND" ) ?;
516
- let high = self . parse_subexpr ( prec ) ?;
511
+ let high = self . parse_subexpr ( Self :: BETWEEN_PREC ) ?;
517
512
Ok ( ASTNode :: SQLBetween {
518
513
expr : Box :: new ( expr) ,
519
514
negated,
@@ -530,35 +525,45 @@ impl Parser {
530
525
} )
531
526
}
532
527
528
+ const UNARY_NOT_PREC : u8 = 15 ;
529
+ const BETWEEN_PREC : u8 = 20 ;
530
+ const PLUS_MINUS_PREC : u8 = 30 ;
531
+
533
532
/// Get the precedence of the next token
534
533
pub fn get_next_precedence ( & self ) -> Result < u8 , ParserError > {
535
534
if let Some ( token) = self . peek_token ( ) {
536
- self . get_precedence ( & token)
535
+ debug ! ( "get_precedence() {:?}" , token) ;
536
+
537
+ match & token {
538
+ Token :: SQLWord ( k) if k. keyword == "OR" => Ok ( 5 ) ,
539
+ Token :: SQLWord ( k) if k. keyword == "AND" => Ok ( 10 ) ,
540
+ Token :: SQLWord ( k) if k. keyword == "NOT" => match & self . peek_nth_token ( 1 ) {
541
+ // The precedence of NOT varies depending on keyword that
542
+ // follows it. If it is followed by IN, BETWEEN, or LIKE,
543
+ // it takes on the precedence of those tokens. Otherwise it
544
+ // takes on UNARY_NOT_PREC.
545
+ Some ( Token :: SQLWord ( k) ) if k. keyword == "IN" => Ok ( Self :: BETWEEN_PREC ) ,
546
+ Some ( Token :: SQLWord ( k) ) if k. keyword == "BETWEEN" => Ok ( Self :: BETWEEN_PREC ) ,
547
+ Some ( Token :: SQLWord ( k) ) if k. keyword == "LIKE" => Ok ( Self :: BETWEEN_PREC ) ,
548
+ _ => Ok ( Self :: UNARY_NOT_PREC ) ,
549
+ } ,
550
+ Token :: SQLWord ( k) if k. keyword == "IS" => Ok ( 17 ) ,
551
+ Token :: SQLWord ( k) if k. keyword == "IN" => Ok ( Self :: BETWEEN_PREC ) ,
552
+ Token :: SQLWord ( k) if k. keyword == "BETWEEN" => Ok ( Self :: BETWEEN_PREC ) ,
553
+ Token :: SQLWord ( k) if k. keyword == "LIKE" => Ok ( Self :: BETWEEN_PREC ) ,
554
+ Token :: Eq | Token :: Lt | Token :: LtEq | Token :: Neq | Token :: Gt | Token :: GtEq => {
555
+ Ok ( 20 )
556
+ }
557
+ Token :: Plus | Token :: Minus => Ok ( Self :: PLUS_MINUS_PREC ) ,
558
+ Token :: Mult | Token :: Div | Token :: Mod => Ok ( 40 ) ,
559
+ Token :: DoubleColon => Ok ( 50 ) ,
560
+ _ => Ok ( 0 ) ,
561
+ }
537
562
} else {
538
563
Ok ( 0 )
539
564
}
540
565
}
541
566
542
- /// Get the precedence of a token
543
- pub fn get_precedence ( & self , tok : & Token ) -> Result < u8 , ParserError > {
544
- debug ! ( "get_precedence() {:?}" , tok) ;
545
-
546
- match tok {
547
- Token :: SQLWord ( k) if k. keyword == "OR" => Ok ( 5 ) ,
548
- Token :: SQLWord ( k) if k. keyword == "AND" => Ok ( 10 ) ,
549
- Token :: SQLWord ( k) if k. keyword == "NOT" => Ok ( 15 ) ,
550
- Token :: SQLWord ( k) if k. keyword == "IS" => Ok ( 17 ) ,
551
- Token :: SQLWord ( k) if k. keyword == "IN" => Ok ( 20 ) ,
552
- Token :: SQLWord ( k) if k. keyword == "BETWEEN" => Ok ( 20 ) ,
553
- Token :: SQLWord ( k) if k. keyword == "LIKE" => Ok ( 20 ) ,
554
- Token :: Eq | Token :: Lt | Token :: LtEq | Token :: Neq | Token :: Gt | Token :: GtEq => Ok ( 20 ) ,
555
- Token :: Plus | Token :: Minus => Ok ( 30 ) ,
556
- Token :: Mult | Token :: Div | Token :: Mod => Ok ( 40 ) ,
557
- Token :: DoubleColon => Ok ( 50 ) ,
558
- _ => Ok ( 0 ) ,
559
- }
560
- }
561
-
562
567
/// Return first non-whitespace token that has not yet been processed
563
568
pub fn peek_token ( & self ) -> Option < Token > {
564
569
self . peek_nth_token ( 0 )
0 commit comments