aboutsummaryrefslogtreecommitdiff
path: root/src/grammar
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-04 11:17:24 +0100
committerAleksey Kladov <[email protected]>2018-08-04 11:17:24 +0100
commite919db3731968ae7a6877530d2cb645b0495d5fd (patch)
tree02c8f9a9accf0db8f89bdf9c8a8293a81f557568 /src/grammar
parent7264c3294b3c460da459774058c9b9fa77edac12 (diff)
refine item parsing
Diffstat (limited to 'src/grammar')
-rw-r--r--src/grammar/expressions.rs29
-rw-r--r--src/grammar/items/mod.rs298
-rw-r--r--src/grammar/items/traits.rs2
3 files changed, 155 insertions, 174 deletions
diff --git a/src/grammar/expressions.rs b/src/grammar/expressions.rs
index 423e1a95a..c68419929 100644
--- a/src/grammar/expressions.rs
+++ b/src/grammar/expressions.rs
@@ -229,18 +229,27 @@ fn block_expr(p: &mut Parser) -> CompletedMarker {
229 while !p.at(EOF) && !p.at(R_CURLY) { 229 while !p.at(EOF) && !p.at(R_CURLY) {
230 match p.current() { 230 match p.current() {
231 LET_KW => let_stmt(p), 231 LET_KW => let_stmt(p),
232 c => { 232 _ => {
233 // test block_items 233 // test block_items
234 // fn a() { fn b() {} } 234 // fn a() { fn b() {} }
235 if items::ITEM_FIRST.contains(c) { 235 let m = p.start();
236 items::item(p) 236 match items::maybe_item(p) {
237 } else { 237 items::MaybeItem::Item(kind) => {
238 let expr_stmt = p.start(); 238 m.complete(p, kind);
239 expressions::expr(p); 239 }
240 if p.eat(SEMI) { 240 items::MaybeItem::Modifiers => {
241 expr_stmt.complete(p, EXPR_STMT); 241 m.abandon(p);
242 } else { 242 p.error("expected an item");
243 expr_stmt.abandon(p); 243 }
244 // test pub_expr
245 // fn foo() { pub 92; } //FIXME
246 items::MaybeItem::None => {
247 expressions::expr(p);
248 if p.eat(SEMI) {
249 m.complete(p, EXPR_STMT);
250 } else {
251 m.abandon(p);
252 }
244 } 253 }
245 } 254 }
246 } 255 }
diff --git a/src/grammar/items/mod.rs b/src/grammar/items/mod.rs
index a1150e2ac..1ed0aea07 100644
--- a/src/grammar/items/mod.rs
+++ b/src/grammar/items/mod.rs
@@ -8,173 +8,136 @@ mod use_item;
8pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { 8pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
9 attributes::inner_attributes(p); 9 attributes::inner_attributes(p);
10 while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { 10 while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) {
11 item(p); 11 item(p, stop_on_r_curly)
12 }
13}
14
15pub(super) fn item(p: &mut Parser, stop_on_r_curly: bool) {
16 let m = p.start();
17 match maybe_item(p) {
18 MaybeItem::Item(kind) => {
19 m.complete(p, kind);
20 }
21 MaybeItem::None => {
22 m.abandon(p);
23 if p.at(L_CURLY) {
24 error_block(p, "expected an item");
25 } else if !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) {
26 p.err_and_bump("expected an item");
27 } else {
28 p.error("expected an item");
29 }
30 }
31 MaybeItem::Modifiers => {
32 p.error("expected fn, trait or impl");
33 m.complete(p, ERROR);
34 }
12 } 35 }
13} 36}
14 37
15pub(super) const ITEM_FIRST: TokenSet = 38pub(super) const ITEM_FIRST: TokenSet =
16 token_set![EXTERN_KW, MOD_KW, USE_KW, STRUCT_KW, ENUM_KW, FN_KW, PUB_KW, POUND]; 39 token_set![EXTERN_KW, MOD_KW, USE_KW, STRUCT_KW, ENUM_KW, FN_KW, PUB_KW, POUND];
17 40
18pub(super) fn item(p: &mut Parser) { 41pub(super) enum MaybeItem {
19 let item = p.start(); 42 None,
43 Item(SyntaxKind),
44 Modifiers,
45}
46
47pub(super) fn maybe_item(p: &mut Parser) -> MaybeItem {
20 attributes::outer_attributes(p); 48 attributes::outer_attributes(p);
21 visibility(p); 49 visibility(p);
22 let la = p.nth(1); 50 if let Some(kind) = items_without_modifiers(p) {
23 let item_kind = match p.current() { 51 return MaybeItem::Item(kind);
24 USE_KW => { 52 }
25 use_item::use_item(p); 53
26 USE_ITEM 54 let mut has_mods = false;
27 } 55 // modifiers
28 // test extern_crate 56 has_mods |= p.eat(CONST_KW);
29 // extern crate foo; 57
30 EXTERN_KW if la == CRATE_KW => { 58 // test unsafe_block_in_mod
31 extern_crate_item(p); 59 // fn foo(){} unsafe { } fn bar(){}
32 EXTERN_CRATE_ITEM 60 if p.at(UNSAFE_KW) && p.nth(1) != L_CURLY {
33 } 61 p.eat(UNSAFE_KW);
34 EXTERN_KW => { 62 has_mods = true;
35 abi(p); 63 }
36 match p.current() { 64 if p.at(EXTERN_KW) {
37 // test extern_fn 65 has_mods = true;
38 // extern fn foo() {} 66 abi(p);
39 FN_KW => { 67 }
40 fn_item(p); 68 if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == TRAIT_KW {
41 FN_ITEM 69 p.bump_remap(AUTO_KW);
42 } 70 has_mods = true;
43 // test extern_block 71 }
44 // extern {} 72 if p.at(IDENT) && p.at_contextual_kw("default") && p.nth(1) == IMPL_KW {
45 L_CURLY => { 73 p.bump_remap(DEFAULT_KW);
46 extern_block(p); 74 has_mods = true;
47 EXTERN_BLOCK_EXPR 75 }
48 } 76
49 // test extern_struct 77 // items
50 // extern struct Foo; 78 let kind = match p.current() {
51 _ => { 79 // test extern_fn
52 item.abandon(p); 80 // extern fn foo() {}
53 p.error("expected `fn` or `{`"); 81
54 return; 82 // test const_fn
55 } 83 // const fn foo() {}
56 } 84
57 } 85 // test const_unsafe_fn
58 STATIC_KW => { 86 // const unsafe fn foo() {}
59 consts::static_item(p); 87
60 STATIC_ITEM 88 // test unsafe_extern_fn
61 } 89 // unsafe extern "C" fn foo() {}
62 CONST_KW => match p.nth(1) { 90
63 // test const_fn 91 // test unsafe_fn
64 // const fn foo() {} 92 // unsafe fn foo() {}
65 FN_KW => { 93 FN_KW => {
66 p.bump(); 94 fn_item(p);
67 fn_item(p); 95 FN_ITEM
68 FN_ITEM
69 }
70 // test const_unsafe_fn
71 // const unsafe fn foo() {}
72 UNSAFE_KW if p.nth(2) == FN_KW => {
73 p.bump();
74 p.bump();
75 fn_item(p);
76 FN_ITEM
77 }
78 _ => {
79 consts::const_item(p);
80 CONST_ITEM
81 }
82 },
83 UNSAFE_KW => {
84 p.bump();
85 let la = p.nth(1);
86 match p.current() {
87 // test unsafe_trait
88 // unsafe trait T {}
89 TRAIT_KW => {
90 traits::trait_item(p);
91 TRAIT_ITEM
92 }
93
94 // test unsafe_auto_trait
95 // unsafe auto trait T {}
96 IDENT if p.at_contextual_kw("auto") && la == TRAIT_KW => {
97 p.bump_remap(AUTO_KW);
98 traits::trait_item(p);
99 TRAIT_ITEM
100 }
101
102 // test unsafe_impl
103 // unsafe impl Foo {}
104 IMPL_KW => {
105 traits::impl_item(p);
106 IMPL_ITEM
107 }
108
109 // test unsafe_default_impl
110 // unsafe default impl Foo {}
111 IDENT if p.at_contextual_kw("default") && la == IMPL_KW => {
112 p.bump_remap(DEFAULT_KW);
113 traits::impl_item(p);
114 IMPL_ITEM
115 }
116
117 // test unsafe_extern_fn
118 // unsafe extern "C" fn foo() {}
119 EXTERN_KW => {
120 abi(p);
121 if !p.at(FN_KW) {
122 item.abandon(p);
123 p.error("expected function");
124 return;
125 }
126 fn_item(p);
127 FN_ITEM
128 }
129
130 // test unsafe_fn
131 // unsafe fn foo() {}
132 FN_KW => {
133 fn_item(p);
134 FN_ITEM
135 }
136
137 t => {
138 item.abandon(p);
139 let message = "expected `trait`, `impl` or `fn`";
140
141 // test unsafe_block_in_mod
142 // fn foo(){} unsafe { } fn bar(){}
143 if t == L_CURLY {
144 error_block(p, message);
145 } else {
146 p.error(message);
147 }
148 return;
149 }
150 }
151 }
152 TRAIT_KW => {
153 traits::trait_item(p);
154 TRAIT_ITEM
155 } 96 }
97
98 // test unsafe_trait
99 // unsafe trait T {}
100
156 // test auto_trait 101 // test auto_trait
157 // auto trait T {} 102 // auto trait T {}
158 IDENT if p.at_contextual_kw("auto") && la == TRAIT_KW => { 103
159 p.bump_remap(AUTO_KW); 104 // test unsafe_auto_trait
105 // unsafe auto trait T {}
106 TRAIT_KW => {
160 traits::trait_item(p); 107 traits::trait_item(p);
161 TRAIT_ITEM 108 TRAIT_ITEM
162 } 109 }
163 IMPL_KW => { 110
164 traits::impl_item(p); 111 // test unsafe_impl
165 IMPL_ITEM 112 // unsafe impl Foo {}
166 } 113
167 // test default_impl 114 // test default_impl
168 // default impl Foo {} 115 // default impl Foo {}
169 IDENT if p.at_contextual_kw("default") && la == IMPL_KW => { 116
170 p.bump_remap(DEFAULT_KW); 117 // test unsafe_default_impl
118 // unsafe default impl Foo {}
119 IMPL_KW => {
171 traits::impl_item(p); 120 traits::impl_item(p);
172 IMPL_ITEM 121 IMPL_ITEM
173 } 122 }
123 _ => return if has_mods {
124 MaybeItem::Modifiers
125 } else {
126 MaybeItem::None
127 }
128 };
174 129
175 FN_KW => { 130 MaybeItem::Item(kind)
176 fn_item(p); 131}
177 FN_ITEM 132
133fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
134 let la = p.nth(1);
135 let kind = match p.current() {
136 // test extern_crate
137 // extern crate foo;
138 EXTERN_KW if la == CRATE_KW => {
139 extern_crate_item(p);
140 EXTERN_CRATE_ITEM
178 } 141 }
179 TYPE_KW => { 142 TYPE_KW => {
180 type_item(p); 143 type_item(p);
@@ -186,31 +149,40 @@ pub(super) fn item(p: &mut Parser) {
186 } 149 }
187 STRUCT_KW => { 150 STRUCT_KW => {
188 structs::struct_item(p); 151 structs::struct_item(p);
152 if p.at(SEMI) {
153 p.err_and_bump(
154 "expected item, found `;`\n\
155 consider removing this semicolon"
156 );
157 }
189 STRUCT_ITEM 158 STRUCT_ITEM
190 } 159 }
191 ENUM_KW => { 160 ENUM_KW => {
192 structs::enum_item(p); 161 structs::enum_item(p);
193 ENUM_ITEM 162 ENUM_ITEM
194 } 163 }
195 L_CURLY => { 164 USE_KW => {
196 item.abandon(p); 165 use_item::use_item(p);
197 error_block(p, "expected item"); 166 USE_ITEM
198 return;
199 } 167 }
200 err_token => { 168 CONST_KW if (la == IDENT || la == MUT_KW) => {
201 item.abandon(p); 169 consts::const_item(p);
202 let message = if err_token == SEMI { 170 CONST_ITEM
203 //TODO: if the item is incomplete, this message is misleading 171 }
204 "expected item, found `;`\n\ 172 STATIC_KW => {
205 consider removing this semicolon" 173 consts::static_item(p);
206 } else { 174 STATIC_ITEM
207 "expected item" 175 }
208 }; 176 // test extern_block
209 p.err_and_bump(message); 177 // extern {}
210 return; 178 EXTERN_KW if la == L_CURLY || ((la == STRING || la == RAW_STRING) && p.nth(2) == L_CURLY) => {
179 abi(p);
180 extern_block(p);
181 EXTERN_BLOCK_EXPR
211 } 182 }
183 _ => return None,
212 }; 184 };
213 item.complete(p, item_kind); 185 Some(kind)
214} 186}
215 187
216fn extern_crate_item(p: &mut Parser) { 188fn extern_crate_item(p: &mut Parser) {
diff --git a/src/grammar/items/traits.rs b/src/grammar/items/traits.rs
index bda13e565..0614e8ab6 100644
--- a/src/grammar/items/traits.rs
+++ b/src/grammar/items/traits.rs
@@ -45,7 +45,7 @@ pub(super) fn impl_item(p: &mut Parser) {
45 // fn bar(&self) {} 45 // fn bar(&self) {}
46 // } 46 // }
47 while !p.at(EOF) && !p.at(R_CURLY) { 47 while !p.at(EOF) && !p.at(R_CURLY) {
48 item(p); 48 item(p, true);
49 } 49 }
50 p.expect(R_CURLY); 50 p.expect(R_CURLY);
51} 51}