diff options
author | Aleksey Kladov <[email protected]> | 2018-01-20 14:21:13 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-01-20 14:21:13 +0000 |
commit | 410f948c5f8711b951d16d6119d152cc159d9110 (patch) | |
tree | 87bd790171683ca532973795ec31759e9afbb655 | |
parent | 3c612bfa3a86675ef18b1effcc76037cb6b9fddf (diff) |
Drop high-order combinators
-rw-r--r-- | src/parser/event_parser/grammar/items.rs | 179 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/mod.rs | 83 | ||||
-rw-r--r-- | tests/data/parser/err/0001_item_recovery_in_file.txt | 4 | ||||
-rw-r--r-- | tests/data/parser/err/0004_use_path_bad_segment.txt | 5 |
4 files changed, 135 insertions, 136 deletions
diff --git a/src/parser/event_parser/grammar/items.rs b/src/parser/event_parser/grammar/items.rs index 5b0180b81..7ae48b5db 100644 --- a/src/parser/event_parser/grammar/items.rs +++ b/src/parser/event_parser/grammar/items.rs | |||
@@ -2,93 +2,90 @@ use super::*; | |||
2 | 2 | ||
3 | pub(super) fn mod_contents(p: &mut Parser) { | 3 | pub(super) fn mod_contents(p: &mut Parser) { |
4 | attributes::inner_attributes(p); | 4 | attributes::inner_attributes(p); |
5 | repeat(p, |p| { | 5 | while !p.at(EOF) { |
6 | skip_to_first( | 6 | item(p); |
7 | p, item_first, mod_contents_item, | ||
8 | "expected item", | ||
9 | ) | ||
10 | }); | ||
11 | } | ||
12 | |||
13 | fn item_first(p: &Parser) -> bool { | ||
14 | match p.current() { | ||
15 | STRUCT_KW | FN_KW | EXTERN_KW | MOD_KW | USE_KW | POUND | PUB_KW => true, | ||
16 | _ => false, | ||
17 | } | 7 | } |
18 | } | 8 | } |
19 | 9 | ||
20 | fn mod_contents_item(p: &mut Parser) { | 10 | fn item(p: &mut Parser){ |
21 | if item(p) { | ||
22 | if p.current() == SEMI { | ||
23 | node(p, ERROR, |p| { | ||
24 | p.error() | ||
25 | .message("expected item, found `;`\n\ | ||
26 | consider removing this semicolon") | ||
27 | .emit(); | ||
28 | p.bump(); | ||
29 | }) | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | |||
34 | fn item(p: &mut Parser) -> bool { | ||
35 | let attrs_start = p.mark(); | 11 | let attrs_start = p.mark(); |
36 | attributes::outer_attributes(p); | 12 | attributes::outer_attributes(p); |
37 | visibility(p); | 13 | visibility(p); |
38 | // node_if(p, USE_KW, USE_ITEM, use_item) | 14 | let la = p.raw_lookahead(1); |
39 | // || extern crate_fn | ||
40 | // || node_if(p, STATIC_KW, STATIC_ITEM, static_item) | ||
41 | // || node_if(p, CONST_KW, CONST_ITEM, const_item) or const FN! | ||
42 | // || unsafe trait, impl | ||
43 | // || node_if(p, FN_KW, FN_ITEM, fn_item) | ||
44 | // || node_if(p, TYPE_KW, TYPE_ITEM, type_item) | ||
45 | let item_start = p.mark(); | 15 | let item_start = p.mark(); |
46 | let item_parsed = node_if(p, [EXTERN_KW, CRATE_KW], EXTERN_CRATE_ITEM, extern_crate_item) | 16 | match p.current() { |
47 | || node_if(p, MOD_KW, MOD_ITEM, mod_item) | 17 | EXTERN_KW if la == CRATE_KW => extern_crate_item(p), |
48 | || node_if(p, USE_KW, USE_ITEM, use_item) | 18 | MOD_KW => mod_item(p), |
49 | || node_if(p, STRUCT_KW, STRUCT_ITEM, struct_item) | 19 | USE_KW => use_item(p), |
50 | || node_if(p, FN_KW, FN_ITEM, fn_item); | 20 | STRUCT_KW => struct_item(p), |
51 | 21 | FN_KW => fn_item(p), | |
22 | err_token => { | ||
23 | p.start(ERROR); | ||
24 | let message = if err_token == SEMI { | ||
25 | //TODO: if the item is incomplete, this messsage is misleading | ||
26 | "expected item, found `;`\n\ | ||
27 | consider removing this semicolon" | ||
28 | } else { | ||
29 | "expected item" | ||
30 | }; | ||
31 | p.error() | ||
32 | .message(message) | ||
33 | .emit(); | ||
34 | p.bump(); | ||
35 | p.finish(); | ||
36 | return; | ||
37 | } | ||
38 | }; | ||
52 | p.forward_parent(attrs_start, item_start); | 39 | p.forward_parent(attrs_start, item_start); |
53 | item_parsed | ||
54 | } | 40 | } |
55 | 41 | ||
56 | fn struct_item(p: &mut Parser) { | 42 | fn struct_item(p: &mut Parser) { |
57 | if !p.expect(IDENT) { | 43 | p.start(STRUCT_ITEM); |
58 | return | 44 | |
59 | } | 45 | assert!(p.at(STRUCT_KW)); |
60 | generic_parameters(p); | 46 | p.bump(); |
61 | match p.current() { | 47 | |
62 | WHERE_KW => { | 48 | struct_inner(p); |
63 | where_clause(p); | 49 | p.finish(); |
64 | match p.current() { | 50 | |
65 | SEMI => { | 51 | fn struct_inner(p: &mut Parser) { |
66 | p.bump(); | 52 | if !p.expect(IDENT) { |
67 | return | 53 | p.finish(); |
68 | } | ||
69 | L_CURLY => named_fields(p), | ||
70 | _ => { //TODO: special case `(` error message | ||
71 | p.error() | ||
72 | .message("expected `;` or `{`") | ||
73 | .emit(); | ||
74 | return | ||
75 | } | ||
76 | } | ||
77 | } | ||
78 | SEMI => { | ||
79 | p.bump(); | ||
80 | return | 54 | return |
81 | } | 55 | } |
82 | L_CURLY => named_fields(p), | 56 | generic_parameters(p); |
83 | L_PAREN => { | 57 | match p.current() { |
84 | tuple_fields(p); | 58 | WHERE_KW => { |
85 | p.expect(SEMI); | 59 | where_clause(p); |
86 | }, | 60 | match p.current() { |
87 | _ => { | 61 | SEMI => { |
88 | p.error() | 62 | p.bump(); |
89 | .message("expected `;`, `{`, or `(`") | 63 | return |
90 | .emit(); | 64 | } |
91 | return | 65 | L_CURLY => named_fields(p), |
66 | _ => { //TODO: special case `(` error message | ||
67 | p.error() | ||
68 | .message("expected `;` or `{`") | ||
69 | .emit(); | ||
70 | return | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | SEMI => { | ||
75 | p.bump(); | ||
76 | return | ||
77 | } | ||
78 | L_CURLY => named_fields(p), | ||
79 | L_PAREN => { | ||
80 | tuple_fields(p); | ||
81 | p.expect(SEMI); | ||
82 | }, | ||
83 | _ => { | ||
84 | p.error() | ||
85 | .message("expected `;`, `{`, or `(`") | ||
86 | .emit(); | ||
87 | return | ||
88 | } | ||
92 | } | 89 | } |
93 | } | 90 | } |
94 | } | 91 | } |
@@ -135,17 +132,28 @@ fn where_clause(_: &mut Parser) { | |||
135 | } | 132 | } |
136 | 133 | ||
137 | fn extern_crate_item(p: &mut Parser) { | 134 | fn extern_crate_item(p: &mut Parser) { |
135 | p.start(EXTERN_CRATE_ITEM); | ||
136 | |||
137 | assert!(p.at(EXTERN_KW)); | ||
138 | p.bump(); | ||
139 | |||
140 | assert!(p.at(CRATE_KW)); | ||
141 | p.bump(); | ||
142 | |||
138 | p.expect(IDENT) && alias(p) && p.expect(SEMI); | 143 | p.expect(IDENT) && alias(p) && p.expect(SEMI); |
144 | p.finish(); | ||
139 | } | 145 | } |
140 | 146 | ||
141 | fn mod_item(p: &mut Parser) { | 147 | fn mod_item(p: &mut Parser) { |
142 | if !p.expect(IDENT) { | 148 | p.start(MOD_ITEM); |
143 | return; | 149 | |
144 | } | 150 | assert!(p.at(MOD_KW)); |
145 | if p.eat(SEMI) { | 151 | p.bump(); |
146 | return; | 152 | |
153 | if p.expect(IDENT) && !p.eat(SEMI) { | ||
154 | p.curly_block(mod_contents); | ||
147 | } | 155 | } |
148 | p.curly_block(mod_contents); | 156 | p.finish() |
149 | } | 157 | } |
150 | 158 | ||
151 | pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool { | 159 | pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool { |
@@ -153,8 +161,13 @@ pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool { | |||
153 | } | 161 | } |
154 | 162 | ||
155 | fn use_item(p: &mut Parser) { | 163 | fn use_item(p: &mut Parser) { |
164 | p.start(USE_ITEM); | ||
165 | |||
166 | assert!(p.at(USE_KW)); | ||
167 | p.bump(); | ||
156 | use_tree(p); | 168 | use_tree(p); |
157 | p.expect(SEMI); | 169 | p.expect(SEMI); |
170 | p.finish(); | ||
158 | 171 | ||
159 | fn use_tree(p: &mut Parser) -> bool{ | 172 | fn use_tree(p: &mut Parser) -> bool{ |
160 | if node_if(p, STAR, USE_TREE, |_| ()) { | 173 | if node_if(p, STAR, USE_TREE, |_| ()) { |
@@ -210,8 +223,14 @@ fn use_item(p: &mut Parser) { | |||
210 | 223 | ||
211 | 224 | ||
212 | fn fn_item(p: &mut Parser) { | 225 | fn fn_item(p: &mut Parser) { |
226 | p.start(FN_ITEM); | ||
227 | |||
228 | assert!(p.at(FN_KW)); | ||
229 | p.bump(); | ||
230 | |||
213 | p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN) | 231 | p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN) |
214 | && p.curly_block(|_| ()); | 232 | && p.curly_block(|_| ()); |
233 | p.finish(); | ||
215 | } | 234 | } |
216 | 235 | ||
217 | 236 | ||
diff --git a/src/parser/event_parser/grammar/mod.rs b/src/parser/event_parser/grammar/mod.rs index 1097344c0..0c775bb25 100644 --- a/src/parser/event_parser/grammar/mod.rs +++ b/src/parser/event_parser/grammar/mod.rs | |||
@@ -10,37 +10,39 @@ mod types; | |||
10 | mod paths; | 10 | mod paths; |
11 | 11 | ||
12 | pub(crate) fn file(p: &mut Parser) { | 12 | pub(crate) fn file(p: &mut Parser) { |
13 | node(p, FILE, |p| { | 13 | p.start(FILE); |
14 | p.eat(SHEBANG); | 14 | p.eat(SHEBANG); |
15 | items::mod_contents(p); | 15 | items::mod_contents(p); |
16 | }) | 16 | p.finish() |
17 | } | 17 | } |
18 | 18 | ||
19 | fn visibility(p: &mut Parser) { | 19 | fn visibility(p: &mut Parser) { |
20 | node_if(p, PUB_KW, VISIBILITY, |p| { | 20 | if p.at(PUB_KW) { |
21 | if p.current() != L_PAREN { | 21 | p.start(VISIBILITY); |
22 | return | 22 | p.bump(); |
23 | } | 23 | if p.at(L_PAREN) { |
24 | match p.raw_lookahead(1) { | 24 | match p.raw_lookahead(1) { |
25 | CRATE_KW | SELF_KW | SUPER_KW => { | 25 | CRATE_KW | SELF_KW | SUPER_KW | IN_KW => { |
26 | p.bump(); | 26 | p.bump(); |
27 | p.bump(); | 27 | if p.bump() == IN_KW { |
28 | } | 28 | paths::use_path(p); |
29 | IN_KW => { | 29 | } |
30 | p.bump(); | 30 | p.expect(R_PAREN); |
31 | p.bump(); | 31 | } |
32 | paths::use_path(p); | 32 | _ => () |
33 | } | 33 | } |
34 | _ => return | ||
35 | } | 34 | } |
36 | p.expect(R_PAREN); | 35 | p.finish(); |
37 | }); | 36 | } |
38 | } | 37 | } |
39 | 38 | ||
40 | fn alias(p: &mut Parser) -> bool { | 39 | fn alias(p: &mut Parser) -> bool { |
41 | node_if(p, AS_KW, ALIAS, |p| { | 40 | if p.at(AS_KW) { |
41 | p.start(ALIAS); | ||
42 | p.bump(); | ||
42 | p.expect(IDENT); | 43 | p.expect(IDENT); |
43 | }); | 44 | p.finish(); |
45 | } | ||
44 | true //FIXME: return false if three are errors | 46 | true //FIXME: return false if three are errors |
45 | } | 47 | } |
46 | 48 | ||
@@ -92,40 +94,13 @@ fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, end: SyntaxKind, f: F) | |||
92 | } | 94 | } |
93 | 95 | ||
94 | 96 | ||
95 | fn skip_to_first<C, F>(p: &mut Parser, cond: C, f: F, message: &str) -> bool | 97 | impl<'p> Parser<'p> { |
96 | where | 98 | fn at(&self, kind: SyntaxKind) -> bool { |
97 | C: Fn(&Parser) -> bool, | 99 | self.current() == kind |
98 | F: FnOnce(&mut Parser), | ||
99 | { | ||
100 | let mut skipped = false; | ||
101 | loop { | ||
102 | if cond(p) { | ||
103 | if skipped { | ||
104 | p.finish(); | ||
105 | } | ||
106 | f(p); | ||
107 | return true; | ||
108 | } | ||
109 | if p.current() == EOF { | ||
110 | if skipped { | ||
111 | p.finish(); | ||
112 | } | ||
113 | return false; | ||
114 | } | ||
115 | if !skipped { | ||
116 | p.start(ERROR); | ||
117 | p.error() | ||
118 | .message(message) | ||
119 | .emit(); | ||
120 | } | ||
121 | p.bump(); | ||
122 | skipped = true; | ||
123 | } | 100 | } |
124 | } | ||
125 | 101 | ||
126 | impl<'p> Parser<'p> { | ||
127 | pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { | 102 | pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { |
128 | if self.current() == kind { | 103 | if self.at(kind) { |
129 | self.bump(); | 104 | self.bump(); |
130 | true | 105 | true |
131 | } else { | 106 | } else { |
@@ -195,4 +170,4 @@ impl<'a> Lookahead for AnyOf<'a> { | |||
195 | p.bump(); | 170 | p.bump(); |
196 | } | 171 | } |
197 | 172 | ||
198 | } \ No newline at end of file | 173 | } |
diff --git a/tests/data/parser/err/0001_item_recovery_in_file.txt b/tests/data/parser/err/0001_item_recovery_in_file.txt index 730367694..0ac741aa8 100644 --- a/tests/data/parser/err/0001_item_recovery_in_file.txt +++ b/tests/data/parser/err/0001_item_recovery_in_file.txt | |||
@@ -1,8 +1,10 @@ | |||
1 | FILE@[0; 21) | 1 | FILE@[0; 21) |
2 | ERROR@[0; 10) | 2 | ERROR@[0; 3) |
3 | err: `expected item` | 3 | err: `expected item` |
4 | IDENT@[0; 2) | 4 | IDENT@[0; 2) |
5 | WHITESPACE@[2; 3) | 5 | WHITESPACE@[2; 3) |
6 | ERROR@[3; 10) | ||
7 | err: `expected item` | ||
6 | IDENT@[3; 8) | 8 | IDENT@[3; 8) |
7 | WHITESPACE@[8; 10) | 9 | WHITESPACE@[8; 10) |
8 | STRUCT_ITEM@[10; 21) | 10 | STRUCT_ITEM@[10; 21) |
diff --git a/tests/data/parser/err/0004_use_path_bad_segment.txt b/tests/data/parser/err/0004_use_path_bad_segment.txt index cd7e86d68..adc049683 100644 --- a/tests/data/parser/err/0004_use_path_bad_segment.txt +++ b/tests/data/parser/err/0004_use_path_bad_segment.txt | |||
@@ -11,7 +11,10 @@ FILE@[0; 12) | |||
11 | PATH_SEGMENT@[9; 9) | 11 | PATH_SEGMENT@[9; 9) |
12 | err: `expected identifier` | 12 | err: `expected identifier` |
13 | err: `expected SEMI` | 13 | err: `expected SEMI` |
14 | ERROR@[9; 12) | 14 | ERROR@[9; 11) |
15 | err: `expected item` | 15 | err: `expected item` |
16 | INT_NUMBER@[9; 11) | 16 | INT_NUMBER@[9; 11) |
17 | ERROR@[11; 12) | ||
18 | err: `expected item, found `;` | ||
19 | consider removing this semicolon` | ||
17 | SEMI@[11; 12) | 20 | SEMI@[11; 12) |