Skip to content

Commit 0d0af59

Browse files
authored
parser: add more wrapper nodes in syntax tree (#686)
1 parent 84b772d commit 0d0af59

26 files changed

+1534
-1217
lines changed

crates/squawk_ide/src/expand_selection.rs

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,27 +33,23 @@ use squawk_syntax::{
3333
ast::{self, AstToken},
3434
};
3535

36-
const ALL_LIST_KINDS: &[SyntaxKind] = &[
36+
const DELIMITED_LIST_KINDS: &[SyntaxKind] = &[
3737
SyntaxKind::ARG_LIST,
3838
SyntaxKind::ATTRIBUTE_LIST,
3939
SyntaxKind::COLUMN_LIST,
4040
SyntaxKind::CONSTRAINT_EXCLUSION_LIST,
41-
// only separated by whitespace
42-
// SyntaxKind::FUNC_OPTION_LIST,
4341
SyntaxKind::JSON_TABLE_COLUMN_LIST,
4442
SyntaxKind::OPTIONS_LIST,
4543
SyntaxKind::PARAM_LIST,
46-
// only separated by whitespace
47-
// SyntaxKind::SEQUENCE_OPTION_LIST,
44+
SyntaxKind::PARTITION_ITEM_LIST,
45+
SyntaxKind::ROW_LIST,
4846
SyntaxKind::SET_OPTIONS_LIST,
4947
SyntaxKind::TABLE_ARG_LIST,
5048
SyntaxKind::TABLE_LIST,
5149
SyntaxKind::TARGET_LIST,
5250
SyntaxKind::TRANSACTION_MODE_LIST,
5351
SyntaxKind::VACUUM_OPTION_LIST,
5452
SyntaxKind::VARIANT_LIST,
55-
// only separated by whitespace
56-
// SyntaxKind::XML_COLUMN_OPTION_LIST,
5753
SyntaxKind::XML_TABLE_COLUMN_LIST,
5854
];
5955

@@ -117,7 +113,7 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
117113

118114
if node
119115
.parent()
120-
.is_some_and(|n| ALL_LIST_KINDS.contains(&n.kind()))
116+
.is_some_and(|n| DELIMITED_LIST_KINDS.contains(&n.kind()))
121117
{
122118
if let Some(range) = extend_list_item(&node) {
123119
return Some(range);
@@ -544,44 +540,26 @@ $0
544540

545541
#[test]
546542
fn list_variants() {
547-
// only separated by whitespace
548-
const EXCLUDED_LIST_KINDS: &[SyntaxKind] = &[
543+
let delimited_ws_list_kinds = &[
549544
SyntaxKind::FUNC_OPTION_LIST,
550545
SyntaxKind::SEQUENCE_OPTION_LIST,
551546
SyntaxKind::XML_COLUMN_OPTION_LIST,
547+
SyntaxKind::WHEN_CLAUSE_LIST,
552548
];
553549

554550
let generated_list_kinds: Vec<SyntaxKind> = (0..SyntaxKind::__LAST as u16)
555551
.map(SyntaxKind::from)
556552
.filter(|kind| {
557-
format!("{:?}", kind).ends_with("_LIST") && !EXCLUDED_LIST_KINDS.contains(kind)
553+
format!("{:?}", kind).ends_with("_LIST") && !delimited_ws_list_kinds.contains(kind)
558554
})
559555
.collect();
560556

561-
assert_debug_snapshot!(generated_list_kinds, @r"
562-
[
563-
ARG_LIST,
564-
ATTRIBUTE_LIST,
565-
COLUMN_LIST,
566-
CONSTRAINT_EXCLUSION_LIST,
567-
JSON_TABLE_COLUMN_LIST,
568-
OPTIONS_LIST,
569-
PARAM_LIST,
570-
SET_OPTIONS_LIST,
571-
TABLE_ARG_LIST,
572-
TABLE_LIST,
573-
TARGET_LIST,
574-
TRANSACTION_MODE_LIST,
575-
VACUUM_OPTION_LIST,
576-
VARIANT_LIST,
577-
XML_TABLE_COLUMN_LIST,
578-
]
579-
");
557+
let diff: Vec<SyntaxKind> = generated_list_kinds
558+
.iter()
559+
.filter(|kind| !DELIMITED_LIST_KINDS.contains(kind))
560+
.copied()
561+
.collect();
580562

581-
assert_eq!(
582-
ALL_LIST_KINDS,
583-
generated_list_kinds.as_slice(),
584-
"ALL_LIST_KINDS constant is out of sync with actual _LIST variants"
585-
);
563+
assert_eq!(diff, vec![], "We shouldn't have any unhandled list kinds")
586564
}
587565
}

crates/squawk_parser/src/generated/syntax_kind.rs

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/squawk_parser/src/grammar.rs

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -183,20 +183,35 @@ fn case_expr(p: &mut Parser<'_>) -> CompletedMarker {
183183
if !p.at(WHEN_KW) && expr(p).is_none() {
184184
p.error("expected an expression");
185185
}
186+
when_clause_list(p);
187+
opt_else_clause(p);
188+
p.expect(END_KW);
189+
m.complete(p, CASE_EXPR)
190+
}
191+
192+
fn when_clause_list(p: &mut Parser<'_>) {
193+
let m = p.start();
186194
while !p.at(EOF) {
187195
when_clause(p);
188196
if !p.at(WHEN_KW) {
189197
break;
190198
}
191199
}
192-
// case_default
193-
// | ELSE a_expr
194-
// | /* empty */
200+
m.complete(p, WHEN_CLAUSE_LIST);
201+
}
202+
203+
// case_default
204+
// | ELSE a_expr
205+
// | /* empty */
206+
fn opt_else_clause(p: &mut Parser<'_>) {
207+
if !p.at(ELSE_KW) {
208+
return;
209+
}
210+
let m = p.start();
195211
if p.eat(ELSE_KW) && expr(p).is_none() {
196212
p.error("expected an expression");
197213
}
198-
p.expect(END_KW);
199-
m.complete(p, CASE_EXPR)
214+
m.complete(p, ELSE_CLAUSE);
200215
}
201216

202217
// when_clause:
@@ -10917,21 +10932,23 @@ fn set_transaction(p: &mut Parser<'_>) -> CompletedMarker {
1091710932
fn values(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
1091810933
let m = m.unwrap_or_else(|| p.start());
1091910934
p.bump(VALUES_KW);
10920-
// TODO: generalize this
10935+
row_list(p);
10936+
opt_order_by_clause(p);
10937+
opt_limit_clause(p);
10938+
opt_offset_clause(p);
10939+
opt_fetch_clause(p);
10940+
m.complete(p, VALUES)
10941+
}
10942+
10943+
// ( expression [, ...] ) [, ...]
10944+
fn row_list(p: &mut Parser<'_>) {
10945+
let m = p.start();
1092110946
while !p.at(EOF) {
1092210947
if !p.at(L_PAREN) {
1092310948
p.err_and_bump("expected L_PAREN");
1092410949
continue;
1092510950
}
10926-
delimited(
10927-
p,
10928-
L_PAREN,
10929-
R_PAREN,
10930-
COMMA,
10931-
|| "expected expression".to_string(),
10932-
EXPR_FIRST,
10933-
|p| expr(p).is_some(),
10934-
);
10951+
row(p);
1093510952
if !p.eat(COMMA) {
1093610953
if p.at(L_PAREN) {
1093710954
p.error("expected COMMA");
@@ -10940,11 +10957,22 @@ fn values(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
1094010957
}
1094110958
}
1094210959
}
10943-
opt_order_by_clause(p);
10944-
opt_limit_clause(p);
10945-
opt_offset_clause(p);
10946-
opt_fetch_clause(p);
10947-
m.complete(p, VALUES)
10960+
m.complete(p, ROW_LIST);
10961+
}
10962+
10963+
// ( expression [, ...] )
10964+
fn row(p: &mut Parser<'_>) {
10965+
let m = p.start();
10966+
delimited(
10967+
p,
10968+
L_PAREN,
10969+
R_PAREN,
10970+
COMMA,
10971+
|| "expected expression".to_string(),
10972+
EXPR_FIRST,
10973+
|p| expr(p).is_some(),
10974+
);
10975+
m.complete(p, ROW);
1094810976
}
1094910977

1095010978
const REINDEX_OPTION_FIRST: TokenSet = TokenSet::new(&[CONCURRENTLY_KW, VERBOSE_KW, TABLESPACE_KW]);
@@ -12375,7 +12403,7 @@ fn create_index(p: &mut Parser<'_>) -> CompletedMarker {
1237512403
// [ NULLS { FIRST | LAST } ]
1237612404
// [, ...]
1237712405
// )
12378-
index_params(p);
12406+
partition_items(p, true);
1237912407
opt_include_columns(p);
1238012408
opt_nulls_not_distinct(p);
1238112409
opt_with_params(p);
@@ -12384,12 +12412,6 @@ fn create_index(p: &mut Parser<'_>) -> CompletedMarker {
1238412412
m.complete(p, CREATE_INDEX)
1238512413
}
1238612414

12387-
fn index_params(p: &mut Parser<'_>) {
12388-
let m = p.start();
12389-
partition_items(p, true);
12390-
m.complete(p, INDEX_PARAMS);
12391-
}
12392-
1239312415
// (
1239412416
// { column_name | ( expression ) }
1239512417
// [ COLLATE collation ]
@@ -12407,6 +12429,7 @@ fn index_params(p: &mut Parser<'_>) {
1240712429
// [, ...]
1240812430
// )
1240912431
fn partition_items(p: &mut Parser<'_>, allow_extra_params: bool) {
12432+
let m = p.start();
1241012433
delimited(
1241112434
p,
1241212435
L_PAREN,
@@ -12416,6 +12439,7 @@ fn partition_items(p: &mut Parser<'_>, allow_extra_params: bool) {
1241612439
EXPR_FIRST,
1241712440
|p| opt_partition_item(p, allow_extra_params).is_some(),
1241812441
);
12442+
m.complete(p, PARTITION_ITEM_LIST);
1241912443
}
1242012444

1242112445
// [ argmode ]

crates/squawk_parser/tests/snapshots/tests__create_index_err.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ SOURCE_FILE
2121
NAME_REF
2222
IDENT "t"
2323
WHITESPACE " "
24-
INDEX_PARAMS
24+
PARTITION_ITEM_LIST
2525
L_PAREN "("
2626
PARTITION_ITEM
2727
NAME_REF

0 commit comments

Comments
 (0)