Skip to main content

rigsql_parser/grammar/
mod.rs

1mod ansi;
2mod tsql;
3
4pub use ansi::AnsiGrammar;
5pub use tsql::TsqlGrammar;
6
7use rigsql_core::{NodeSegment, Segment, SegmentType, Token, TokenKind, TokenSegment};
8
9use crate::context::ParseContext;
10
11// ── Grammar trait ────────────────────────────────────────────────
12
13/// Trait for dialect-specific SQL grammar.
14///
15/// Dialects implement `dispatch_statement` and `statement_keywords`.
16/// All shared ANSI parsing logic lives in default methods.
17pub trait Grammar: Send + Sync {
18    /// Return the set of keywords that can start a statement in this dialect.
19    fn statement_keywords(&self) -> &[&str];
20
21    /// Dispatch a single statement based on the current token.
22    /// Called from `parse_statement` after consuming leading trivia.
23    fn dispatch_statement(&self, ctx: &mut ParseContext) -> Option<Segment>;
24
25    /// ANSI-only statement dispatch.  Dialect impls can call this as fallback.
26    fn dispatch_ansi_statement(&self, ctx: &mut ParseContext) -> Option<Segment> {
27        if ctx.peek_keyword("SELECT") || ctx.peek_keyword("WITH") {
28            self.parse_select_statement(ctx)
29        } else if ctx.peek_keyword("INSERT") {
30            self.parse_insert_statement(ctx)
31        } else if ctx.peek_keyword("UPDATE") {
32            self.parse_update_statement(ctx)
33        } else if ctx.peek_keyword("DELETE") {
34            self.parse_delete_statement(ctx)
35        } else if ctx.peek_keyword("CREATE") {
36            self.parse_create_statement(ctx)
37        } else if ctx.peek_keyword("DROP") {
38            self.parse_drop_statement(ctx)
39        } else if ctx.peek_keyword("ALTER") {
40            self.parse_alter_statement(ctx)
41        } else if ctx.peek_keyword("USE")
42            || ctx.peek_keyword("TRUNCATE")
43            || ctx.peek_keyword("OPEN")
44            || ctx.peek_keyword("CLOSE")
45            || ctx.peek_keyword("DEALLOCATE")
46            || ctx.peek_keyword("FETCH")
47            || ctx.peek_keyword("BREAK")
48            || ctx.peek_keyword("CONTINUE")
49            || ctx.peek_keyword("MERGE")
50        {
51            self.parse_simple_statement(ctx)
52        } else {
53            None
54        }
55    }
56
57    // ── Top-level ────────────────────────────────────────────────
58
59    /// Parse a complete SQL file: zero or more statements.
60    fn parse_file(&self, ctx: &mut ParseContext) -> Segment {
61        let mut children = Vec::new();
62        while !ctx.at_eof() {
63            children.extend(eat_trivia_segments(ctx));
64            if ctx.at_eof() {
65                break;
66            }
67            if let Some(stmt) = self.parse_statement(ctx) {
68                children.push(stmt);
69            } else {
70                // Error recovery: skip to the next statement boundary
71                // (semicolon or a recognised statement keyword) and wrap
72                // all skipped tokens in a single Unparsable node.
73                let error_offset = ctx
74                    .peek()
75                    .map(|t| t.span.start)
76                    .unwrap_or(ctx.source().len() as u32);
77                let mut unparsable_children = Vec::new();
78                // Always consume at least one token to guarantee forward
79                // progress and avoid infinite loops (e.g. when a statement
80                // keyword like WITH is not actually a valid statement start
81                // in this context, such as WITH(NOLOCK) table hints).
82                if let Some(token) = ctx.advance() {
83                    unparsable_children.push(any_token_segment(token));
84                }
85                while !ctx.at_eof() {
86                    // Stop before a semicolon — consume it as part of the
87                    // unparsable node so the next iteration starts cleanly.
88                    if ctx.peek_kind() == Some(TokenKind::Semicolon) {
89                        if let Some(semi) = ctx.advance() {
90                            unparsable_children.push(token_segment(semi, SegmentType::Semicolon));
91                        }
92                        break;
93                    }
94                    // Stop before a token that looks like it starts a new statement.
95                    if self.peek_statement_start(ctx) {
96                        break;
97                    }
98                    if let Some(token) = ctx.advance() {
99                        unparsable_children.push(any_token_segment(token));
100                    }
101                }
102                if !unparsable_children.is_empty() {
103                    children.push(Segment::Node(NodeSegment::new(
104                        SegmentType::Unparsable,
105                        unparsable_children,
106                    )));
107                    ctx.record_error_at(
108                        error_offset,
109                        "Unparsable segment: could not match any statement",
110                    );
111                }
112            }
113        }
114        Segment::Node(NodeSegment::new(SegmentType::File, children))
115    }
116
117    /// Parse a single statement (terminated by `;` or EOF).
118    fn parse_statement(&self, ctx: &mut ParseContext) -> Option<Segment> {
119        let save = ctx.save();
120        let mut children = Vec::new();
121        children.extend(eat_trivia_segments(ctx));
122
123        let inner = self.dispatch_statement(ctx);
124
125        match inner {
126            Some(stmt_seg) => {
127                children.push(stmt_seg);
128                // Optional trailing semicolon
129                children.extend(eat_trivia_segments(ctx));
130                if let Some(semi) = ctx.eat_kind(TokenKind::Semicolon) {
131                    children.push(token_segment(semi, SegmentType::Semicolon));
132                }
133                Some(Segment::Node(NodeSegment::new(
134                    SegmentType::Statement,
135                    children,
136                )))
137            }
138            None => {
139                ctx.restore(save);
140                None
141            }
142        }
143    }
144
145    // ── SELECT ───────────────────────────────────────────────────
146
147    fn parse_select_statement(&self, ctx: &mut ParseContext) -> Option<Segment> {
148        let mut children = Vec::new();
149
150        // WITH clause (optional)
151        if ctx.peek_keyword("WITH") {
152            if let Some(with) = self.parse_with_clause(ctx) {
153                children.push(with);
154                children.extend(eat_trivia_segments(ctx));
155            }
156        }
157
158        // SELECT clause (required)
159        let select = self.parse_select_clause(ctx)?;
160        children.push(select);
161
162        // FROM clause (optional)
163        children.extend(eat_trivia_segments(ctx));
164        if ctx.peek_keyword("FROM") {
165            if let Some(from) = self.parse_from_clause(ctx) {
166                children.push(from);
167            }
168        }
169
170        // WHERE clause (optional)
171        children.extend(eat_trivia_segments(ctx));
172        if ctx.peek_keyword("WHERE") {
173            if let Some(wh) = self.parse_where_clause(ctx) {
174                children.push(wh);
175            }
176        }
177
178        // GROUP BY clause (optional)
179        children.extend(eat_trivia_segments(ctx));
180        if ctx.peek_keywords(&["GROUP", "BY"]) {
181            if let Some(gb) = self.parse_group_by_clause(ctx) {
182                children.push(gb);
183            }
184        }
185
186        // HAVING clause (optional)
187        children.extend(eat_trivia_segments(ctx));
188        if ctx.peek_keyword("HAVING") {
189            if let Some(hav) = self.parse_having_clause(ctx) {
190                children.push(hav);
191            }
192        }
193
194        // ORDER BY clause (optional)
195        children.extend(eat_trivia_segments(ctx));
196        if ctx.peek_keywords(&["ORDER", "BY"]) {
197            if let Some(ob) = self.parse_order_by_clause(ctx) {
198                children.push(ob);
199            }
200        }
201
202        // LIMIT clause (optional)
203        children.extend(eat_trivia_segments(ctx));
204        if ctx.peek_keyword("LIMIT") {
205            if let Some(lim) = self.parse_limit_clause(ctx) {
206                children.push(lim);
207            }
208        }
209
210        // OFFSET clause (optional)
211        children.extend(eat_trivia_segments(ctx));
212        if ctx.peek_keyword("OFFSET") {
213            if let Some(off) = self.parse_offset_clause(ctx) {
214                children.push(off);
215            }
216        }
217
218        // UNION / INTERSECT / EXCEPT (optional, recursive)
219        children.extend(eat_trivia_segments(ctx));
220        if ctx.peek_keyword("UNION") || ctx.peek_keyword("INTERSECT") || ctx.peek_keyword("EXCEPT")
221        {
222            if let Some(set_op) = self.parse_set_operation(ctx) {
223                children.push(set_op);
224            }
225        }
226
227        Some(Segment::Node(NodeSegment::new(
228            SegmentType::SelectStatement,
229            children,
230        )))
231    }
232
233    fn parse_select_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
234        let mut children = Vec::new();
235
236        let kw = ctx.eat_keyword("SELECT")?;
237        children.push(token_segment(kw, SegmentType::Keyword));
238
239        children.extend(eat_trivia_segments(ctx));
240
241        // DISTINCT / ALL (optional)
242        if ctx.peek_keyword("DISTINCT") || ctx.peek_keyword("ALL") {
243            if let Some(token) = ctx.advance() {
244                children.push(token_segment(token, SegmentType::Keyword));
245                children.extend(eat_trivia_segments(ctx));
246            }
247        }
248
249        // TOP (N) / TOP N (TSQL)
250        if ctx.peek_keyword("TOP") {
251            if let Some(top_kw) = ctx.advance() {
252                children.push(token_segment(top_kw, SegmentType::Keyword));
253                children.extend(eat_trivia_segments(ctx));
254                // TOP (expr) or TOP N
255                if let Some(lparen) = ctx.eat_kind(TokenKind::LParen) {
256                    children.push(token_segment(lparen, SegmentType::LParen));
257                    children.extend(eat_trivia_segments(ctx));
258                    if let Some(expr) = self.parse_expression(ctx) {
259                        children.push(expr);
260                    }
261                    children.extend(eat_trivia_segments(ctx));
262                    if let Some(rparen) = ctx.eat_kind(TokenKind::RParen) {
263                        children.push(token_segment(rparen, SegmentType::RParen));
264                    }
265                } else if let Some(num) = ctx.eat_kind(TokenKind::NumberLiteral) {
266                    children.push(token_segment(num, SegmentType::Literal));
267                }
268                children.extend(eat_trivia_segments(ctx));
269            }
270        }
271
272        // Select targets (comma-separated expressions)
273        parse_comma_separated(ctx, &mut children, |c| self.parse_select_target(c));
274
275        Some(Segment::Node(NodeSegment::new(
276            SegmentType::SelectClause,
277            children,
278        )))
279    }
280
281    fn parse_select_target(&self, ctx: &mut ParseContext) -> Option<Segment> {
282        // Parse an expression, optionally followed by alias (AS alias_name or just alias_name)
283        let expr = self.parse_expression(ctx)?;
284
285        let save = ctx.save();
286        let trivia = eat_trivia_segments(ctx);
287
288        // Check for alias: AS name, or just a word that's not a keyword
289        if ctx.peek_keyword("AS") {
290            let mut children = vec![expr];
291            children.extend(trivia);
292            let as_kw = ctx.advance().unwrap();
293            children.push(token_segment(as_kw, SegmentType::Keyword));
294            children.extend(eat_trivia_segments(ctx));
295            if let Some(alias) = self.parse_identifier(ctx) {
296                children.push(alias);
297            }
298            return Some(Segment::Node(NodeSegment::new(
299                SegmentType::AliasExpression,
300                children,
301            )));
302        }
303
304        // Implicit alias: a bare word that's not a clause keyword
305        if let Some(t) = ctx.peek_non_trivia() {
306            if t.kind == TokenKind::Word && !is_clause_keyword(&t.text) {
307                let mut children = vec![expr];
308                children.extend(trivia);
309                if let Some(alias) = self.parse_identifier(ctx) {
310                    children.push(alias);
311                }
312                return Some(Segment::Node(NodeSegment::new(
313                    SegmentType::AliasExpression,
314                    children,
315                )));
316            }
317        }
318
319        ctx.restore(save);
320        // Re-eat trivia would happen naturally at calling site
321        Some(expr)
322    }
323
324    fn parse_from_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
325        let mut children = Vec::new();
326        let kw = ctx.eat_keyword("FROM")?;
327        children.push(token_segment(kw, SegmentType::Keyword));
328        children.extend(eat_trivia_segments(ctx));
329
330        // Table references (comma-separated)
331        parse_comma_separated(ctx, &mut children, |c| self.parse_table_reference(c));
332
333        // JOIN clauses
334        loop {
335            children.extend(eat_trivia_segments(ctx));
336            if peek_join_keyword(ctx) {
337                if let Some(join) = self.parse_join_clause(ctx) {
338                    children.push(join);
339                } else {
340                    break;
341                }
342            } else {
343                break;
344            }
345        }
346
347        Some(Segment::Node(NodeSegment::new(
348            SegmentType::FromClause,
349            children,
350        )))
351    }
352
353    fn parse_table_reference(&self, ctx: &mut ParseContext) -> Option<Segment> {
354        let save = ctx.save();
355
356        // Subquery in parens
357        if ctx.peek_kind() == Some(TokenKind::LParen) {
358            if let Some(subq) = self.parse_paren_subquery(ctx) {
359                // Optional alias
360                let save2 = ctx.save();
361                let trivia = eat_trivia_segments(ctx);
362                if ctx.peek_keyword("AS")
363                    || ctx
364                        .peek_non_trivia()
365                        .is_some_and(|t| t.kind == TokenKind::Word && !is_clause_keyword(&t.text))
366                {
367                    let mut children = vec![subq];
368                    children.extend(trivia);
369                    if ctx.peek_keyword("AS") {
370                        let kw = ctx.advance().unwrap();
371                        children.push(token_segment(kw, SegmentType::Keyword));
372                        children.extend(eat_trivia_segments(ctx));
373                    }
374                    if let Some(alias) = self.parse_identifier(ctx) {
375                        children.push(alias);
376                    }
377                    return Some(Segment::Node(NodeSegment::new(
378                        SegmentType::AliasExpression,
379                        children,
380                    )));
381                }
382                ctx.restore(save2);
383                return Some(subq);
384            }
385        }
386
387        // Table name (possibly qualified: schema.table)
388        let name = self.parse_qualified_name(ctx);
389        if name.is_none() {
390            ctx.restore(save);
391            return None;
392        }
393        let name = name.unwrap();
394
395        // Optional alias
396        let save2 = ctx.save();
397        let trivia = eat_trivia_segments(ctx);
398        if ctx.peek_keyword("AS") {
399            let mut children = vec![name];
400            children.extend(trivia);
401            let kw = ctx.advance().unwrap();
402            children.push(token_segment(kw, SegmentType::Keyword));
403            children.extend(eat_trivia_segments(ctx));
404            if let Some(alias) = self.parse_identifier(ctx) {
405                children.push(alias);
406            }
407            return Some(Segment::Node(NodeSegment::new(
408                SegmentType::AliasExpression,
409                children,
410            )));
411        }
412        if let Some(t) = ctx.peek_non_trivia() {
413            if t.kind == TokenKind::Word && !is_clause_keyword(&t.text) && !is_join_keyword(&t.text)
414            {
415                let mut children = vec![name];
416                children.extend(trivia);
417                if let Some(alias) = self.parse_identifier(ctx) {
418                    children.push(alias);
419                }
420                return Some(Segment::Node(NodeSegment::new(
421                    SegmentType::AliasExpression,
422                    children,
423                )));
424            }
425        }
426        ctx.restore(save2);
427        Some(name)
428    }
429
430    fn parse_where_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
431        let mut children = Vec::new();
432        let kw = ctx.eat_keyword("WHERE")?;
433        children.push(token_segment(kw, SegmentType::Keyword));
434        children.extend(eat_trivia_segments(ctx));
435        if let Some(expr) = self.parse_expression(ctx) {
436            children.push(expr);
437        }
438        Some(Segment::Node(NodeSegment::new(
439            SegmentType::WhereClause,
440            children,
441        )))
442    }
443
444    fn parse_group_by_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
445        let mut children = Vec::new();
446        let group_kw = ctx.eat_keyword("GROUP")?;
447        children.push(token_segment(group_kw, SegmentType::Keyword));
448        children.extend(eat_trivia_segments(ctx));
449        let by_kw = ctx.eat_keyword("BY")?;
450        children.push(token_segment(by_kw, SegmentType::Keyword));
451        children.extend(eat_trivia_segments(ctx));
452
453        // Comma-separated expressions
454        parse_comma_separated(ctx, &mut children, |c| self.parse_expression(c));
455
456        Some(Segment::Node(NodeSegment::new(
457            SegmentType::GroupByClause,
458            children,
459        )))
460    }
461
462    fn parse_having_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
463        let mut children = Vec::new();
464        let kw = ctx.eat_keyword("HAVING")?;
465        children.push(token_segment(kw, SegmentType::Keyword));
466        children.extend(eat_trivia_segments(ctx));
467        if let Some(expr) = self.parse_expression(ctx) {
468            children.push(expr);
469        }
470        Some(Segment::Node(NodeSegment::new(
471            SegmentType::HavingClause,
472            children,
473        )))
474    }
475
476    fn parse_order_by_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
477        let mut children = Vec::new();
478        let order_kw = ctx.eat_keyword("ORDER")?;
479        children.push(token_segment(order_kw, SegmentType::Keyword));
480        children.extend(eat_trivia_segments(ctx));
481        let by_kw = ctx.eat_keyword("BY")?;
482        children.push(token_segment(by_kw, SegmentType::Keyword));
483        children.extend(eat_trivia_segments(ctx));
484
485        // Comma-separated order expressions
486        parse_comma_separated(ctx, &mut children, |c| self.parse_order_expression(c));
487
488        Some(Segment::Node(NodeSegment::new(
489            SegmentType::OrderByClause,
490            children,
491        )))
492    }
493
494    fn parse_order_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
495        let mut children = Vec::new();
496        let expr = self.parse_expression(ctx)?;
497        children.push(expr);
498
499        let save = ctx.save();
500        let trivia = eat_trivia_segments(ctx);
501        if ctx.peek_keyword("ASC") || ctx.peek_keyword("DESC") {
502            children.extend(trivia);
503            let kw = ctx.advance().unwrap();
504            children.push(token_segment(kw, SegmentType::Keyword));
505        } else {
506            ctx.restore(save);
507        }
508
509        // NULLS FIRST / NULLS LAST
510        let save = ctx.save();
511        let trivia = eat_trivia_segments(ctx);
512        if ctx.peek_keyword("NULLS") {
513            children.extend(trivia);
514            let kw = ctx.advance().unwrap();
515            children.push(token_segment(kw, SegmentType::Keyword));
516            children.extend(eat_trivia_segments(ctx));
517            if ctx.peek_keyword("FIRST") || ctx.peek_keyword("LAST") {
518                let kw = ctx.advance().unwrap();
519                children.push(token_segment(kw, SegmentType::Keyword));
520            }
521        } else {
522            ctx.restore(save);
523        }
524
525        Some(Segment::Node(NodeSegment::new(
526            SegmentType::OrderByExpression,
527            children,
528        )))
529    }
530
531    fn parse_limit_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
532        let mut children = Vec::new();
533        let kw = ctx.eat_keyword("LIMIT")?;
534        children.push(token_segment(kw, SegmentType::Keyword));
535        children.extend(eat_trivia_segments(ctx));
536        if let Some(expr) = self.parse_expression(ctx) {
537            children.push(expr);
538        }
539        Some(Segment::Node(NodeSegment::new(
540            SegmentType::LimitClause,
541            children,
542        )))
543    }
544
545    fn parse_offset_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
546        let mut children = Vec::new();
547        let kw = ctx.eat_keyword("OFFSET")?;
548        children.push(token_segment(kw, SegmentType::Keyword));
549        children.extend(eat_trivia_segments(ctx));
550        if let Some(expr) = self.parse_expression(ctx) {
551            children.push(expr);
552        }
553        Some(Segment::Node(NodeSegment::new(
554            SegmentType::OffsetClause,
555            children,
556        )))
557    }
558
559    fn parse_with_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
560        let mut children = Vec::new();
561        let kw = ctx.eat_keyword("WITH")?;
562        children.push(token_segment(kw, SegmentType::Keyword));
563        children.extend(eat_trivia_segments(ctx));
564
565        // RECURSIVE (optional)
566        if ctx.peek_keyword("RECURSIVE") {
567            let kw = ctx.advance().unwrap();
568            children.push(token_segment(kw, SegmentType::Keyword));
569            children.extend(eat_trivia_segments(ctx));
570        }
571
572        // CTE definitions (comma-separated)
573        parse_comma_separated(ctx, &mut children, |c| self.parse_cte_definition(c));
574
575        Some(Segment::Node(NodeSegment::new(
576            SegmentType::WithClause,
577            children,
578        )))
579    }
580
581    fn parse_cte_definition(&self, ctx: &mut ParseContext) -> Option<Segment> {
582        let mut children = Vec::new();
583        let name = self.parse_identifier(ctx)?;
584        children.push(name);
585        children.extend(eat_trivia_segments(ctx));
586
587        // Optional column list
588        if ctx.peek_kind() == Some(TokenKind::LParen) {
589            if let Some(cols) = self.parse_paren_block(ctx) {
590                children.push(cols);
591                children.extend(eat_trivia_segments(ctx));
592            }
593        }
594
595        let as_kw = ctx.eat_keyword("AS")?;
596        children.push(token_segment(as_kw, SegmentType::Keyword));
597        children.extend(eat_trivia_segments(ctx));
598
599        // ( subquery )
600        if let Some(subq) = self.parse_paren_subquery(ctx) {
601            children.push(subq);
602        }
603
604        Some(Segment::Node(NodeSegment::new(
605            SegmentType::CteDefinition,
606            children,
607        )))
608    }
609
610    fn parse_set_operation(&self, ctx: &mut ParseContext) -> Option<Segment> {
611        let mut children = Vec::new();
612
613        // UNION / INTERSECT / EXCEPT
614        let kw = ctx.advance()?;
615        children.push(token_segment(kw, SegmentType::Keyword));
616        children.extend(eat_trivia_segments(ctx));
617
618        // ALL / DISTINCT (optional)
619        if ctx.peek_keyword("ALL") || ctx.peek_keyword("DISTINCT") {
620            let kw = ctx.advance().unwrap();
621            children.push(token_segment(kw, SegmentType::Keyword));
622            children.extend(eat_trivia_segments(ctx));
623        }
624
625        // Following select
626        if let Some(sel) = self.parse_select_statement(ctx) {
627            children.push(sel);
628        }
629
630        Some(Segment::Node(NodeSegment::new(
631            SegmentType::SelectStatement,
632            children,
633        )))
634    }
635
636    // ── JOIN ─────────────────────────────────────────────────────
637
638    fn parse_join_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
639        let mut children = Vec::new();
640
641        // Optional: INNER / LEFT / RIGHT / FULL / CROSS
642        if ctx.peek_keyword("INNER")
643            || ctx.peek_keyword("LEFT")
644            || ctx.peek_keyword("RIGHT")
645            || ctx.peek_keyword("FULL")
646            || ctx.peek_keyword("CROSS")
647        {
648            let kw = ctx.advance().unwrap();
649            children.push(token_segment(kw, SegmentType::Keyword));
650            children.extend(eat_trivia_segments(ctx));
651
652            // Optional: OUTER
653            if ctx.peek_keyword("OUTER") {
654                let kw = ctx.advance().unwrap();
655                children.push(token_segment(kw, SegmentType::Keyword));
656                children.extend(eat_trivia_segments(ctx));
657            }
658        }
659
660        let join_kw = ctx.eat_keyword("JOIN")?;
661        children.push(token_segment(join_kw, SegmentType::Keyword));
662        children.extend(eat_trivia_segments(ctx));
663
664        // Table reference
665        if let Some(tref) = self.parse_table_reference(ctx) {
666            children.push(tref);
667        }
668
669        // ON or USING
670        children.extend(eat_trivia_segments(ctx));
671        if ctx.peek_keyword("ON") {
672            let kw = ctx.advance().unwrap();
673            let mut on_children = vec![token_segment(kw, SegmentType::Keyword)];
674            on_children.extend(eat_trivia_segments(ctx));
675            if let Some(expr) = self.parse_expression(ctx) {
676                on_children.push(expr);
677            }
678            children.push(Segment::Node(NodeSegment::new(
679                SegmentType::OnClause,
680                on_children,
681            )));
682        } else if ctx.peek_keyword("USING") {
683            let kw = ctx.advance().unwrap();
684            let mut using_children = vec![token_segment(kw, SegmentType::Keyword)];
685            using_children.extend(eat_trivia_segments(ctx));
686            if let Some(paren) = self.parse_paren_block(ctx) {
687                using_children.push(paren);
688            }
689            children.push(Segment::Node(NodeSegment::new(
690                SegmentType::UsingClause,
691                using_children,
692            )));
693        }
694
695        Some(Segment::Node(NodeSegment::new(
696            SegmentType::JoinClause,
697            children,
698        )))
699    }
700
701    // ── INSERT ───────────────────────────────────────────────────
702
703    fn parse_insert_statement(&self, ctx: &mut ParseContext) -> Option<Segment> {
704        let mut children = Vec::new();
705        let kw = ctx.eat_keyword("INSERT")?;
706        children.push(token_segment(kw, SegmentType::Keyword));
707        children.extend(eat_trivia_segments(ctx));
708
709        let into_kw = ctx.eat_keyword("INTO")?;
710        children.push(token_segment(into_kw, SegmentType::Keyword));
711        children.extend(eat_trivia_segments(ctx));
712
713        // Table name
714        if let Some(name) = self.parse_qualified_name(ctx) {
715            children.push(name);
716        }
717        children.extend(eat_trivia_segments(ctx));
718
719        // Optional column list
720        if ctx.peek_kind() == Some(TokenKind::LParen) {
721            if let Some(cols) = self.parse_paren_block(ctx) {
722                children.push(cols);
723                children.extend(eat_trivia_segments(ctx));
724            }
725        }
726
727        // VALUES or SELECT
728        if ctx.peek_keyword("VALUES") {
729            if let Some(vals) = self.parse_values_clause(ctx) {
730                children.push(vals);
731            }
732        } else if ctx.peek_keyword("SELECT") || ctx.peek_keyword("WITH") {
733            if let Some(sel) = self.parse_select_statement(ctx) {
734                children.push(sel);
735            }
736        }
737
738        Some(Segment::Node(NodeSegment::new(
739            SegmentType::InsertStatement,
740            children,
741        )))
742    }
743
744    fn parse_values_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
745        let mut children = Vec::new();
746        let kw = ctx.eat_keyword("VALUES")?;
747        children.push(token_segment(kw, SegmentType::Keyword));
748        children.extend(eat_trivia_segments(ctx));
749
750        // Comma-separated (expr, expr, ...)
751        parse_comma_separated(ctx, &mut children, |c| self.parse_paren_block(c));
752
753        Some(Segment::Node(NodeSegment::new(
754            SegmentType::ValuesClause,
755            children,
756        )))
757    }
758
759    // ── UPDATE ───────────────────────────────────────────────────
760
761    fn parse_update_statement(&self, ctx: &mut ParseContext) -> Option<Segment> {
762        let mut children = Vec::new();
763        let kw = ctx.eat_keyword("UPDATE")?;
764        children.push(token_segment(kw, SegmentType::Keyword));
765        children.extend(eat_trivia_segments(ctx));
766
767        // Table name
768        if let Some(name) = self.parse_table_reference(ctx) {
769            children.push(name);
770        }
771        children.extend(eat_trivia_segments(ctx));
772
773        // SET clause
774        if ctx.peek_keyword("SET") {
775            if let Some(set) = self.parse_set_clause(ctx) {
776                children.push(set);
777            }
778        }
779
780        // WHERE clause
781        children.extend(eat_trivia_segments(ctx));
782        if ctx.peek_keyword("WHERE") {
783            if let Some(wh) = self.parse_where_clause(ctx) {
784                children.push(wh);
785            }
786        }
787
788        Some(Segment::Node(NodeSegment::new(
789            SegmentType::UpdateStatement,
790            children,
791        )))
792    }
793
794    fn parse_set_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
795        let mut children = Vec::new();
796        let kw = ctx.eat_keyword("SET")?;
797        children.push(token_segment(kw, SegmentType::Keyword));
798        children.extend(eat_trivia_segments(ctx));
799
800        // col = expr, ...
801        parse_comma_separated(ctx, &mut children, |c| self.parse_expression(c));
802
803        Some(Segment::Node(NodeSegment::new(
804            SegmentType::SetClause,
805            children,
806        )))
807    }
808
809    // ── DELETE ────────────────────────────────────────────────────
810
811    fn parse_delete_statement(&self, ctx: &mut ParseContext) -> Option<Segment> {
812        let mut children = Vec::new();
813        let kw = ctx.eat_keyword("DELETE")?;
814        children.push(token_segment(kw, SegmentType::Keyword));
815        children.extend(eat_trivia_segments(ctx));
816
817        // FROM
818        if ctx.peek_keyword("FROM") {
819            let from_kw = ctx.advance().unwrap();
820            children.push(token_segment(from_kw, SegmentType::Keyword));
821            children.extend(eat_trivia_segments(ctx));
822        }
823
824        // Table name
825        if let Some(name) = self.parse_qualified_name(ctx) {
826            children.push(name);
827        }
828
829        // WHERE clause
830        children.extend(eat_trivia_segments(ctx));
831        if ctx.peek_keyword("WHERE") {
832            if let Some(wh) = self.parse_where_clause(ctx) {
833                children.push(wh);
834            }
835        }
836
837        Some(Segment::Node(NodeSegment::new(
838            SegmentType::DeleteStatement,
839            children,
840        )))
841    }
842
843    // ── DDL ──────────────────────────────────────────────────────
844
845    fn parse_create_statement(&self, ctx: &mut ParseContext) -> Option<Segment> {
846        let mut children = Vec::new();
847        let kw = ctx.eat_keyword("CREATE")?;
848        children.push(token_segment(kw, SegmentType::Keyword));
849        children.extend(eat_trivia_segments(ctx));
850
851        if ctx.peek_keyword("TABLE") {
852            return self.parse_create_table_body(ctx, children);
853        }
854
855        // For other CREATE statements, consume until semicolon or EOF
856        self.consume_until_end(ctx, &mut children);
857        Some(Segment::Node(NodeSegment::new(
858            SegmentType::Statement,
859            children,
860        )))
861    }
862
863    fn parse_create_table_body(
864        &self,
865        ctx: &mut ParseContext,
866        mut children: Vec<Segment>,
867    ) -> Option<Segment> {
868        let kw = ctx.eat_keyword("TABLE")?;
869        children.push(token_segment(kw, SegmentType::Keyword));
870        children.extend(eat_trivia_segments(ctx));
871
872        // IF NOT EXISTS
873        if ctx.peek_keyword("IF") {
874            let kw = ctx.advance().unwrap();
875            children.push(token_segment(kw, SegmentType::Keyword));
876            children.extend(eat_trivia_segments(ctx));
877            if let Some(kw) = ctx.eat_keyword("NOT") {
878                children.push(token_segment(kw, SegmentType::Keyword));
879                children.extend(eat_trivia_segments(ctx));
880            }
881            if let Some(kw) = ctx.eat_keyword("EXISTS") {
882                children.push(token_segment(kw, SegmentType::Keyword));
883                children.extend(eat_trivia_segments(ctx));
884            }
885        }
886
887        // Table name
888        if let Some(name) = self.parse_qualified_name(ctx) {
889            children.push(name);
890        }
891        children.extend(eat_trivia_segments(ctx));
892
893        // Column definitions in parens
894        if ctx.peek_kind() == Some(TokenKind::LParen) {
895            if let Some(defs) = self.parse_paren_block(ctx) {
896                children.push(defs);
897            }
898        }
899
900        Some(Segment::Node(NodeSegment::new(
901            SegmentType::CreateTableStatement,
902            children,
903        )))
904    }
905
906    fn parse_drop_statement(&self, ctx: &mut ParseContext) -> Option<Segment> {
907        let mut children = Vec::new();
908        let kw = ctx.eat_keyword("DROP")?;
909        children.push(token_segment(kw, SegmentType::Keyword));
910        children.extend(eat_trivia_segments(ctx));
911
912        // Consume until semicolon
913        self.consume_until_end(ctx, &mut children);
914        Some(Segment::Node(NodeSegment::new(
915            SegmentType::DropStatement,
916            children,
917        )))
918    }
919
920    fn parse_alter_statement(&self, ctx: &mut ParseContext) -> Option<Segment> {
921        let mut children = Vec::new();
922        let kw = ctx.eat_keyword("ALTER")?;
923        children.push(token_segment(kw, SegmentType::Keyword));
924        children.extend(eat_trivia_segments(ctx));
925
926        self.consume_until_end(ctx, &mut children);
927        Some(Segment::Node(NodeSegment::new(
928            SegmentType::AlterTableStatement,
929            children,
930        )))
931    }
932
933    // ── Expression parsing ───────────────────────────────────────
934
935    /// Parse an expression. This uses a simple precedence climbing approach.
936    fn parse_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
937        self.parse_or_expression(ctx)
938    }
939
940    fn parse_or_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
941        let mut left = self.parse_and_expression(ctx)?;
942        loop {
943            let save = ctx.save();
944            let trivia = eat_trivia_segments(ctx);
945            if ctx.peek_keyword("OR") {
946                let op = ctx.advance().unwrap();
947                let mut children = vec![left];
948                children.extend(trivia);
949                children.push(token_segment(op, SegmentType::Keyword));
950                children.extend(eat_trivia_segments(ctx));
951                if let Some(right) = self.parse_and_expression(ctx) {
952                    children.push(right);
953                }
954                left = Segment::Node(NodeSegment::new(SegmentType::BinaryExpression, children));
955            } else {
956                ctx.restore(save);
957                break;
958            }
959        }
960        Some(left)
961    }
962
963    fn parse_and_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
964        let mut left = self.parse_not_expression(ctx)?;
965        loop {
966            let save = ctx.save();
967            let trivia = eat_trivia_segments(ctx);
968            if ctx.peek_keyword("AND") {
969                let op = ctx.advance().unwrap();
970                let mut children = vec![left];
971                children.extend(trivia);
972                children.push(token_segment(op, SegmentType::Keyword));
973                children.extend(eat_trivia_segments(ctx));
974                if let Some(right) = self.parse_not_expression(ctx) {
975                    children.push(right);
976                }
977                left = Segment::Node(NodeSegment::new(SegmentType::BinaryExpression, children));
978            } else {
979                ctx.restore(save);
980                break;
981            }
982        }
983        Some(left)
984    }
985
986    fn parse_not_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
987        if ctx.peek_keyword("NOT") {
988            let mut children = Vec::new();
989            let kw = ctx.advance().unwrap();
990            children.push(token_segment(kw, SegmentType::Keyword));
991            children.extend(eat_trivia_segments(ctx));
992            if let Some(expr) = self.parse_not_expression(ctx) {
993                children.push(expr);
994            }
995            return Some(Segment::Node(NodeSegment::new(
996                SegmentType::UnaryExpression,
997                children,
998            )));
999        }
1000        self.parse_comparison_expression(ctx)
1001    }
1002
1003    fn parse_comparison_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
1004        let left = self.parse_addition_expression(ctx)?;
1005
1006        let save = ctx.save();
1007        let trivia = eat_trivia_segments(ctx);
1008
1009        // IS [NOT] NULL
1010        if ctx.peek_keyword("IS") {
1011            let is_kw = ctx.advance().unwrap();
1012            let mut children = vec![left];
1013            children.extend(trivia);
1014            children.push(token_segment(is_kw, SegmentType::Keyword));
1015            children.extend(eat_trivia_segments(ctx));
1016            if ctx.peek_keyword("NOT") {
1017                let not_kw = ctx.advance().unwrap();
1018                children.push(token_segment(not_kw, SegmentType::Keyword));
1019                children.extend(eat_trivia_segments(ctx));
1020            }
1021            if ctx.peek_keyword("NULL") {
1022                let null_kw = ctx.advance().unwrap();
1023                children.push(token_segment(null_kw, SegmentType::Keyword));
1024            }
1025            return Some(Segment::Node(NodeSegment::new(
1026                SegmentType::IsNullExpression,
1027                children,
1028            )));
1029        }
1030
1031        // [NOT] IN (...)
1032        if ctx.peek_keyword("IN") {
1033            let in_kw = ctx.advance().unwrap();
1034            let mut children = vec![left];
1035            children.extend(trivia);
1036            children.push(token_segment(in_kw, SegmentType::Keyword));
1037            children.extend(eat_trivia_segments(ctx));
1038            if ctx.peek_kind() == Some(TokenKind::LParen) {
1039                if let Some(list) = self.parse_paren_block(ctx) {
1040                    children.push(list);
1041                }
1042            }
1043            return Some(Segment::Node(NodeSegment::new(
1044                SegmentType::InExpression,
1045                children,
1046            )));
1047        }
1048
1049        // NOT IN / NOT BETWEEN / NOT LIKE
1050        if ctx.peek_keyword("NOT") {
1051            let save_not = ctx.save();
1052            let not_kw = ctx.advance().unwrap();
1053            let not_trivia = eat_trivia_segments(ctx);
1054
1055            if ctx.peek_keyword("IN") {
1056                let in_kw = ctx.advance().unwrap();
1057                let mut children = vec![left];
1058                children.extend(trivia);
1059                children.push(token_segment(not_kw, SegmentType::Keyword));
1060                children.extend(not_trivia);
1061                children.push(token_segment(in_kw, SegmentType::Keyword));
1062                children.extend(eat_trivia_segments(ctx));
1063                if ctx.peek_kind() == Some(TokenKind::LParen) {
1064                    if let Some(list) = self.parse_paren_block(ctx) {
1065                        children.push(list);
1066                    }
1067                }
1068                return Some(Segment::Node(NodeSegment::new(
1069                    SegmentType::InExpression,
1070                    children,
1071                )));
1072            }
1073            if ctx.peek_keyword("BETWEEN") {
1074                let kw = ctx.advance().unwrap();
1075                let mut children = vec![left];
1076                children.extend(trivia);
1077                children.push(token_segment(not_kw, SegmentType::Keyword));
1078                children.extend(not_trivia);
1079                children.push(token_segment(kw, SegmentType::Keyword));
1080                children.extend(eat_trivia_segments(ctx));
1081                if let Some(lo) = self.parse_addition_expression(ctx) {
1082                    children.push(lo);
1083                }
1084                children.extend(eat_trivia_segments(ctx));
1085                if let Some(and_kw) = ctx.eat_keyword("AND") {
1086                    children.push(token_segment(and_kw, SegmentType::Keyword));
1087                }
1088                children.extend(eat_trivia_segments(ctx));
1089                if let Some(hi) = self.parse_addition_expression(ctx) {
1090                    children.push(hi);
1091                }
1092                return Some(Segment::Node(NodeSegment::new(
1093                    SegmentType::BetweenExpression,
1094                    children,
1095                )));
1096            }
1097            if ctx.peek_keyword("LIKE") || ctx.peek_keyword("ILIKE") {
1098                let kw = ctx.advance().unwrap();
1099                let mut children = vec![left];
1100                children.extend(trivia);
1101                children.push(token_segment(not_kw, SegmentType::Keyword));
1102                children.extend(not_trivia);
1103                children.push(token_segment(kw, SegmentType::Keyword));
1104                children.extend(eat_trivia_segments(ctx));
1105                if let Some(pattern) = self.parse_addition_expression(ctx) {
1106                    children.push(pattern);
1107                }
1108                return Some(Segment::Node(NodeSegment::new(
1109                    SegmentType::LikeExpression,
1110                    children,
1111                )));
1112            }
1113
1114            // NOT was consumed but wasn't NOT IN/BETWEEN/LIKE — restore
1115            ctx.restore(save_not);
1116            ctx.restore(save);
1117            return Some(left);
1118        }
1119
1120        // BETWEEN ... AND ...
1121        if ctx.peek_keyword("BETWEEN") {
1122            let kw = ctx.advance().unwrap();
1123            let mut children = vec![left];
1124            children.extend(trivia);
1125            children.push(token_segment(kw, SegmentType::Keyword));
1126            children.extend(eat_trivia_segments(ctx));
1127            if let Some(lo) = self.parse_addition_expression(ctx) {
1128                children.push(lo);
1129            }
1130            children.extend(eat_trivia_segments(ctx));
1131            if let Some(and_kw) = ctx.eat_keyword("AND") {
1132                children.push(token_segment(and_kw, SegmentType::Keyword));
1133            }
1134            children.extend(eat_trivia_segments(ctx));
1135            if let Some(hi) = self.parse_addition_expression(ctx) {
1136                children.push(hi);
1137            }
1138            return Some(Segment::Node(NodeSegment::new(
1139                SegmentType::BetweenExpression,
1140                children,
1141            )));
1142        }
1143
1144        // LIKE / ILIKE
1145        if ctx.peek_keyword("LIKE") || ctx.peek_keyword("ILIKE") {
1146            let kw = ctx.advance().unwrap();
1147            let mut children = vec![left];
1148            children.extend(trivia);
1149            children.push(token_segment(kw, SegmentType::Keyword));
1150            children.extend(eat_trivia_segments(ctx));
1151            if let Some(pattern) = self.parse_addition_expression(ctx) {
1152                children.push(pattern);
1153            }
1154            return Some(Segment::Node(NodeSegment::new(
1155                SegmentType::LikeExpression,
1156                children,
1157            )));
1158        }
1159
1160        // Comparison operators: = <> != < > <= >=
1161        if let Some(kind) = ctx.peek_kind() {
1162            if matches!(
1163                kind,
1164                TokenKind::Eq
1165                    | TokenKind::Neq
1166                    | TokenKind::Lt
1167                    | TokenKind::Gt
1168                    | TokenKind::LtEq
1169                    | TokenKind::GtEq
1170            ) {
1171                let op = ctx.advance().unwrap();
1172                let mut children = vec![left];
1173                children.extend(trivia);
1174                children.push(token_segment(op, SegmentType::ComparisonOperator));
1175                children.extend(eat_trivia_segments(ctx));
1176                if let Some(right) = self.parse_addition_expression(ctx) {
1177                    children.push(right);
1178                }
1179                return Some(Segment::Node(NodeSegment::new(
1180                    SegmentType::BinaryExpression,
1181                    children,
1182                )));
1183            }
1184        }
1185
1186        ctx.restore(save);
1187        Some(left)
1188    }
1189
1190    fn parse_addition_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
1191        let mut left = self.parse_multiplication_expression(ctx)?;
1192        loop {
1193            let save = ctx.save();
1194            let trivia = eat_trivia_segments(ctx);
1195            if let Some(kind) = ctx.peek_kind() {
1196                if matches!(kind, TokenKind::Plus | TokenKind::Minus | TokenKind::Concat) {
1197                    let op = ctx.advance().unwrap();
1198                    let mut children = vec![left];
1199                    children.extend(trivia);
1200                    children.push(token_segment(op, SegmentType::ArithmeticOperator));
1201                    children.extend(eat_trivia_segments(ctx));
1202                    if let Some(right) = self.parse_multiplication_expression(ctx) {
1203                        children.push(right);
1204                    }
1205                    left = Segment::Node(NodeSegment::new(SegmentType::BinaryExpression, children));
1206                    continue;
1207                }
1208            }
1209            ctx.restore(save);
1210            break;
1211        }
1212        Some(left)
1213    }
1214
1215    fn parse_multiplication_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
1216        let mut left = self.parse_unary_expression(ctx)?;
1217        loop {
1218            let save = ctx.save();
1219            let trivia = eat_trivia_segments(ctx);
1220            if let Some(kind) = ctx.peek_kind() {
1221                if matches!(
1222                    kind,
1223                    TokenKind::Star | TokenKind::Slash | TokenKind::Percent
1224                ) {
1225                    let op = ctx.advance().unwrap();
1226                    let mut children = vec![left];
1227                    children.extend(trivia);
1228                    children.push(token_segment(op, SegmentType::ArithmeticOperator));
1229                    children.extend(eat_trivia_segments(ctx));
1230                    if let Some(right) = self.parse_unary_expression(ctx) {
1231                        children.push(right);
1232                    }
1233                    left = Segment::Node(NodeSegment::new(SegmentType::BinaryExpression, children));
1234                    continue;
1235                }
1236            }
1237            ctx.restore(save);
1238            break;
1239        }
1240        Some(left)
1241    }
1242
1243    fn parse_unary_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
1244        if let Some(kind) = ctx.peek_kind() {
1245            if matches!(kind, TokenKind::Plus | TokenKind::Minus) {
1246                let op = ctx.advance().unwrap();
1247                let mut children = vec![token_segment(op, SegmentType::ArithmeticOperator)];
1248                children.extend(eat_trivia_segments(ctx));
1249                if let Some(expr) = self.parse_primary_expression(ctx) {
1250                    children.push(expr);
1251                }
1252                return Some(Segment::Node(NodeSegment::new(
1253                    SegmentType::UnaryExpression,
1254                    children,
1255                )));
1256            }
1257        }
1258        self.parse_primary_expression(ctx)
1259    }
1260
1261    fn parse_primary_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
1262        match ctx.peek_kind()? {
1263            // Parenthesized expression or subquery
1264            TokenKind::LParen => {
1265                // Check if it's a subquery
1266                let save = ctx.save();
1267                if let Some(subq) = self.parse_paren_subquery(ctx) {
1268                    return Some(subq);
1269                }
1270                ctx.restore(save);
1271                self.parse_paren_expression(ctx)
1272            }
1273
1274            // Number literal
1275            TokenKind::NumberLiteral => {
1276                let token = ctx.advance().unwrap();
1277                Some(token_segment(token, SegmentType::NumericLiteral))
1278            }
1279
1280            // String literal
1281            TokenKind::StringLiteral => {
1282                let token = ctx.advance().unwrap();
1283                Some(token_segment(token, SegmentType::StringLiteral))
1284            }
1285
1286            // Star (e.g. SELECT *)
1287            TokenKind::Star => {
1288                let token = ctx.advance().unwrap();
1289                Some(token_segment(token, SegmentType::Star))
1290            }
1291
1292            // Placeholder
1293            TokenKind::Placeholder => {
1294                let token = ctx.advance().unwrap();
1295                Some(token_segment(token, SegmentType::Literal))
1296            }
1297
1298            // Quoted identifier
1299            TokenKind::QuotedIdentifier => {
1300                let token = ctx.advance().unwrap();
1301                Some(token_segment(token, SegmentType::QuotedIdentifier))
1302            }
1303
1304            // Word: keyword, function call, column ref, etc.
1305            TokenKind::Word => {
1306                let text = &ctx.peek().unwrap().text;
1307
1308                if text.eq_ignore_ascii_case("CASE") {
1309                    return self.parse_case_expression(ctx);
1310                }
1311                if text.eq_ignore_ascii_case("EXISTS") {
1312                    return self.parse_exists_expression(ctx);
1313                }
1314                if text.eq_ignore_ascii_case("CAST") {
1315                    return self.parse_cast_expression(ctx);
1316                }
1317                if text.eq_ignore_ascii_case("TRUE") || text.eq_ignore_ascii_case("FALSE") {
1318                    let token = ctx.advance().unwrap();
1319                    return Some(token_segment(token, SegmentType::BooleanLiteral));
1320                }
1321                if text.eq_ignore_ascii_case("NULL") {
1322                    let token = ctx.advance().unwrap();
1323                    return Some(token_segment(token, SegmentType::NullLiteral));
1324                }
1325
1326                self.parse_name_or_function(ctx)
1327            }
1328
1329            // @ variable (SQL Server)
1330            TokenKind::AtSign => {
1331                let token = ctx.advance().unwrap();
1332                Some(token_segment(token, SegmentType::Identifier))
1333            }
1334
1335            _ => None,
1336        }
1337    }
1338
1339    fn parse_paren_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
1340        let mut children = Vec::new();
1341        let lp = ctx.eat_kind(TokenKind::LParen)?;
1342        children.push(token_segment(lp, SegmentType::LParen));
1343        children.extend(eat_trivia_segments(ctx));
1344
1345        if let Some(expr) = self.parse_expression(ctx) {
1346            children.push(expr);
1347        }
1348
1349        children.extend(eat_trivia_segments(ctx));
1350        if let Some(rp) = ctx.eat_kind(TokenKind::RParen) {
1351            children.push(token_segment(rp, SegmentType::RParen));
1352        }
1353
1354        Some(Segment::Node(NodeSegment::new(
1355            SegmentType::ParenExpression,
1356            children,
1357        )))
1358    }
1359
1360    fn parse_paren_subquery(&self, ctx: &mut ParseContext) -> Option<Segment> {
1361        let save = ctx.save();
1362        let mut children = Vec::new();
1363        let lp = ctx.eat_kind(TokenKind::LParen)?;
1364        children.push(token_segment(lp, SegmentType::LParen));
1365        children.extend(eat_trivia_segments(ctx));
1366
1367        // Check if it's a SELECT or WITH inside
1368        if !ctx.peek_keyword("SELECT") && !ctx.peek_keyword("WITH") {
1369            ctx.restore(save);
1370            return None;
1371        }
1372
1373        if let Some(sel) = self.parse_select_statement(ctx) {
1374            children.push(sel);
1375        } else {
1376            ctx.restore(save);
1377            return None;
1378        }
1379
1380        children.extend(eat_trivia_segments(ctx));
1381        if let Some(rp) = ctx.eat_kind(TokenKind::RParen) {
1382            children.push(token_segment(rp, SegmentType::RParen));
1383        }
1384
1385        Some(Segment::Node(NodeSegment::new(
1386            SegmentType::Subquery,
1387            children,
1388        )))
1389    }
1390
1391    fn parse_case_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
1392        let mut children = Vec::new();
1393        let case_kw = ctx.eat_keyword("CASE")?;
1394        children.push(token_segment(case_kw, SegmentType::Keyword));
1395        children.extend(eat_trivia_segments(ctx));
1396
1397        // Simple CASE: CASE expr WHEN ...
1398        // Searched CASE: CASE WHEN ...
1399        if !ctx.peek_keyword("WHEN") {
1400            if let Some(expr) = self.parse_expression(ctx) {
1401                children.push(expr);
1402                children.extend(eat_trivia_segments(ctx));
1403            }
1404        }
1405
1406        // WHEN clauses
1407        while ctx.peek_keyword("WHEN") {
1408            if let Some(when) = self.parse_when_clause(ctx) {
1409                children.push(when);
1410                children.extend(eat_trivia_segments(ctx));
1411            }
1412        }
1413
1414        // ELSE clause
1415        if ctx.peek_keyword("ELSE") {
1416            let mut else_children = Vec::new();
1417            let kw = ctx.advance().unwrap();
1418            else_children.push(token_segment(kw, SegmentType::Keyword));
1419            else_children.extend(eat_trivia_segments(ctx));
1420            if let Some(expr) = self.parse_expression(ctx) {
1421                else_children.push(expr);
1422            }
1423            children.push(Segment::Node(NodeSegment::new(
1424                SegmentType::ElseClause,
1425                else_children,
1426            )));
1427            children.extend(eat_trivia_segments(ctx));
1428        }
1429
1430        // END
1431        if let Some(end_kw) = ctx.eat_keyword("END") {
1432            children.push(token_segment(end_kw, SegmentType::Keyword));
1433        }
1434
1435        Some(Segment::Node(NodeSegment::new(
1436            SegmentType::CaseExpression,
1437            children,
1438        )))
1439    }
1440
1441    fn parse_when_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
1442        let mut children = Vec::new();
1443        let kw = ctx.eat_keyword("WHEN")?;
1444        children.push(token_segment(kw, SegmentType::Keyword));
1445        children.extend(eat_trivia_segments(ctx));
1446
1447        if let Some(cond) = self.parse_expression(ctx) {
1448            children.push(cond);
1449        }
1450        children.extend(eat_trivia_segments(ctx));
1451
1452        if let Some(then_kw) = ctx.eat_keyword("THEN") {
1453            children.push(token_segment(then_kw, SegmentType::Keyword));
1454        }
1455        children.extend(eat_trivia_segments(ctx));
1456
1457        if let Some(result) = self.parse_expression(ctx) {
1458            children.push(result);
1459        }
1460
1461        Some(Segment::Node(NodeSegment::new(
1462            SegmentType::WhenClause,
1463            children,
1464        )))
1465    }
1466
1467    fn parse_exists_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
1468        let mut children = Vec::new();
1469        let kw = ctx.eat_keyword("EXISTS")?;
1470        children.push(token_segment(kw, SegmentType::Keyword));
1471        children.extend(eat_trivia_segments(ctx));
1472
1473        if let Some(subq) = self.parse_paren_subquery(ctx) {
1474            children.push(subq);
1475        }
1476
1477        Some(Segment::Node(NodeSegment::new(
1478            SegmentType::ExistsExpression,
1479            children,
1480        )))
1481    }
1482
1483    fn parse_cast_expression(&self, ctx: &mut ParseContext) -> Option<Segment> {
1484        let mut children = Vec::new();
1485        let kw = ctx.eat_keyword("CAST")?;
1486        children.push(token_segment(kw, SegmentType::Keyword));
1487        children.extend(eat_trivia_segments(ctx));
1488
1489        let lp = ctx.eat_kind(TokenKind::LParen)?;
1490        children.push(token_segment(lp, SegmentType::LParen));
1491        children.extend(eat_trivia_segments(ctx));
1492
1493        if let Some(expr) = self.parse_expression(ctx) {
1494            children.push(expr);
1495        }
1496        children.extend(eat_trivia_segments(ctx));
1497
1498        if let Some(as_kw) = ctx.eat_keyword("AS") {
1499            children.push(token_segment(as_kw, SegmentType::Keyword));
1500        }
1501        children.extend(eat_trivia_segments(ctx));
1502
1503        // Data type
1504        if let Some(dt) = self.parse_data_type(ctx) {
1505            children.push(dt);
1506        }
1507        children.extend(eat_trivia_segments(ctx));
1508
1509        if let Some(rp) = ctx.eat_kind(TokenKind::RParen) {
1510            children.push(token_segment(rp, SegmentType::RParen));
1511        }
1512
1513        Some(Segment::Node(NodeSegment::new(
1514            SegmentType::CastExpression,
1515            children,
1516        )))
1517    }
1518
1519    fn parse_data_type(&self, ctx: &mut ParseContext) -> Option<Segment> {
1520        let mut children = Vec::new();
1521
1522        // Type name (may be multi-word like "DOUBLE PRECISION", "CHARACTER VARYING")
1523        let word = ctx.eat_kind(TokenKind::Word)?;
1524        children.push(token_segment(word, SegmentType::Keyword));
1525
1526        // Additional type words
1527        loop {
1528            let save = ctx.save();
1529            let trivia = eat_trivia_segments(ctx);
1530            if let Some(t) = ctx.peek() {
1531                if t.kind == TokenKind::Word && !is_clause_keyword(&t.text) {
1532                    children.extend(trivia);
1533                    let w = ctx.advance().unwrap();
1534                    children.push(token_segment(w, SegmentType::Keyword));
1535                    continue;
1536                }
1537            }
1538            ctx.restore(save);
1539            break;
1540        }
1541
1542        // Optional (precision, scale)
1543        let save = ctx.save();
1544        let trivia = eat_trivia_segments(ctx);
1545        if ctx.peek_kind() == Some(TokenKind::LParen) {
1546            children.extend(trivia);
1547            if let Some(params) = self.parse_paren_block(ctx) {
1548                children.push(params);
1549            }
1550        } else {
1551            ctx.restore(save);
1552        }
1553
1554        Some(Segment::Node(NodeSegment::new(
1555            SegmentType::DataType,
1556            children,
1557        )))
1558    }
1559
1560    // ── Identifiers & names ──────────────────────────────────────
1561
1562    fn parse_identifier(&self, ctx: &mut ParseContext) -> Option<Segment> {
1563        match ctx.peek_kind()? {
1564            TokenKind::Word => {
1565                let token = ctx.advance().unwrap();
1566                Some(token_segment(token, SegmentType::Identifier))
1567            }
1568            TokenKind::QuotedIdentifier => {
1569                let token = ctx.advance().unwrap();
1570                Some(token_segment(token, SegmentType::QuotedIdentifier))
1571            }
1572            // @variable / @@variable (TSQL table variables, system variables)
1573            TokenKind::AtSign => {
1574                let token = ctx.advance().unwrap();
1575                Some(token_segment(token, SegmentType::Identifier))
1576            }
1577            _ => None,
1578        }
1579    }
1580
1581    /// Parse a possibly qualified name: a, a.b, a.b.c
1582    fn parse_qualified_name(&self, ctx: &mut ParseContext) -> Option<Segment> {
1583        let first = self.parse_identifier(ctx)?;
1584
1585        let save = ctx.save();
1586        if ctx.peek_kind() == Some(TokenKind::Dot) {
1587            let mut children = vec![first];
1588            while ctx.peek_kind() == Some(TokenKind::Dot) {
1589                let dot = ctx.advance().unwrap();
1590                children.push(token_segment(dot, SegmentType::Dot));
1591                if let Some(part) = self.parse_identifier(ctx) {
1592                    children.push(part);
1593                } else {
1594                    // Star: schema.table.*
1595                    if ctx.peek_kind() == Some(TokenKind::Star) {
1596                        let star = ctx.advance().unwrap();
1597                        children.push(token_segment(star, SegmentType::Star));
1598                    }
1599                    break;
1600                }
1601            }
1602            Some(Segment::Node(NodeSegment::new(
1603                SegmentType::ColumnRef,
1604                children,
1605            )))
1606        } else {
1607            ctx.restore(save);
1608            Some(first)
1609        }
1610    }
1611
1612    fn parse_name_or_function(&self, ctx: &mut ParseContext) -> Option<Segment> {
1613        let name = self.parse_qualified_name(ctx)?;
1614
1615        // Check for function call: name(...)
1616        if ctx.peek_kind() == Some(TokenKind::LParen) {
1617            let mut children = vec![name];
1618            if let Some(args) = self.parse_paren_block(ctx) {
1619                children.push(args);
1620            }
1621            let func = Segment::Node(NodeSegment::new(SegmentType::FunctionCall, children));
1622
1623            // Check for OVER clause (window function)
1624            let save = ctx.save();
1625            let trivia = eat_trivia_segments(ctx);
1626            if ctx.peek_keyword("OVER") {
1627                let mut win_children = vec![func];
1628                win_children.extend(trivia);
1629                if let Some(over) = self.parse_over_clause(ctx) {
1630                    win_children.push(over);
1631                }
1632                return Some(Segment::Node(NodeSegment::new(
1633                    SegmentType::WindowExpression,
1634                    win_children,
1635                )));
1636            }
1637            ctx.restore(save);
1638
1639            return Some(func);
1640        }
1641
1642        Some(name)
1643    }
1644
1645    /// Parse OVER clause: `OVER (PARTITION BY ... ORDER BY ... ROWS/RANGE ...)`
1646    /// or `OVER window_name`
1647    fn parse_over_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
1648        let mut children = Vec::new();
1649        let over_kw = ctx.eat_keyword("OVER")?;
1650        children.push(token_segment(over_kw, SegmentType::Keyword));
1651        children.extend(eat_trivia_segments(ctx));
1652
1653        // OVER window_name (named window reference, no parens)
1654        if ctx.peek_kind() != Some(TokenKind::LParen) {
1655            if let Some(name) = self.parse_identifier(ctx) {
1656                children.push(name);
1657            }
1658            return Some(Segment::Node(NodeSegment::new(
1659                SegmentType::OverClause,
1660                children,
1661            )));
1662        }
1663
1664        // OVER ( ... )
1665        let lp = ctx.eat_kind(TokenKind::LParen)?;
1666        children.push(token_segment(lp, SegmentType::LParen));
1667        children.extend(eat_trivia_segments(ctx));
1668
1669        // PARTITION BY ...
1670        if ctx.peek_keyword("PARTITION") {
1671            if let Some(pb) = self.parse_partition_by_clause(ctx) {
1672                children.push(pb);
1673                children.extend(eat_trivia_segments(ctx));
1674            }
1675        }
1676
1677        // ORDER BY ...
1678        if ctx.peek_keywords(&["ORDER", "BY"]) {
1679            if let Some(ob) = self.parse_window_order_by(ctx) {
1680                children.push(ob);
1681                children.extend(eat_trivia_segments(ctx));
1682            }
1683        }
1684
1685        // Window frame: ROWS / RANGE / GROUPS
1686        if ctx.peek_keyword("ROWS") || ctx.peek_keyword("RANGE") || ctx.peek_keyword("GROUPS") {
1687            if let Some(frame) = self.parse_window_frame_clause(ctx) {
1688                children.push(frame);
1689                children.extend(eat_trivia_segments(ctx));
1690            }
1691        }
1692
1693        if let Some(rp) = ctx.eat_kind(TokenKind::RParen) {
1694            children.push(token_segment(rp, SegmentType::RParen));
1695        }
1696
1697        Some(Segment::Node(NodeSegment::new(
1698            SegmentType::OverClause,
1699            children,
1700        )))
1701    }
1702
1703    /// Parse PARTITION BY expr, expr, ...
1704    fn parse_partition_by_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
1705        let mut children = Vec::new();
1706        let part_kw = ctx.eat_keyword("PARTITION")?;
1707        children.push(token_segment(part_kw, SegmentType::Keyword));
1708        children.extend(eat_trivia_segments(ctx));
1709
1710        if let Some(by_kw) = ctx.eat_keyword("BY") {
1711            children.push(token_segment(by_kw, SegmentType::Keyword));
1712        }
1713        children.extend(eat_trivia_segments(ctx));
1714
1715        // Comma-separated expressions
1716        parse_comma_separated(ctx, &mut children, |c| self.parse_expression(c));
1717
1718        Some(Segment::Node(NodeSegment::new(
1719            SegmentType::PartitionByClause,
1720            children,
1721        )))
1722    }
1723
1724    /// Parse ORDER BY inside a window spec (reuses expression parsing).
1725    fn parse_window_order_by(&self, ctx: &mut ParseContext) -> Option<Segment> {
1726        // Delegate to the existing ORDER BY parser
1727        self.parse_order_by_clause(ctx)
1728    }
1729
1730    /// Parse window frame: ROWS/RANGE/GROUPS frame_spec
1731    fn parse_window_frame_clause(&self, ctx: &mut ParseContext) -> Option<Segment> {
1732        let mut children = Vec::new();
1733
1734        // ROWS | RANGE | GROUPS
1735        let frame_kw = ctx.advance()?;
1736        children.push(token_segment(frame_kw, SegmentType::Keyword));
1737        children.extend(eat_trivia_segments(ctx));
1738
1739        // BETWEEN ... AND ... or single bound
1740        if ctx.peek_keyword("BETWEEN") {
1741            let bw_kw = ctx.advance().unwrap();
1742            children.push(token_segment(bw_kw, SegmentType::Keyword));
1743            children.extend(eat_trivia_segments(ctx));
1744
1745            // start bound
1746            eat_frame_bound(ctx, &mut children);
1747            children.extend(eat_trivia_segments(ctx));
1748
1749            // AND
1750            if let Some(and_kw) = ctx.eat_keyword("AND") {
1751                children.push(token_segment(and_kw, SegmentType::Keyword));
1752                children.extend(eat_trivia_segments(ctx));
1753            }
1754
1755            // end bound
1756            eat_frame_bound(ctx, &mut children);
1757        } else {
1758            // Single bound (e.g. ROWS UNBOUNDED PRECEDING)
1759            eat_frame_bound(ctx, &mut children);
1760        }
1761
1762        Some(Segment::Node(NodeSegment::new(
1763            SegmentType::WindowFrameClause,
1764            children,
1765        )))
1766    }
1767
1768    // ── Simple statement ─────────────────────────────────────────
1769
1770    /// Parse a simple statement (USE, TRUNCATE, etc.) by consuming until end.
1771    fn parse_simple_statement(&self, ctx: &mut ParseContext) -> Option<Segment> {
1772        let mut children = Vec::new();
1773        let kw = ctx.advance()?;
1774        children.push(token_segment(kw, SegmentType::Keyword));
1775        children.extend(eat_trivia_segments(ctx));
1776        self.consume_until_statement_end(ctx, &mut children);
1777        Some(Segment::Node(NodeSegment::new(
1778            SegmentType::Statement,
1779            children,
1780        )))
1781    }
1782
1783    // ── Statement boundary helpers ──────────────────────────────
1784
1785    /// Check if current token looks like the start of a new statement.
1786    fn peek_statement_start(&self, ctx: &ParseContext) -> bool {
1787        if let Some(t) = ctx.peek_non_trivia() {
1788            if t.kind == TokenKind::Word {
1789                return self
1790                    .statement_keywords()
1791                    .iter()
1792                    .any(|kw| t.text.eq_ignore_ascii_case(kw));
1793            }
1794        }
1795        false
1796    }
1797
1798    /// Consume tokens until semicolon, EOF, or start of new statement.
1799    /// Consume tokens until semicolon, EOF, or start of a new statement.
1800    /// Tracks paren depth so that keywords inside subqueries (e.g. `SELECT`
1801    /// within `(SELECT ...)`) do not cause premature termination.
1802    fn consume_until_statement_end(&self, ctx: &mut ParseContext, children: &mut Vec<Segment>) {
1803        let mut paren_depth = 0u32;
1804        while !ctx.at_eof() {
1805            match ctx.peek_kind() {
1806                Some(TokenKind::Semicolon) if paren_depth == 0 => break,
1807                Some(TokenKind::LParen) => {
1808                    paren_depth += 1;
1809                    let token = ctx.advance().unwrap();
1810                    children.push(any_token_segment(token));
1811                }
1812                Some(TokenKind::RParen) => {
1813                    paren_depth = paren_depth.saturating_sub(1);
1814                    let token = ctx.advance().unwrap();
1815                    children.push(any_token_segment(token));
1816                }
1817                _ => {
1818                    if paren_depth == 0 && self.peek_statement_start(ctx) {
1819                        break;
1820                    }
1821                    let token = ctx.advance().unwrap();
1822                    children.push(any_token_segment(token));
1823                }
1824            }
1825        }
1826    }
1827
1828    // ── Utility parsing ──────────────────────────────────────────
1829
1830    /// Parse parenthesized content as a simple block.
1831    fn parse_paren_block(&self, ctx: &mut ParseContext) -> Option<Segment> {
1832        let mut children = Vec::new();
1833        let lp = ctx.eat_kind(TokenKind::LParen)?;
1834        children.push(token_segment(lp, SegmentType::LParen));
1835
1836        let mut depth = 1u32;
1837        while depth > 0 && !ctx.at_eof() {
1838            match ctx.peek_kind() {
1839                Some(TokenKind::LParen) => {
1840                    depth += 1;
1841                    let token = ctx.advance().unwrap();
1842                    children.push(any_token_segment(token));
1843                }
1844                Some(TokenKind::RParen) => {
1845                    depth -= 1;
1846                    let token = ctx.advance().unwrap();
1847                    if depth == 0 {
1848                        children.push(token_segment(token, SegmentType::RParen));
1849                    } else {
1850                        children.push(any_token_segment(token));
1851                    }
1852                }
1853                _ => {
1854                    let token = ctx.advance().unwrap();
1855                    children.push(any_token_segment(token));
1856                }
1857            }
1858        }
1859
1860        Some(Segment::Node(NodeSegment::new(
1861            SegmentType::ParenExpression,
1862            children,
1863        )))
1864    }
1865
1866    /// Consume tokens until the end of a statement.
1867    ///
1868    /// The ANSI default tracks paren and CASE/END depth, stopping at
1869    /// semicolons or EOF.  TSQL overrides this to additionally track
1870    /// BEGIN/END blocks and the GO batch separator.
1871    fn consume_until_end(&self, ctx: &mut ParseContext, children: &mut Vec<Segment>) {
1872        let mut paren_depth = 0u32;
1873        let mut case_depth = 0u32;
1874        while !ctx.at_eof() {
1875            match ctx.peek_kind() {
1876                Some(TokenKind::Semicolon) if paren_depth == 0 => break,
1877                Some(TokenKind::LParen) => {
1878                    paren_depth += 1;
1879                    let token = ctx.advance().unwrap();
1880                    children.push(any_token_segment(token));
1881                }
1882                Some(TokenKind::RParen) => {
1883                    paren_depth = paren_depth.saturating_sub(1);
1884                    let token = ctx.advance().unwrap();
1885                    children.push(any_token_segment(token));
1886                }
1887                _ => {
1888                    let t = ctx.peek().unwrap();
1889                    if t.kind == TokenKind::Word {
1890                        if t.text.eq_ignore_ascii_case("CASE") {
1891                            case_depth += 1;
1892                        } else if t.text.eq_ignore_ascii_case("END") && case_depth > 0 {
1893                            case_depth -= 1;
1894                        }
1895                    }
1896                    let token = ctx.advance().unwrap();
1897                    children.push(any_token_segment(token));
1898                }
1899            }
1900        }
1901    }
1902}
1903
1904// ── Free helper functions ────────────────────────────────────────
1905
1906pub fn token_segment(token: &Token, segment_type: SegmentType) -> Segment {
1907    Segment::Token(TokenSegment {
1908        token: token.clone(),
1909        segment_type,
1910    })
1911}
1912
1913pub fn any_token_segment(token: &Token) -> Segment {
1914    let st = match token.kind {
1915        TokenKind::Whitespace => SegmentType::Whitespace,
1916        TokenKind::Newline => SegmentType::Newline,
1917        TokenKind::LineComment => SegmentType::LineComment,
1918        TokenKind::BlockComment => SegmentType::BlockComment,
1919        TokenKind::Comma => SegmentType::Comma,
1920        TokenKind::Dot => SegmentType::Dot,
1921        TokenKind::Semicolon => SegmentType::Semicolon,
1922        TokenKind::Star => SegmentType::Star,
1923        TokenKind::LParen => SegmentType::LParen,
1924        TokenKind::RParen => SegmentType::RParen,
1925        TokenKind::NumberLiteral => SegmentType::NumericLiteral,
1926        TokenKind::StringLiteral => SegmentType::StringLiteral,
1927        TokenKind::Word => SegmentType::Keyword,
1928        TokenKind::QuotedIdentifier => SegmentType::QuotedIdentifier,
1929        _ => SegmentType::Operator,
1930    };
1931    token_segment(token, st)
1932}
1933
1934pub fn unparsable_token(token: &Token) -> Segment {
1935    Segment::Token(TokenSegment {
1936        token: token.clone(),
1937        segment_type: SegmentType::Unparsable,
1938    })
1939}
1940
1941pub fn eat_trivia_segments(ctx: &mut ParseContext) -> Vec<Segment> {
1942    ctx.eat_trivia()
1943        .into_iter()
1944        .map(any_token_segment)
1945        .collect()
1946}
1947
1948/// Parse statements until `is_end` returns true, consuming unparsable tokens as fallback.
1949pub fn parse_statement_list(
1950    grammar: &dyn Grammar,
1951    ctx: &mut ParseContext,
1952    children: &mut Vec<Segment>,
1953    is_end: impl Fn(&ParseContext) -> bool,
1954) {
1955    loop {
1956        children.extend(eat_trivia_segments(ctx));
1957        if ctx.at_eof() || is_end(ctx) {
1958            break;
1959        }
1960        if let Some(stmt) = grammar.parse_statement(ctx) {
1961            children.push(stmt);
1962        } else {
1963            children.extend(eat_trivia_segments(ctx));
1964            if !ctx.at_eof() && !is_end(ctx) {
1965                if let Some(token) = ctx.advance() {
1966                    children.push(unparsable_token(token));
1967                }
1968            }
1969        }
1970    }
1971}
1972
1973/// Parse a comma-separated list of items, appending them to `children`.
1974///
1975/// Parses the first item, then loops: save → eat trivia → comma? → parse next.
1976/// If no comma is found, restores to before the trivia and returns.
1977pub fn parse_comma_separated(
1978    ctx: &mut ParseContext,
1979    children: &mut Vec<Segment>,
1980    mut parse_one: impl FnMut(&mut ParseContext) -> Option<Segment>,
1981) {
1982    if let Some(item) = parse_one(ctx) {
1983        children.push(item);
1984    }
1985    loop {
1986        let save = ctx.save();
1987        let trivia = eat_trivia_segments(ctx);
1988        if let Some(comma) = ctx.eat_kind(TokenKind::Comma) {
1989            children.extend(trivia);
1990            children.push(token_segment(comma, SegmentType::Comma));
1991            children.extend(eat_trivia_segments(ctx));
1992            if let Some(item) = parse_one(ctx) {
1993                children.push(item);
1994            }
1995        } else {
1996            ctx.restore(save);
1997            break;
1998        }
1999    }
2000}
2001
2002fn peek_join_keyword(ctx: &ParseContext) -> bool {
2003    if let Some(t) = ctx.peek_non_trivia() {
2004        if t.kind == TokenKind::Word {
2005            return is_join_keyword(&t.text);
2006        }
2007    }
2008    false
2009}
2010
2011/// Consume a frame bound: UNBOUNDED PRECEDING/FOLLOWING, CURRENT ROW, N PRECEDING/FOLLOWING
2012fn eat_frame_bound(ctx: &mut ParseContext, children: &mut Vec<Segment>) {
2013    // CURRENT ROW
2014    if ctx.peek_keyword("CURRENT") {
2015        let kw = ctx.advance().unwrap();
2016        children.push(token_segment(kw, SegmentType::Keyword));
2017        children.extend(eat_trivia_segments(ctx));
2018        if ctx.peek_keyword("ROW") {
2019            let row_kw = ctx.advance().unwrap();
2020            children.push(token_segment(row_kw, SegmentType::Keyword));
2021        }
2022        return;
2023    }
2024
2025    // UNBOUNDED PRECEDING/FOLLOWING
2026    if ctx.peek_keyword("UNBOUNDED") {
2027        let kw = ctx.advance().unwrap();
2028        children.push(token_segment(kw, SegmentType::Keyword));
2029        children.extend(eat_trivia_segments(ctx));
2030        if ctx.peek_keyword("PRECEDING") || ctx.peek_keyword("FOLLOWING") {
2031            let dir = ctx.advance().unwrap();
2032            children.push(token_segment(dir, SegmentType::Keyword));
2033        }
2034        return;
2035    }
2036
2037    // N PRECEDING/FOLLOWING
2038    if ctx.peek_kind() == Some(TokenKind::NumberLiteral) {
2039        let num = ctx.advance().unwrap();
2040        children.push(token_segment(num, SegmentType::NumericLiteral));
2041        children.extend(eat_trivia_segments(ctx));
2042        if ctx.peek_keyword("PRECEDING") || ctx.peek_keyword("FOLLOWING") {
2043            let dir = ctx.advance().unwrap();
2044            children.push(token_segment(dir, SegmentType::Keyword));
2045        }
2046    }
2047}
2048
2049/// Sorted list of keywords that must NOT be consumed as implicit aliases.
2050const CLAUSE_KEYWORDS: &[&str] = &[
2051    "ALTER",
2052    "AND",
2053    "AS",
2054    "BEGIN",
2055    "BETWEEN",
2056    "BREAK",
2057    "CASE",
2058    "CATCH",
2059    "CLOSE",
2060    "COMMIT",
2061    "CONTINUE",
2062    "CREATE",
2063    "CROSS",
2064    "CURSOR",
2065    "DEALLOCATE",
2066    "DECLARE",
2067    "DELETE",
2068    "DROP",
2069    "ELSE",
2070    "END",
2071    "EXCEPT",
2072    "EXEC",
2073    "EXECUTE",
2074    "EXISTS",
2075    "FETCH",
2076    "FOR",
2077    "FROM",
2078    "FULL",
2079    "GO",
2080    "GOTO",
2081    "GROUP",
2082    "HAVING",
2083    "IF",
2084    "IN",
2085    "INNER",
2086    "INSERT",
2087    "INTERSECT",
2088    "INTO",
2089    "IS",
2090    "JOIN",
2091    "LEFT",
2092    "LIKE",
2093    "LIMIT",
2094    "MERGE",
2095    "NEXT",
2096    "NOT",
2097    "OFFSET",
2098    "ON",
2099    "OPEN",
2100    "OR",
2101    "ORDER",
2102    "OUTPUT",
2103    "OVER",
2104    "PARTITION",
2105    "PRINT",
2106    "RAISERROR",
2107    "RETURN",
2108    "RETURNING",
2109    "RIGHT",
2110    "ROLLBACK",
2111    "SELECT",
2112    "SET",
2113    "TABLE",
2114    "THEN",
2115    "THROW",
2116    "TRUNCATE",
2117    "TRY",
2118    "UNION",
2119    "UPDATE",
2120    "USING",
2121    "VALUES",
2122    "WHEN",
2123    "WHERE",
2124    "WHILE",
2125    "WITH",
2126];
2127
2128pub fn is_clause_keyword(word: &str) -> bool {
2129    CLAUSE_KEYWORDS
2130        .iter()
2131        .any(|kw| word.eq_ignore_ascii_case(kw))
2132}
2133
2134pub fn is_join_keyword(word: &str) -> bool {
2135    word.eq_ignore_ascii_case("JOIN")
2136        || word.eq_ignore_ascii_case("INNER")
2137        || word.eq_ignore_ascii_case("LEFT")
2138        || word.eq_ignore_ascii_case("RIGHT")
2139        || word.eq_ignore_ascii_case("FULL")
2140        || word.eq_ignore_ascii_case("CROSS")
2141}