aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-01-20 14:21:13 +0000
committerAleksey Kladov <[email protected]>2018-01-20 14:21:13 +0000
commit410f948c5f8711b951d16d6119d152cc159d9110 (patch)
tree87bd790171683ca532973795ec31759e9afbb655
parent3c612bfa3a86675ef18b1effcc76037cb6b9fddf (diff)
Drop high-order combinators
-rw-r--r--src/parser/event_parser/grammar/items.rs179
-rw-r--r--src/parser/event_parser/grammar/mod.rs83
-rw-r--r--tests/data/parser/err/0001_item_recovery_in_file.txt4
-rw-r--r--tests/data/parser/err/0004_use_path_bad_segment.txt5
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
3pub(super) fn mod_contents(p: &mut Parser) { 3pub(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
13fn 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
20fn mod_contents_item(p: &mut Parser) { 10fn 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
34fn 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
56fn struct_item(p: &mut Parser) { 42fn 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
137fn extern_crate_item(p: &mut Parser) { 134fn 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
141fn mod_item(p: &mut Parser) { 147fn 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
151pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool { 159pub(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
155fn use_item(p: &mut Parser) { 163fn 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
212fn fn_item(p: &mut Parser) { 225fn 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;
10mod paths; 10mod paths;
11 11
12pub(crate) fn file(p: &mut Parser) { 12pub(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
19fn visibility(p: &mut Parser) { 19fn 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
40fn alias(p: &mut Parser) -> bool { 39fn 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
95fn skip_to_first<C, F>(p: &mut Parser, cond: C, f: F, message: &str) -> bool 97impl<'p> Parser<'p> {
96where 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
126impl<'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 @@
1FILE@[0; 21) 1FILE@[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 `;`
19consider removing this semicolon`
17 SEMI@[11; 12) 20 SEMI@[11; 12)