@@ -256,10 +256,22 @@ impl ParserOptions {
256256    } 
257257} 
258258
259+ #[ derive( Copy ,  Clone ) ]  
260+ enum  ParserState  { 
261+     /// The default state of the parser. 
262+      Normal , 
263+     /// The state when parsing a CONNECT BY expression. This allows parsing 
264+      /// PRIOR expressions while still allowing prior as an identifier name 
265+      /// in other contexts. 
266+      ConnectBy , 
267+ } 
268+ 
259269pub  struct  Parser < ' a >  { 
260270    tokens :  Vec < TokenWithLocation > , 
261271    /// The index of the first unprocessed token in `self.tokens` 
262272     index :  usize , 
273+     /// The current state of the parser. 
274+      state :  ParserState , 
263275    /// The current dialect to use 
264276     dialect :  & ' a  dyn  Dialect , 
265277    /// Additional options that allow you to mix & match behavior 
@@ -290,6 +302,7 @@ impl<'a> Parser<'a> {
290302        Self  { 
291303            tokens :  vec ! [ ] , 
292304            index :  0 , 
305+             state :  ParserState :: Normal , 
293306            dialect, 
294307            recursion_counter :  RecursionCounter :: new ( DEFAULT_REMAINING_DEPTH ) , 
295308            options :  ParserOptions :: default ( ) , 
@@ -1040,6 +1053,10 @@ impl<'a> Parser<'a> {
10401053                    self . prev_token ( ) ; 
10411054                    self . parse_bigquery_struct_literal ( ) 
10421055                } 
1056+                 Keyword :: PRIOR  if  matches ! ( self . state,  ParserState :: ConnectBy )  => { 
1057+                     let  expr = self . parse_subexpr ( Self :: PLUS_MINUS_PREC ) ?; 
1058+                     Ok ( Expr :: Prior ( Box :: new ( expr) ) ) 
1059+                 } 
10431060                // Here `w` is a word, check if it's a part of a multi-part 
10441061                // identifier, a function call, or a simple identifier: 
10451062                _ => match  self . peek_token ( ) . token  { 
@@ -7695,6 +7712,17 @@ impl<'a> Parser<'a> {
76957712            None 
76967713        } ; 
76977714
7715+         let  connect_by = if  self . dialect . supports_connect_by ( ) 
7716+             && self 
7717+                 . parse_one_of_keywords ( & [ Keyword :: START ,  Keyword :: CONNECT ] ) 
7718+                 . is_some ( ) 
7719+         { 
7720+             self . prev_token ( ) ; 
7721+             Some ( self . parse_connect_by ( ) ?) 
7722+         }  else  { 
7723+             None 
7724+         } ; 
7725+ 
76987726        Ok ( Select  { 
76997727            distinct, 
77007728            top, 
@@ -7711,6 +7739,44 @@ impl<'a> Parser<'a> {
77117739            named_window :  named_windows, 
77127740            qualify, 
77137741            value_table_mode, 
7742+             connect_by, 
7743+         } ) 
7744+     } 
7745+ 
7746+     /// Invoke `f` after first setting the parser's `ParserState` to `state`. 
7747+      /// 
7748+      /// Upon return, restores the parser's state to what it started at. 
7749+      fn  with_state < T ,  F > ( & mut  self ,  state :  ParserState ,  mut  f :  F )  -> Result < T ,  ParserError > 
7750+     where 
7751+         F :  FnMut ( & mut  Parser )  -> Result < T ,  ParserError > , 
7752+     { 
7753+         let  current_state = self . state ; 
7754+         self . state  = state; 
7755+         let  res = f ( self ) ; 
7756+         self . state  = current_state; 
7757+         res
7758+     } 
7759+ 
7760+     pub  fn  parse_connect_by ( & mut  self )  -> Result < ConnectBy ,  ParserError >  { 
7761+         let  ( condition,  relationships)  = if  self . parse_keywords ( & [ Keyword :: CONNECT ,  Keyword :: BY ] )  { 
7762+             let  relationships = self . with_state ( ParserState :: ConnectBy ,  |parser| { 
7763+                 parser. parse_comma_separated ( Parser :: parse_expr) 
7764+             } ) ?; 
7765+             self . expect_keywords ( & [ Keyword :: START ,  Keyword :: WITH ] ) ?; 
7766+             let  condition = self . parse_expr ( ) ?; 
7767+             ( condition,  relationships) 
7768+         }  else  { 
7769+             self . expect_keywords ( & [ Keyword :: START ,  Keyword :: WITH ] ) ?; 
7770+             let  condition = self . parse_expr ( ) ?; 
7771+             self . expect_keywords ( & [ Keyword :: CONNECT ,  Keyword :: BY ] ) ?; 
7772+             let  relationships = self . with_state ( ParserState :: ConnectBy ,  |parser| { 
7773+                 parser. parse_comma_separated ( Parser :: parse_expr) 
7774+             } ) ?; 
7775+             ( condition,  relationships) 
7776+         } ; 
7777+         Ok ( ConnectBy  { 
7778+             condition, 
7779+             relationships, 
77147780        } ) 
77157781    } 
77167782
0 commit comments