1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
use std::sync::Arc;

use crate::core::dialects::base::Dialect;
use crate::core::dialects::init::DialectKind;
use crate::core::parser::grammar::anyof::{one_of, optionally_bracketed, AnyNumberOf};
use crate::core::parser::grammar::base::{Anything, Nothing, Ref};
use crate::core::parser::grammar::delimited::Delimited;
use crate::core::parser::grammar::sequence::{Bracketed, Sequence};
use crate::core::parser::parsers::TypedParser;
use crate::core::parser::segments::meta::MetaSegment;
use crate::core::parser::types::ParseMode;
use crate::dialects::ansi::NodeMatcher;
use crate::dialects::sqlite_keywords::{RESERVED_KEYWORDS, UNRESERVED_KEYWORDS};
use crate::dialects::SyntaxKind;
use crate::helpers::{Config, ToMatchable};
use crate::vec_of_erased;

pub fn dialect() -> Dialect {
    raw_dialect().config(|dialect| dialect.expand())
}

pub fn raw_dialect() -> Dialect {
    let sqlite_dialect = super::ansi::raw_dialect();
    let mut sqlite_dialect = sqlite_dialect;
    sqlite_dialect.name = DialectKind::Sqlite;

    sqlite_dialect.sets_mut("reserved_keywords").clear();
    sqlite_dialect.sets_mut("reserved_keywords").extend(RESERVED_KEYWORDS);
    sqlite_dialect.sets_mut("unreserved_keywords").clear();
    sqlite_dialect.sets_mut("unreserved_keywords").extend(UNRESERVED_KEYWORDS);

    sqlite_dialect.add([
        (
            "BooleanBinaryOperatorGrammar".into(),
            one_of(vec_of_erased![
                Ref::new("AndOperatorGrammar"),
                Ref::new("OrOperatorGrammar"),
                Ref::keyword("REGEXP")
            ])
            .to_matchable()
            .into(),
        ),
        (
            "PrimaryKeyGrammar".into(),
            Sequence::new(vec_of_erased![
                Ref::keyword("PRIMARY"),
                Ref::keyword("KEY"),
                Sequence::new(vec_of_erased![Ref::keyword("AUTOINCREMENT")]).config(|config| {
                    config.optional();
                })
            ])
            .to_matchable()
            .into(),
        ),
        ("TemporaryTransientGrammar".into(), Ref::new("TemporaryGrammar").to_matchable().into()),
        (
            "DateTimeLiteralGrammar".into(),
            Sequence::new(vec_of_erased![
                one_of(vec_of_erased![Ref::keyword("DATE"), Ref::keyword("DATETIME")]),
                TypedParser::new(SyntaxKind::SingleQuote, SyntaxKind::DateConstructorLiteral)
            ])
            .to_matchable()
            .into(),
        ),
        (
            "BaseExpressionElementGrammar".into(),
            one_of(vec_of_erased![
                Ref::new("LiteralGrammar"),
                Ref::new("BareFunctionSegment"),
                Ref::new("FunctionSegment"),
                Ref::new("ColumnReferenceSegment"),
                Ref::new("ExpressionSegment"),
                Sequence::new(vec_of_erased![
                    Ref::new("DatatypeSegment"),
                    Ref::new("LiteralGrammar")
                ])
            ])
            .to_matchable()
            .into(),
        ),
        ("AutoIncrementGrammar".into(), Nothing::new().to_matchable().into()),
        ("CommentClauseSegment".into(), Nothing::new().to_matchable().into()),
        ("IntervalExpressionSegment".into(), Nothing::new().to_matchable().into()),
        ("TimeZoneGrammar".into(), Nothing::new().to_matchable().into()),
        ("FetchClauseSegment".into(), Nothing::new().to_matchable().into()),
        ("TrimParametersGrammar".into(), Nothing::new().to_matchable().into()),
        (
            "LikeGrammar".into(),
            Sequence::new(vec_of_erased![Ref::keyword("LIKE")]).to_matchable().into(),
        ),
        ("OverlapsClauseSegment".into(), Nothing::new().to_matchable().into()),
        ("MLTableExpressionSegment".into(), Nothing::new().to_matchable().into()),
        ("MergeIntoLiteralGrammar".into(), Nothing::new().to_matchable().into()),
        ("SamplingExpressionSegment".into(), Nothing::new().to_matchable().into()),
        (
            "OrderByClauseTerminators".into(),
            one_of(vec_of_erased![
                Ref::keyword("LIMIT"),
                Ref::keyword("WINDOW"),
                Ref::new("FrameClauseUnitGrammar")
            ])
            .to_matchable()
            .into(),
        ),
        (
            "WhereClauseTerminatorGrammar".into(),
            one_of(vec_of_erased![
                Ref::keyword("LIMIT"),
                Sequence::new(vec_of_erased![Ref::keyword("GROUP"), Ref::keyword("BY")]),
                Sequence::new(vec_of_erased![Ref::keyword("ORDER"), Ref::keyword("BY")]),
                Ref::keyword("WINDOW")
            ])
            .to_matchable()
            .into(),
        ),
        (
            "FromClauseTerminatorGrammar".into(),
            one_of(vec_of_erased![
                Ref::keyword("WHERE"),
                Ref::keyword("LIMIT"),
                Sequence::new(vec_of_erased![Ref::keyword("GROUP"), Ref::keyword("BY")]),
                Sequence::new(vec_of_erased![Ref::keyword("ORDER"), Ref::keyword("BY")]),
                Ref::keyword("WINDOW"),
                Ref::new("SetOperatorSegment"),
                Ref::new("WithNoSchemaBindingClauseSegment"),
                Ref::new("WithDataClauseSegment")
            ])
            .to_matchable()
            .into(),
        ),
        (
            "GroupByClauseTerminatorGrammar".into(),
            one_of(vec_of_erased![
                Sequence::new(vec_of_erased![Ref::keyword("ORDER"), Ref::keyword("BY")]),
                Ref::keyword("LIMIT"),
                Ref::keyword("HAVING"),
                Ref::keyword("WINDOW")
            ])
            .to_matchable()
            .into(),
        ),
        ("PostFunctionGrammar".into(), Ref::new("FilterClauseGrammar").to_matchable().into()),
        ("IgnoreRespectNullsGrammar".into(), Nothing::new().to_matchable().into()),
        (
            "SelectClauseTerminatorGrammar".into(),
            one_of(vec_of_erased![
                Ref::keyword("FROM"),
                Ref::keyword("WHERE"),
                Sequence::new(vec_of_erased![Ref::keyword("ORDER"), Ref::keyword("BY")]),
                Ref::keyword("LIMIT"),
                Ref::new("SetOperatorSegment")
            ])
            .to_matchable()
            .into(),
        ),
        (
            "FunctionContentsGrammar".into(),
            AnyNumberOf::new(vec_of_erased![
                Ref::new("ExpressionSegment"),
                Sequence::new(vec_of_erased![
                    Ref::new("ExpressionSegment"),
                    Ref::keyword("AS"),
                    Ref::new("DatatypeSegment")
                ]),
                Sequence::new(vec_of_erased![
                    Ref::new("TrimParametersGrammar"),
                    Ref::new("ExpressionSegment").optional().exclude(Ref::keyword("FROM")).config(
                        |config| {
                            config.exclude = Ref::keyword("FROM").to_matchable().into();
                        }
                    ),
                    Ref::keyword("FROM"),
                    Ref::new("ExpressionSegment")
                ]),
                Sequence::new(vec_of_erased![
                    one_of(vec_of_erased![
                        Ref::new("DatetimeUnitSegment"),
                        Ref::new("ExpressionSegment")
                    ]),
                    Ref::keyword("FROM"),
                    Ref::new("ExpressionSegment")
                ]),
                Sequence::new(vec_of_erased![
                    Ref::keyword("DISTINCT").optional(),
                    one_of(vec_of_erased![
                        Ref::new("StarSegment"),
                        Delimited::new(vec_of_erased![Ref::new(
                            "FunctionContentsExpressionGrammar"
                        )])
                    ])
                ]),
                Ref::new("OrderByClauseSegment"),
                Sequence::new(vec_of_erased![
                    one_of(vec_of_erased![
                        Ref::new("QuotedLiteralSegment"),
                        Ref::new("SingleIdentifierGrammar"),
                        Ref::new("ColumnReferenceSegment")
                    ]),
                    Ref::keyword("IN"),
                    one_of(vec_of_erased![
                        Ref::new("QuotedLiteralSegment"),
                        Ref::new("SingleIdentifierGrammar"),
                        Ref::new("ColumnReferenceSegment")
                    ])
                ]),
                Ref::new("IndexColumnDefinitionSegment")
            ])
            .to_matchable()
            .into(),
        ),
        (
            "Expression_A_Unary_Operator_Grammar".into(),
            one_of(vec_of_erased![
                Ref::new("SignedSegmentGrammar")
                    .exclude(Sequence::new(vec_of_erased![Ref::new(
                        "QualifiedNumericLiteralSegment"
                    )]))
                    .config(|config| {
                        config.exclude = Sequence::new(vec_of_erased![Ref::new(
                            "QualifiedNumericLiteralSegment"
                        )])
                        .to_matchable()
                        .into();
                    }),
                Ref::new("TildeSegment"),
                Ref::new("NotOperatorGrammar")
            ])
            .to_matchable()
            .into(),
        ),
        (
            "IsClauseGrammar".into(),
            one_of(vec_of_erased![Ref::keyword("NULL"), Ref::new("BooleanLiteralGrammar")])
                .to_matchable()
                .into(),
        ),
    ]);
    sqlite_dialect.add([(
        "SetOperatorSegment".into(),
        NodeMatcher::new(
            SyntaxKind::SetOperator,
            one_of(vec_of_erased![
                Sequence::new(vec_of_erased![
                    Ref::keyword("UNION"),
                    one_of(vec_of_erased![Ref::keyword("DISTINCT"), Ref::keyword("ALL")]).config(
                        |config| {
                            config.optional();
                        }
                    )
                ]),
                Sequence::new(vec_of_erased![
                    one_of(vec_of_erased![Ref::keyword("INTERSECT"), Ref::keyword("EXCEPT")]),
                    Ref::keyword("ALL").optional()
                ])
            ])
            .config(|config| {
                config.exclude = Sequence::new(vec_of_erased![
                    Ref::keyword("EXCEPT"),
                    Bracketed::new(vec_of_erased![Anything::new()])
                ])
                .to_matchable()
                .into();
            })
            .to_matchable(),
        )
        .to_matchable()
        .into(),
    )]);

    sqlite_dialect.replace_grammar(
        "DatatypeSegment",
        one_of(vec_of_erased![
            Sequence::new(vec_of_erased![Ref::keyword("DOUBLE"), Ref::keyword("PRECISION")]),
            Sequence::new(vec_of_erased![
                Ref::keyword("UNSIGNED"),
                Ref::keyword("BIG"),
                Ref::keyword("INT")
            ]),
            Sequence::new(vec_of_erased![
                one_of(vec_of_erased![
                    Sequence::new(vec_of_erased![
                        one_of(vec_of_erased![Ref::keyword("VARYING"), Ref::keyword("NATIVE")]),
                        one_of(vec_of_erased![Ref::keyword("CHARACTER")])
                    ]),
                    Ref::new("DatatypeIdentifierSegment")
                ]),
                Ref::new("BracketedArguments").optional()
            ])
        ])
        .to_matchable(),
    );
    sqlite_dialect.add([(
        "TableEndClauseSegment".into(),
        NodeMatcher::new(
            SyntaxKind::TableEndClauseSegment,
            Delimited::new(vec_of_erased![
                Sequence::new(vec_of_erased![Ref::keyword("WITHOUT"), Ref::keyword("ROWID")]),
                Ref::keyword("STRICT")
            ])
            .to_matchable(),
        )
        .to_matchable()
        .into(),
    )]);

    sqlite_dialect.replace_grammar(
        "ValuesClauseSegment",
        Sequence::new(vec_of_erased![
            Ref::keyword("VALUES"),
            Delimited::new(vec_of_erased![Sequence::new(vec_of_erased![
                Bracketed::new(vec_of_erased![Delimited::new(vec_of_erased![
                    Ref::keyword("DEFAULT"),
                    Ref::new("ExpressionSegment")
                ])])
                .config(|config| {
                    config.parse_mode(ParseMode::Greedy);
                })
            ])])
        ])
        .to_matchable(),
    );
    sqlite_dialect.add([
        (
            "IndexColumnDefinitionSegment".into(),
            NodeMatcher::new(
                SyntaxKind::IndexColumnDefinition,
                Sequence::new(vec_of_erased![
                    one_of(vec_of_erased![
                        Ref::new("SingleIdentifierGrammar"),
                        Ref::new("ExpressionSegment")
                    ]),
                    one_of(vec_of_erased![Ref::keyword("ASC"), Ref::keyword("DESC")]).config(
                        |config| {
                            config.optional();
                        }
                    )
                ])
                .to_matchable(),
            )
            .to_matchable()
            .into(),
        ),
        (
            "InsertStatementSegment".into(),
            NodeMatcher::new(
                SyntaxKind::InsertStatement,
                Sequence::new(vec_of_erased![
                    one_of(vec_of_erased![
                        Sequence::new(vec_of_erased![
                            Ref::keyword("INSERT"),
                            Sequence::new(vec_of_erased![
                                Ref::keyword("OR"),
                                one_of(vec_of_erased![
                                    Ref::keyword("ABORT"),
                                    Ref::keyword("FAIL"),
                                    Ref::keyword("IGNORE"),
                                    Ref::keyword("REPLACE"),
                                    Ref::keyword("ROLLBACK")
                                ])
                            ])
                            .config(|config| {
                                config.optional();
                            })
                        ]),
                        Ref::keyword("REPLACE")
                    ]),
                    Ref::keyword("INTO"),
                    Ref::new("TableReferenceSegment"),
                    Ref::new("BracketedColumnReferenceListGrammar").optional(),
                    one_of(vec_of_erased![
                        Ref::new("ValuesClauseSegment"),
                        optionally_bracketed(vec_of_erased![Ref::new("SelectableGrammar")]),
                        Ref::new("DefaultValuesGrammar")
                    ])
                ])
                .to_matchable(),
            )
            .to_matchable()
            .into(),
        ),
    ]);

    let column_constraint = dyn_clone::clone(
        &sqlite_dialect.grammar("ColumnConstraintSegment").match_grammar().unwrap(),
    )
    .copy(
        Some(vec_of_erased![
            one_of(vec_of_erased![
                Ref::keyword("DEFERRABLE"),
                Sequence::new(vec_of_erased![Ref::keyword("NOT"), Ref::keyword("DEFERRABLE")])
            ])
            .config(|config| {
                config.optional();
            }),
            one_of(vec_of_erased![
                Sequence::new(vec_of_erased![Ref::keyword("INITIALLY"), Ref::keyword("DEFERRED")]),
                Sequence::new(vec_of_erased![Ref::keyword("INITIALLY"), Ref::keyword("IMMEDIATE")])
            ])
            .config(|config| {
                config.optional();
            })
        ]),
        None,
        None,
        None,
        Vec::new(),
        false,
    );
    sqlite_dialect.replace_grammar("ColumnConstraintSegment", column_constraint);

    sqlite_dialect.replace_grammar(
        "TableConstraintSegment",
        Sequence::new(vec_of_erased![
            Sequence::new(vec_of_erased![
                Ref::keyword("CONSTRAINT"),
                Ref::new("ObjectReferenceSegment")
            ])
            .config(|config| {
                config.optional();
            }),
            one_of(vec_of_erased![
                Sequence::new(vec_of_erased![
                    Ref::keyword("CHECK"),
                    Bracketed::new(vec_of_erased![Ref::new("ExpressionSegment")])
                ]),
                Sequence::new(vec_of_erased![
                    Ref::keyword("UNIQUE"),
                    Ref::new("BracketedColumnReferenceListGrammar")
                ]),
                Sequence::new(vec_of_erased![
                    Ref::new("PrimaryKeyGrammar"),
                    Ref::new("BracketedColumnReferenceListGrammar")
                ]),
                Sequence::new(vec_of_erased![
                    Ref::new("ForeignKeyGrammar"),
                    Ref::new("BracketedColumnReferenceListGrammar"),
                    Ref::new("ReferenceDefinitionGrammar")
                ])
            ]),
            one_of(vec_of_erased![
                Ref::keyword("DEFERRABLE"),
                Sequence::new(vec_of_erased![Ref::keyword("NOT"), Ref::keyword("DEFERRABLE")])
            ])
            .config(|config| {
                config.optional();
            }),
            one_of(vec_of_erased![
                Sequence::new(vec_of_erased![Ref::keyword("INITIALLY"), Ref::keyword("DEFERRED")]),
                Sequence::new(vec_of_erased![Ref::keyword("INITIALLY"), Ref::keyword("IMMEDIATE")])
            ])
            .config(|config| {
                config.optional();
            })
        ])
        .to_matchable(),
    );

    sqlite_dialect.replace_grammar(
        "TransactionStatementSegment",
        Sequence::new(vec_of_erased![
            one_of(vec_of_erased![
                Ref::keyword("BEGIN"),
                Ref::keyword("COMMIT"),
                Ref::keyword("ROLLBACK"),
                Ref::keyword("END")
            ]),
            one_of(vec_of_erased![Ref::keyword("TRANSACTION")]).config(|config| {
                config.optional();
            }),
            Sequence::new(vec_of_erased![
                Ref::keyword("TO"),
                Ref::keyword("SAVEPOINT"),
                Ref::new("ObjectReferenceSegment")
            ])
            .config(|config| {
                config.optional();
            })
        ])
        .to_matchable(),
    );

    sqlite_dialect.add([(
        "PragmaReferenceSegment".into(),
        NodeMatcher::new(
            SyntaxKind::PragmaReference,
            sqlite_dialect.grammar("ObjectReferenceSegment").match_grammar().unwrap(),
        )
        .to_matchable()
        .into(),
    )]);

    sqlite_dialect.add([(
        "PragmaStatementSegment".into(),
        NodeMatcher::new(SyntaxKind::PragmaStatement, {
            let pragma_value = one_of(vec_of_erased![
                Ref::new("LiteralGrammar"),
                Ref::new("BooleanLiteralGrammar"),
                Ref::keyword("YES"),
                Ref::keyword("NO"),
                Ref::keyword("ON"),
                Ref::keyword("OFF"),
                Ref::keyword("NONE"),
                Ref::keyword("FULL"),
                Ref::keyword("INCREMENTAL"),
                Ref::keyword("DELETE"),
                Ref::keyword("TRUNCATE"),
                Ref::keyword("PERSIST"),
                Ref::keyword("MEMORY"),
                Ref::keyword("WAL"),
                Ref::keyword("NORMAL"),
                Ref::keyword("EXCLUSIVE"),
                Ref::keyword("FAST"),
                Ref::keyword("EXTRA"),
                Ref::keyword("DEFAULT"),
                Ref::keyword("FILE"),
                Ref::keyword("PASSIVE"),
                Ref::keyword("RESTART"),
                Ref::keyword("RESET")
            ]);

            Sequence::new(vec_of_erased![
                Ref::keyword("PRAGMA"),
                Ref::new("PragmaReferenceSegment"),
                Bracketed::new(vec_of_erased![pragma_value.clone()]).config(|config| {
                    config.optional();
                }),
                Sequence::new(vec_of_erased![
                    Ref::new("EqualsSegment"),
                    optionally_bracketed(vec_of_erased![pragma_value])
                ])
                .config(|config| {
                    config.optional();
                })
            ])
            .to_matchable()
        })
        .to_matchable()
        .into(),
    )]);

    sqlite_dialect.replace_grammar(
        "CreateTriggerStatementSegment",
        Sequence::new(vec_of_erased![
            Ref::keyword("CREATE"),
            Ref::new("TemporaryGrammar").optional(),
            Ref::keyword("TRIGGER"),
            Ref::new("IfNotExistsGrammar").optional(),
            Ref::new("TriggerReferenceSegment"),
            one_of(vec_of_erased![
                Ref::keyword("BEFORE"),
                Ref::keyword("AFTER"),
                Sequence::new(vec_of_erased![Ref::keyword("INSTEAD"), Ref::keyword("OF")])
            ])
            .config(|config| {
                config.optional();
            }),
            one_of(vec_of_erased![
                Ref::keyword("DELETE"),
                Ref::keyword("INSERT"),
                Sequence::new(vec_of_erased![
                    Ref::keyword("UPDATE"),
                    Sequence::new(vec_of_erased![
                        Ref::keyword("OF"),
                        Delimited::new(vec_of_erased![Ref::new("ColumnReferenceSegment")])
                    ])
                    .config(|config| {
                        config.optional();
                    })
                ])
            ]),
            Ref::keyword("ON"),
            Ref::new("TableReferenceSegment"),
            Sequence::new(vec_of_erased![
                Ref::keyword("FOR"),
                Ref::keyword("EACH"),
                Ref::keyword("ROW")
            ])
            .config(|config| {
                config.optional();
            }),
            Sequence::new(vec_of_erased![
                Ref::keyword("WHEN"),
                Bracketed::new(vec_of_erased![Ref::new("ExpressionSegment")])
            ])
            .config(|config| {
                config.optional();
            }),
            Ref::keyword("BEGIN"),
            Delimited::new(vec_of_erased![
                Ref::new("UpdateStatementSegment"),
                Ref::new("InsertStatementSegment"),
                Ref::new("DeleteStatementSegment"),
                Ref::new("SelectableGrammar")
            ])
            .config(|config| {
                config.delimiter(
                    AnyNumberOf::new(vec_of_erased![Ref::new("DelimiterGrammar")]).config(
                        |config| {
                            config.min_times = 1;
                        },
                    ),
                );
                config.allow_trailing = true;
            }),
            Ref::keyword("END")
        ])
        .to_matchable(),
    );
    sqlite_dialect.add([(
        "UnorderedSelectStatementSegment".into(),
        NodeMatcher::new(
            SyntaxKind::SelectStatement,
            Sequence::new(vec_of_erased![
                Ref::new("SelectClauseSegment"),
                MetaSegment::dedent(),
                Ref::new("FromClauseSegment").optional(),
                Ref::new("WhereClauseSegment").optional(),
                Ref::new("GroupByClauseSegment").optional(),
                Ref::new("HavingClauseSegment").optional(),
                Ref::new("OverlapsClauseSegment").optional(),
                Ref::new("NamedWindowSegment").optional()
            ])
            .to_matchable(),
        )
        .to_matchable()
        .into(),
    )]);

    sqlite_dialect.add([(
        "SelectStatementSegment".into(),
        NodeMatcher::new(
            SyntaxKind::SelectStatement,
            sqlite_dialect
                .grammar("UnorderedSelectStatementSegment")
                .match_grammar()
                .unwrap()
                .copy(
                    Some(vec_of_erased![
                        Ref::new("OrderByClauseSegment").optional(),
                        Ref::new("FetchClauseSegment").optional(),
                        Ref::new("LimitClauseSegment").optional(),
                        Ref::new("NamedWindowSegment").optional(),
                    ]),
                    None,
                    None,
                    None,
                    Vec::new(),
                    false,
                ),
        )
        .to_matchable()
        .into(),
    )]);

    sqlite_dialect.replace_grammar(
        "CreateIndexStatementSegment",
        Sequence::new(vec_of_erased![
            Ref::keyword("CREATE"),
            Ref::keyword("UNIQUE").optional(),
            Ref::keyword("INDEX"),
            Ref::new("IfNotExistsGrammar").optional(),
            Ref::new("IndexReferenceSegment"),
            Ref::keyword("ON"),
            Ref::new("TableReferenceSegment"),
            Sequence::new(vec_of_erased![Bracketed::new(vec_of_erased![Delimited::new(
                vec_of_erased![Ref::new("IndexColumnDefinitionSegment")]
            )])]),
            Ref::new("WhereClauseSegment").optional()
        ])
        .to_matchable(),
    );

    sqlite_dialect.replace_grammar(
        "StatementSegment",
        one_of(vec_of_erased![
            Ref::new("AlterTableStatementSegment"),
            Ref::new("CreateIndexStatementSegment"),
            Ref::new("CreateTableStatementSegment"),
            Ref::new("CreateTriggerStatementSegment"),
            Ref::new("CreateViewStatementSegment"),
            Ref::new("DeleteStatementSegment"),
            Ref::new("DropIndexStatementSegment"),
            Ref::new("DropTableStatementSegment"),
            Ref::new("DropTriggerStatementSegment"),
            Ref::new("DropViewStatementSegment"),
            Ref::new("ExplainStatementSegment"),
            Ref::new("InsertStatementSegment"),
            Ref::new("PragmaStatementSegment"),
            Ref::new("SelectableGrammar"),
            Ref::new("TransactionStatementSegment"),
            Ref::new("UpdateStatementSegment"),
            Bracketed::new(vec_of_erased![Ref::new("StatementSegment")])
        ])
        .to_matchable(),
    );

    sqlite_dialect
}

#[cfg(test)]
mod tests {
    use expect_test::expect_file;
    use itertools::Itertools;
    use rayon::iter::{IntoParallelRefIterator, ParallelIterator};

    use crate::core::config::{FluffConfig, Value};
    use crate::core::linter::linter::Linter;
    use crate::core::parser::segments::base::{ErasedSegment, Tables};
    use crate::helpers;

    fn parse_sql(linter: &Linter, sql: &str) -> ErasedSegment {
        let tables = Tables::default();
        let parsed = linter.parse_string(&tables, sql, None, None, None).unwrap();
        parsed.tree.unwrap()
    }

    #[test]
    fn base_parse_struct() {
        let linter = Linter::new(
            FluffConfig::new(
                [(
                    "core".into(),
                    Value::Map([("dialect".into(), Value::String("sqlite".into()))].into()),
                )]
                .into(),
                None,
                None,
            ),
            None,
            None,
        );

        let files =
            glob::glob("test/fixtures/dialects/sqlite/*.sql").unwrap().flatten().collect_vec();

        files.par_iter().for_each(|file| {
            let _panic = helpers::enter_panic(file.display().to_string());

            let yaml = file.with_extension("yml");
            let yaml = std::path::absolute(yaml).unwrap();

            let actual = {
                let sql = std::fs::read_to_string(file).unwrap();
                let tree = parse_sql(&linter, &sql);
                let tree = tree.to_serialised(true, true);

                serde_yaml::to_string(&tree).unwrap()
            };

            expect_file![yaml].assert_eq(&actual);
        });
    }
}