1
1
mirror of https://github.com/oxalica/nil.git synced 2024-11-22 19:49:20 +03:00

Construct empty NAME nodes for recovery

This commit is contained in:
oxalica 2022-11-07 11:24:30 +08:00
parent efca332ce9
commit d714bedf1e
5 changed files with 113 additions and 10 deletions

View File

@ -666,7 +666,7 @@ impl<'i> Parser<'i> {
}
// Use lookahead for ending condition, since `;` might not be typed yet.
while self.peek_non_ws().map_or(false, SyntaxKind::can_start_attr) {
self.attr_opt();
self.attr_opt(false);
}
self.want(T![;]);
self.finish_node()
@ -725,16 +725,17 @@ impl<'i> Parser<'i> {
/// Maybe consume tokens and always make a ATTR_PATH node.
fn attrpath_opt(&mut self) {
self.start_node(ATTR_PATH);
self.attr_opt();
self.attr_opt(true);
while self.peek_non_ws() == Some(T![.]) {
self.bump(); // .
self.attr_opt();
self.attr_opt(true);
}
self.finish_node();
}
/// Maybe consume tokens and always make a {IDENT,DYNAMIC,STRING} node.
fn attr_opt(&mut self) {
/// If `force_name` is true, an empty NAME node would be created when the next token is unexpected.
fn attr_opt(&mut self, force_name: bool) {
// This must matches SyntaxKind::can_start_attr.
match self.peek_non_ws() {
Some(IDENT | T![or]) => {
@ -744,7 +745,13 @@ impl<'i> Parser<'i> {
}
Some(T!["${"]) => self.dynamic(),
Some(T!['"']) => self.string(STRING),
_ => self.error(ErrorKind::ExpectAttr),
_ => {
self.error(ErrorKind::ExpectAttr);
if force_name {
self.start_node(NAME);
self.finish_node();
}
}
}
}

View File

@ -6,8 +6,12 @@
65..66: ExpectAttr
84..85: ExpectToken(SEMICOLON)
84..85: ExpectAttr
SOURCE_FILE@0..91
ATTR_SET@0..90
93..94: ExpectAttr
95..96: ExpectAttr
95..96: ExpectToken(EQ)
95..96: ExpectToken(SEMICOLON)
SOURCE_FILE@0..97
ATTR_SET@0..96
L_CURLY@0..1 "{"
SPACE@1..4 "\n "
ATTR_PATH_VALUE@4..10
@ -114,6 +118,15 @@ SOURCE_FILE@0..91
LITERAL@86..87
INT@86..87 "1"
SEMICOLON@87..88 ";"
SPACE@88..89 "\n"
R_CURLY@89..90 "}"
SPACE@90..91 "\n"
SPACE@88..91 "\n "
ATTR_PATH_VALUE@91..95
ATTR_PATH@91..95
NAME@91..92
IDENT@91..92 "x"
DOT@92..93 "."
NAME@93..93
DOT@93..94 "."
SPACE@94..95 "\n"
NAME@95..95
R_CURLY@95..96 "}"
SPACE@96..97 "\n"

View File

@ -10,4 +10,5 @@
e = 1;
x.y = 1
f = 1;
x..
}

View File

@ -0,0 +1,76 @@
10..11: ExpectAttr
20..21: ExpectAttr
32..33: ExpectAttr
44..45: ExpectAttr
SOURCE_FILE@0..48
ATTR_SET@0..47
L_CURLY@0..1 "{"
SPACE@1..4 "\n "
ATTR_PATH_VALUE@4..11
ATTR_PATH@4..6
NAME@4..5
IDENT@4..5 "a"
SPACE@5..6 " "
EQ@6..7 "="
SPACE@7..8 " "
SELECT@8..10
REF@8..9
IDENT@8..9 "a"
DOT@9..10 "."
ATTR_PATH@10..10
NAME@10..10
SEMICOLON@10..11 ";"
SPACE@11..14 "\n "
ATTR_PATH_VALUE@14..23
ATTR_PATH@14..16
NAME@14..15
IDENT@14..15 "b"
SPACE@15..16 " "
EQ@16..17 "="
SPACE@17..18 " "
SELECT@18..22
REF@18..19
IDENT@18..19 "a"
DOT@19..20 "."
ATTR_PATH@20..22
NAME@20..20
DOT@20..21 "."
NAME@21..22
IDENT@21..22 "b"
SEMICOLON@22..23 ";"
SPACE@23..26 "\n "
ATTR_PATH_VALUE@26..33
ATTR_PATH@26..28
NAME@26..27
IDENT@26..27 "c"
SPACE@27..28 " "
EQ@28..29 "="
SPACE@29..30 " "
HAS_ATTR@30..32
REF@30..31
IDENT@30..31 "a"
QUESTION@31..32 "?"
ATTR_PATH@32..32
NAME@32..32
SEMICOLON@32..33 ";"
SPACE@33..36 "\n "
ATTR_PATH_VALUE@36..45
ATTR_PATH@36..38
NAME@36..37
IDENT@36..37 "d"
SPACE@37..38 " "
EQ@38..39 "="
SPACE@39..40 " "
HAS_ATTR@40..44
REF@40..41
IDENT@40..41 "a"
QUESTION@41..42 "?"
ATTR_PATH@42..44
NAME@42..43
IDENT@42..43 "b"
DOT@43..44 "."
NAME@44..44
SEMICOLON@44..45 ";"
SPACE@45..46 "\n"
R_CURLY@46..47 "}"
SPACE@47..48 "\n"

View File

@ -0,0 +1,6 @@
{
a = a.;
b = a..b;
c = a?;
d = a?b.;
}