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