aboutsummaryrefslogtreecommitdiff
path: root/crates/libsyntax2/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-28 09:12:42 +0100
committerAleksey Kladov <[email protected]>2018-08-28 09:12:42 +0100
commit2fa90e736b026ee979d9eb59178dc1f792228250 (patch)
treeadba3a569241a2030bf66e4e0b24ac5ffeaccbc3 /crates/libsyntax2/src
parent13110f48e948d7554500aefc336e72f96041386b (diff)
better recovery for exprs
Diffstat (limited to 'crates/libsyntax2/src')
-rw-r--r--crates/libsyntax2/src/ast/generated.rs78
-rw-r--r--crates/libsyntax2/src/ast/mod.rs9
-rw-r--r--crates/libsyntax2/src/grammar.ron10
-rw-r--r--crates/libsyntax2/src/grammar/expressions/atom.rs5
-rw-r--r--crates/libsyntax2/src/parser_api.rs19
5 files changed, 113 insertions, 8 deletions
diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs
index f99d1274a..6181aada8 100644
--- a/crates/libsyntax2/src/ast/generated.rs
+++ b/crates/libsyntax2/src/ast/generated.rs
@@ -439,6 +439,24 @@ impl<'a> ExprStmt<'a> {
439 } 439 }
440} 440}
441 441
442// ExternCrateItem
443#[derive(Debug, Clone, Copy)]
444pub struct ExternCrateItem<'a> {
445 syntax: SyntaxNodeRef<'a>,
446}
447
448impl<'a> AstNode<'a> for ExternCrateItem<'a> {
449 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
450 match syntax.kind() {
451 EXTERN_CRATE_ITEM => Some(ExternCrateItem { syntax }),
452 _ => None,
453 }
454 }
455 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
456}
457
458impl<'a> ExternCrateItem<'a> {}
459
442// FieldExpr 460// FieldExpr
443#[derive(Debug, Clone, Copy)] 461#[derive(Debug, Clone, Copy)]
444pub struct FieldExpr<'a> { 462pub struct FieldExpr<'a> {
@@ -839,11 +857,51 @@ impl<'a> AstNode<'a> for Module<'a> {
839impl<'a> ast::NameOwner<'a> for Module<'a> {} 857impl<'a> ast::NameOwner<'a> for Module<'a> {}
840impl<'a> ast::AttrsOwner<'a> for Module<'a> {} 858impl<'a> ast::AttrsOwner<'a> for Module<'a> {}
841impl<'a> Module<'a> { 859impl<'a> Module<'a> {
842 pub fn modules(self) -> impl Iterator<Item = Module<'a>> + 'a { 860 pub fn items(self) -> impl Iterator<Item = ModuleItem<'a>> + 'a {
843 super::children(self) 861 super::children(self)
844 } 862 }
845} 863}
846 864
865// ModuleItem
866#[derive(Debug, Clone, Copy)]
867pub enum ModuleItem<'a> {
868 StructDef(StructDef<'a>),
869 EnumDef(EnumDef<'a>),
870 FnDef(FnDef<'a>),
871 TraitDef(TraitDef<'a>),
872 ImplItem(ImplItem<'a>),
873 UseItem(UseItem<'a>),
874 ExternCrateItem(ExternCrateItem<'a>),
875}
876
877impl<'a> AstNode<'a> for ModuleItem<'a> {
878 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
879 match syntax.kind() {
880 STRUCT_DEF => Some(ModuleItem::StructDef(StructDef { syntax })),
881 ENUM_DEF => Some(ModuleItem::EnumDef(EnumDef { syntax })),
882 FN_DEF => Some(ModuleItem::FnDef(FnDef { syntax })),
883 TRAIT_DEF => Some(ModuleItem::TraitDef(TraitDef { syntax })),
884 IMPL_ITEM => Some(ModuleItem::ImplItem(ImplItem { syntax })),
885 USE_ITEM => Some(ModuleItem::UseItem(UseItem { syntax })),
886 EXTERN_CRATE_ITEM => Some(ModuleItem::ExternCrateItem(ExternCrateItem { syntax })),
887 _ => None,
888 }
889 }
890 fn syntax(self) -> SyntaxNodeRef<'a> {
891 match self {
892 ModuleItem::StructDef(inner) => inner.syntax(),
893 ModuleItem::EnumDef(inner) => inner.syntax(),
894 ModuleItem::FnDef(inner) => inner.syntax(),
895 ModuleItem::TraitDef(inner) => inner.syntax(),
896 ModuleItem::ImplItem(inner) => inner.syntax(),
897 ModuleItem::UseItem(inner) => inner.syntax(),
898 ModuleItem::ExternCrateItem(inner) => inner.syntax(),
899 }
900 }
901}
902
903impl<'a> ModuleItem<'a> {}
904
847// Name 905// Name
848#[derive(Debug, Clone, Copy)] 906#[derive(Debug, Clone, Copy)]
849pub struct Name<'a> { 907pub struct Name<'a> {
@@ -1762,6 +1820,24 @@ impl<'a> AstNode<'a> for TypeRef<'a> {
1762 1820
1763impl<'a> TypeRef<'a> {} 1821impl<'a> TypeRef<'a> {}
1764 1822
1823// UseItem
1824#[derive(Debug, Clone, Copy)]
1825pub struct UseItem<'a> {
1826 syntax: SyntaxNodeRef<'a>,
1827}
1828
1829impl<'a> AstNode<'a> for UseItem<'a> {
1830 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1831 match syntax.kind() {
1832 USE_ITEM => Some(UseItem { syntax }),
1833 _ => None,
1834 }
1835 }
1836 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1837}
1838
1839impl<'a> UseItem<'a> {}
1840
1765// WhereClause 1841// WhereClause
1766#[derive(Debug, Clone, Copy)] 1842#[derive(Debug, Clone, Copy)]
1767pub struct WhereClause<'a> { 1843pub struct WhereClause<'a> {
diff --git a/crates/libsyntax2/src/ast/mod.rs b/crates/libsyntax2/src/ast/mod.rs
index 2ebee6a4f..9941138a7 100644
--- a/crates/libsyntax2/src/ast/mod.rs
+++ b/crates/libsyntax2/src/ast/mod.rs
@@ -115,6 +115,15 @@ impl<'a> Module<'a> {
115 } 115 }
116} 116}
117 117
118impl<'a> LetStmt<'a> {
119 pub fn has_semi(self) -> bool {
120 match self.syntax().last_child() {
121 None => false,
122 Some(node) => node.kind() == SEMI,
123 }
124 }
125}
126
118impl<'a> IfExpr<'a> { 127impl<'a> IfExpr<'a> {
119 pub fn then_branch(self) -> Option<Block<'a>> { 128 pub fn then_branch(self) -> Option<Block<'a>> {
120 self.blocks().nth(0) 129 self.blocks().nth(0)
diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron
index a98e9e2fd..7217a4633 100644
--- a/crates/libsyntax2/src/grammar.ron
+++ b/crates/libsyntax2/src/grammar.ron
@@ -273,7 +273,7 @@ Grammar(
273 "Module": ( 273 "Module": (
274 traits: ["NameOwner", "AttrsOwner"], 274 traits: ["NameOwner", "AttrsOwner"],
275 collections: [ 275 collections: [
276 ["modules", "Module"] 276 ["items", "ModuleItem"]
277 ] 277 ]
278 ), 278 ),
279 "ConstDef": ( traits: [ 279 "ConstDef": ( traits: [
@@ -331,6 +331,10 @@ Grammar(
331 "AttrsOwner" 331 "AttrsOwner"
332 ], 332 ],
333 ), 333 ),
334 "ModuleItem": (
335 enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "ImplItem",
336 "UseItem", "ExternCrateItem" ]
337 ),
334 338
335 "TupleExpr": (), 339 "TupleExpr": (),
336 "ArrayExpr": (), 340 "ArrayExpr": (),
@@ -479,6 +483,8 @@ Grammar(
479 ), 483 ),
480 "Param": ( 484 "Param": (
481 options: [["pat", "Pat"]], 485 options: [["pat", "Pat"]],
482 ) 486 ),
487 "UseItem": (),
488 "ExternCrateItem": (),
483 }, 489 },
484) 490)
diff --git a/crates/libsyntax2/src/grammar/expressions/atom.rs b/crates/libsyntax2/src/grammar/expressions/atom.rs
index ab4aa49d2..0769bb5a8 100644
--- a/crates/libsyntax2/src/grammar/expressions/atom.rs
+++ b/crates/libsyntax2/src/grammar/expressions/atom.rs
@@ -33,6 +33,9 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
33 RETURN_KW, IDENT, SELF_KW, SUPER_KW, COLONCOLON, BREAK_KW, CONTINUE_KW, LIFETIME ], 33 RETURN_KW, IDENT, SELF_KW, SUPER_KW, COLONCOLON, BREAK_KW, CONTINUE_KW, LIFETIME ],
34 ]; 34 ];
35 35
36const EXPR_RECOVERY_SET: TokenSet =
37 token_set![LET_KW];
38
36pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { 39pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> {
37 match literal(p) { 40 match literal(p) {
38 Some(m) => return Some(m), 41 Some(m) => return Some(m),
@@ -73,7 +76,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMark
73 CONTINUE_KW => continue_expr(p), 76 CONTINUE_KW => continue_expr(p),
74 BREAK_KW => break_expr(p), 77 BREAK_KW => break_expr(p),
75 _ => { 78 _ => {
76 p.err_and_bump("expected expression"); 79 p.err_recover("expected expression", EXPR_RECOVERY_SET);
77 return None; 80 return None;
78 } 81 }
79 }; 82 };
diff --git a/crates/libsyntax2/src/parser_api.rs b/crates/libsyntax2/src/parser_api.rs
index 0a3b29b70..10b9b64ac 100644
--- a/crates/libsyntax2/src/parser_api.rs
+++ b/crates/libsyntax2/src/parser_api.rs
@@ -12,6 +12,8 @@ fn mask(kind: SyntaxKind) -> u128 {
12} 12}
13 13
14impl TokenSet { 14impl TokenSet {
15 const EMPTY: TokenSet = TokenSet(0);
16
15 pub fn contains(&self, kind: SyntaxKind) -> bool { 17 pub fn contains(&self, kind: SyntaxKind) -> bool {
16 self.0 & mask(kind) != 0 18 self.0 & mask(kind) != 0
17 } 19 }
@@ -139,12 +141,21 @@ impl<'t> Parser<'t> {
139 141
140 /// Create an error node and consume the next token. 142 /// Create an error node and consume the next token.
141 pub(crate) fn err_and_bump(&mut self, message: &str) { 143 pub(crate) fn err_and_bump(&mut self, message: &str) {
142 let m = self.start(); 144 self.err_recover(message, TokenSet::EMPTY);
143 self.error(message); 145 }
144 if !self.at(SyntaxKind::L_CURLY) && !self.at(SyntaxKind::R_CURLY) { 146
147 /// Create an error node and consume the next token.
148 pub(crate) fn err_recover(&mut self, message: &str, recovery_set: TokenSet) {
149 if self.at(SyntaxKind::L_CURLY)
150 || self.at(SyntaxKind::R_CURLY)
151 || recovery_set.contains(self.current()) {
152 self.error(message);
153 } else {
154 let m = self.start();
155 self.error(message);
145 self.bump(); 156 self.bump();
157 m.complete(self, ERROR);
146 } 158 }
147 m.complete(self, ERROR);
148 } 159 }
149} 160}
150 161