diff options
author | Aleksey Kladov <[email protected]> | 2018-01-20 20:25:34 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-01-20 20:25:34 +0000 |
commit | 0b5d39f2a204e5ec6cd6205440e4cdc763162814 (patch) | |
tree | 8d201ef62b5e4fe48e3cce7b557071e434530801 | |
parent | be60d5aa6669a74e92495288f44b7f9258a8518f (diff) |
Markers API
-rw-r--r-- | src/parser/event_parser/grammar/attributes.rs | 8 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/expressions.rs | 4 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/items.rs | 151 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/mod.rs | 12 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/paths.rs | 17 | ||||
-rw-r--r-- | src/parser/event_parser/mod.rs | 2 | ||||
-rw-r--r-- | src/parser/event_parser/parser.rs | 112 | ||||
-rw-r--r-- | src/parser/mod.rs | 5 | ||||
-rw-r--r-- | src/tree/file_builder.rs | 8 | ||||
-rw-r--r-- | src/tree/mod.rs | 15 |
10 files changed, 189 insertions, 145 deletions
diff --git a/src/parser/event_parser/grammar/attributes.rs b/src/parser/event_parser/grammar/attributes.rs index 8b5e5bcfe..2d04a1a41 100644 --- a/src/parser/event_parser/grammar/attributes.rs +++ b/src/parser/event_parser/grammar/attributes.rs | |||
@@ -19,13 +19,13 @@ fn attribute(p: &mut Parser, kind: AttrKind) -> bool { | |||
19 | if kind == AttrKind::Inner && p.raw_lookahead(1) != EXCL { | 19 | if kind == AttrKind::Inner && p.raw_lookahead(1) != EXCL { |
20 | return false; | 20 | return false; |
21 | } | 21 | } |
22 | p.start(ATTR); | 22 | let attr = p.start(); |
23 | p.bump(); | 23 | p.bump(); |
24 | if kind == AttrKind::Inner { | 24 | if kind == AttrKind::Inner { |
25 | p.bump(); | 25 | p.bump(); |
26 | } | 26 | } |
27 | p.expect(L_BRACK) && meta_item(p) && p.expect(R_BRACK); | 27 | p.expect(L_BRACK) && meta_item(p) && p.expect(R_BRACK); |
28 | p.finish(); | 28 | attr.complete(p, ATTR); |
29 | true | 29 | true |
30 | } else { | 30 | } else { |
31 | false | 31 | false |
@@ -34,7 +34,7 @@ fn attribute(p: &mut Parser, kind: AttrKind) -> bool { | |||
34 | 34 | ||
35 | fn meta_item(p: &mut Parser) -> bool { | 35 | fn meta_item(p: &mut Parser) -> bool { |
36 | if p.at(IDENT) { | 36 | if p.at(IDENT) { |
37 | p.start(META_ITEM); | 37 | let meta_item = p.start(); |
38 | p.bump(); | 38 | p.bump(); |
39 | if p.eat(EQ) { | 39 | if p.eat(EQ) { |
40 | if !expressions::literal(p) { | 40 | if !expressions::literal(p) { |
@@ -46,7 +46,7 @@ fn meta_item(p: &mut Parser) -> bool { | |||
46 | comma_list(p, R_PAREN, meta_item_inner); | 46 | comma_list(p, R_PAREN, meta_item_inner); |
47 | p.expect(R_PAREN); | 47 | p.expect(R_PAREN); |
48 | } | 48 | } |
49 | p.finish(); | 49 | meta_item.complete(p, META_ITEM); |
50 | true | 50 | true |
51 | } else { | 51 | } else { |
52 | false | 52 | false |
diff --git a/src/parser/event_parser/grammar/expressions.rs b/src/parser/event_parser/grammar/expressions.rs index 0f65193c9..a943b8c81 100644 --- a/src/parser/event_parser/grammar/expressions.rs +++ b/src/parser/event_parser/grammar/expressions.rs | |||
@@ -6,9 +6,9 @@ pub(super) fn literal(p: &mut Parser) -> bool { | |||
6 | INT_NUMBER | FLOAT_NUMBER | | 6 | INT_NUMBER | FLOAT_NUMBER | |
7 | BYTE | CHAR | | 7 | BYTE | CHAR | |
8 | STRING | RAW_STRING | BYTE_STRING | RAW_BYTE_STRING => { | 8 | STRING | RAW_STRING | BYTE_STRING | RAW_BYTE_STRING => { |
9 | p.start(LITERAL); | 9 | let lit = p.start(); |
10 | p.bump(); | 10 | p.bump(); |
11 | p.finish(); | 11 | lit.complete(p, LITERAL); |
12 | true | 12 | true |
13 | } | 13 | } |
14 | _ => false | 14 | _ => false |
diff --git a/src/parser/event_parser/grammar/items.rs b/src/parser/event_parser/grammar/items.rs index 4514f0dab..c9a890553 100644 --- a/src/parser/event_parser/grammar/items.rs +++ b/src/parser/event_parser/grammar/items.rs | |||
@@ -8,19 +8,34 @@ pub(super) fn mod_contents(p: &mut Parser) { | |||
8 | } | 8 | } |
9 | 9 | ||
10 | fn item(p: &mut Parser) { | 10 | fn item(p: &mut Parser) { |
11 | let attrs_start = p.mark(); | 11 | let item = p.start(); |
12 | attributes::outer_attributes(p); | 12 | attributes::outer_attributes(p); |
13 | visibility(p); | 13 | visibility(p); |
14 | let la = p.raw_lookahead(1); | 14 | let la = p.raw_lookahead(1); |
15 | let item_start = p.mark(); | 15 | let item_kind = match p.current() { |
16 | match p.current() { | 16 | EXTERN_KW if la == CRATE_KW => { |
17 | EXTERN_KW if la == CRATE_KW => extern_crate_item(p), | 17 | extern_crate_item(p); |
18 | MOD_KW => mod_item(p), | 18 | EXTERN_CRATE_ITEM |
19 | USE_KW => use_item(p), | 19 | } |
20 | STRUCT_KW => struct_item(p), | 20 | MOD_KW => { |
21 | FN_KW => fn_item(p), | 21 | mod_item(p); |
22 | MOD_ITEM | ||
23 | } | ||
24 | USE_KW => { | ||
25 | use_item(p); | ||
26 | USE_ITEM | ||
27 | } | ||
28 | STRUCT_KW => { | ||
29 | struct_item(p); | ||
30 | STRUCT_ITEM | ||
31 | } | ||
32 | FN_KW => { | ||
33 | fn_item(p); | ||
34 | FN_ITEM | ||
35 | } | ||
22 | err_token => { | 36 | err_token => { |
23 | p.start(ERROR); | 37 | item.abandon(p); |
38 | let err = p.start(); | ||
24 | let message = if err_token == SEMI { | 39 | let message = if err_token == SEMI { |
25 | //TODO: if the item is incomplete, this message is misleading | 40 | //TODO: if the item is incomplete, this message is misleading |
26 | "expected item, found `;`\n\ | 41 | "expected item, found `;`\n\ |
@@ -32,60 +47,52 @@ fn item(p: &mut Parser) { | |||
32 | .message(message) | 47 | .message(message) |
33 | .emit(); | 48 | .emit(); |
34 | p.bump(); | 49 | p.bump(); |
35 | p.finish(); | 50 | err.complete(p, ERROR); |
36 | return; | 51 | return; |
37 | } | 52 | } |
38 | }; | 53 | }; |
39 | p.forward_parent(attrs_start, item_start); | 54 | item.complete(p, item_kind); |
40 | } | 55 | } |
41 | 56 | ||
42 | fn struct_item(p: &mut Parser) { | 57 | fn struct_item(p: &mut Parser) { |
43 | p.start(STRUCT_ITEM); | ||
44 | |||
45 | assert!(p.at(STRUCT_KW)); | 58 | assert!(p.at(STRUCT_KW)); |
46 | p.bump(); | 59 | p.bump(); |
47 | 60 | ||
48 | struct_inner(p); | 61 | if !p.expect(IDENT) { |
49 | p.finish(); | 62 | return; |
50 | 63 | } | |
51 | fn struct_inner(p: &mut Parser) { | 64 | generic_parameters(p); |
52 | if !p.expect(IDENT) { | 65 | match p.current() { |
53 | p.finish(); | 66 | WHERE_KW => { |
54 | return; | 67 | where_clause(p); |
55 | } | 68 | match p.current() { |
56 | generic_parameters(p); | 69 | SEMI => { |
57 | match p.current() { | 70 | p.bump(); |
58 | WHERE_KW => { | 71 | return; |
59 | where_clause(p); | 72 | } |
60 | match p.current() { | 73 | L_CURLY => named_fields(p), |
61 | SEMI => { | 74 | _ => { //TODO: special case `(` error message |
62 | p.bump(); | 75 | p.error() |
63 | return; | 76 | .message("expected `;` or `{`") |
64 | } | 77 | .emit(); |
65 | L_CURLY => named_fields(p), | 78 | return; |
66 | _ => { //TODO: special case `(` error message | ||
67 | p.error() | ||
68 | .message("expected `;` or `{`") | ||
69 | .emit(); | ||
70 | return; | ||
71 | } | ||
72 | } | 79 | } |
73 | } | 80 | } |
74 | SEMI => { | 81 | } |
75 | p.bump(); | 82 | SEMI => { |
76 | return; | 83 | p.bump(); |
77 | } | 84 | return; |
78 | L_CURLY => named_fields(p), | 85 | } |
79 | L_PAREN => { | 86 | L_CURLY => named_fields(p), |
80 | tuple_fields(p); | 87 | L_PAREN => { |
81 | p.expect(SEMI); | 88 | pos_fields(p); |
82 | } | 89 | p.expect(SEMI); |
83 | _ => { | 90 | } |
84 | p.error() | 91 | _ => { |
85 | .message("expected `;`, `{`, or `(`") | 92 | p.error() |
86 | .emit(); | 93 | .message("expected `;`, `{`, or `(`") |
87 | return; | 94 | .emit(); |
88 | } | 95 | return; |
89 | } | 96 | } |
90 | } | 97 | } |
91 | } | 98 | } |
@@ -97,30 +104,30 @@ fn named_fields(p: &mut Parser) { | |||
97 | })); | 104 | })); |
98 | 105 | ||
99 | fn named_field(p: &mut Parser) { | 106 | fn named_field(p: &mut Parser) { |
100 | p.start(NAMED_FIELD); | 107 | let field = p.start(); |
101 | visibility(p); | 108 | visibility(p); |
102 | if p.expect(IDENT) && p.expect(COLON) { | 109 | if p.expect(IDENT) && p.expect(COLON) { |
103 | types::type_ref(p); | 110 | types::type_ref(p); |
104 | }; | 111 | }; |
105 | p.finish() | 112 | field.complete(p, NAMED_FIELD); |
106 | } | 113 | } |
107 | } | 114 | } |
108 | 115 | ||
109 | fn tuple_fields(p: &mut Parser) { | 116 | fn pos_fields(p: &mut Parser) { |
110 | if !p.expect(L_PAREN) { | 117 | if !p.expect(L_PAREN) { |
111 | return; | 118 | return; |
112 | } | 119 | } |
113 | comma_list(p, R_PAREN, |p| { | 120 | comma_list(p, R_PAREN, |p| { |
114 | tuple_field(p); | 121 | pos_field(p); |
115 | true | 122 | true |
116 | }); | 123 | }); |
117 | p.expect(R_PAREN); | 124 | p.expect(R_PAREN); |
118 | 125 | ||
119 | fn tuple_field(p: &mut Parser) { | 126 | fn pos_field(p: &mut Parser) { |
120 | p.start(POS_FIELD); | 127 | let pos_field = p.start(); |
121 | visibility(p); | 128 | visibility(p); |
122 | types::type_ref(p); | 129 | types::type_ref(p); |
123 | p.finish(); | 130 | pos_field.complete(p, POS_FIELD); |
124 | } | 131 | } |
125 | } | 132 | } |
126 | 133 | ||
@@ -129,28 +136,21 @@ fn generic_parameters(_: &mut Parser) {} | |||
129 | fn where_clause(_: &mut Parser) {} | 136 | fn where_clause(_: &mut Parser) {} |
130 | 137 | ||
131 | fn extern_crate_item(p: &mut Parser) { | 138 | fn extern_crate_item(p: &mut Parser) { |
132 | p.start(EXTERN_CRATE_ITEM); | ||
133 | |||
134 | assert!(p.at(EXTERN_KW)); | 139 | assert!(p.at(EXTERN_KW)); |
135 | p.bump(); | 140 | p.bump(); |
136 | |||
137 | assert!(p.at(CRATE_KW)); | 141 | assert!(p.at(CRATE_KW)); |
138 | p.bump(); | 142 | p.bump(); |
139 | 143 | ||
140 | p.expect(IDENT) && alias(p) && p.expect(SEMI); | 144 | p.expect(IDENT) && alias(p) && p.expect(SEMI); |
141 | p.finish(); | ||
142 | } | 145 | } |
143 | 146 | ||
144 | fn mod_item(p: &mut Parser) { | 147 | fn mod_item(p: &mut Parser) { |
145 | p.start(MOD_ITEM); | ||
146 | |||
147 | assert!(p.at(MOD_KW)); | 148 | assert!(p.at(MOD_KW)); |
148 | p.bump(); | 149 | p.bump(); |
149 | 150 | ||
150 | if p.expect(IDENT) && !p.eat(SEMI) { | 151 | if p.expect(IDENT) && !p.eat(SEMI) { |
151 | p.curly_block(mod_contents); | 152 | p.curly_block(mod_contents); |
152 | } | 153 | } |
153 | p.finish() | ||
154 | } | 154 | } |
155 | 155 | ||
156 | pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool { | 156 | pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool { |
@@ -158,28 +158,24 @@ pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool { | |||
158 | } | 158 | } |
159 | 159 | ||
160 | fn use_item(p: &mut Parser) { | 160 | fn use_item(p: &mut Parser) { |
161 | p.start(USE_ITEM); | ||
162 | |||
163 | assert!(p.at(USE_KW)); | 161 | assert!(p.at(USE_KW)); |
164 | p.bump(); | 162 | p.bump(); |
163 | |||
165 | use_tree(p); | 164 | use_tree(p); |
166 | p.expect(SEMI); | 165 | p.expect(SEMI); |
167 | p.finish(); | ||
168 | 166 | ||
169 | fn use_tree(p: &mut Parser) -> bool { | 167 | fn use_tree(p: &mut Parser) -> bool { |
170 | let la = p.raw_lookahead(1); | 168 | let la = p.raw_lookahead(1); |
169 | let m = p.start(); | ||
171 | match (p.current(), la) { | 170 | match (p.current(), la) { |
172 | (STAR, _) => { | 171 | (STAR, _) => { |
173 | p.start(USE_TREE); | ||
174 | p.bump(); | 172 | p.bump(); |
175 | } | 173 | } |
176 | (COLONCOLON, STAR) => { | 174 | (COLONCOLON, STAR) => { |
177 | p.start(USE_TREE); | ||
178 | p.bump(); | 175 | p.bump(); |
179 | p.bump(); | 176 | p.bump(); |
180 | } | 177 | } |
181 | (L_CURLY, _) | (COLONCOLON, L_CURLY) => { | 178 | (L_CURLY, _) | (COLONCOLON, L_CURLY) => { |
182 | p.start(USE_TREE); | ||
183 | if p.at(COLONCOLON) { | 179 | if p.at(COLONCOLON) { |
184 | p.bump(); | 180 | p.bump(); |
185 | } | 181 | } |
@@ -188,7 +184,6 @@ fn use_item(p: &mut Parser) { | |||
188 | }); | 184 | }); |
189 | } | 185 | } |
190 | _ if paths::is_path_start(p) => { | 186 | _ if paths::is_path_start(p) => { |
191 | p.start(USE_TREE); | ||
192 | paths::use_path(p); | 187 | paths::use_path(p); |
193 | match p.current() { | 188 | match p.current() { |
194 | AS_KW => { | 189 | AS_KW => { |
@@ -216,23 +211,23 @@ fn use_item(p: &mut Parser) { | |||
216 | _ => (), | 211 | _ => (), |
217 | } | 212 | } |
218 | } | 213 | } |
219 | _ => return false, | 214 | _ => { |
215 | m.abandon(p); | ||
216 | return false | ||
217 | }, | ||
220 | } | 218 | } |
221 | p.finish(); | 219 | m.complete(p, USE_TREE); |
222 | return true; | 220 | return true; |
223 | } | 221 | } |
224 | } | 222 | } |
225 | 223 | ||
226 | 224 | ||
227 | fn fn_item(p: &mut Parser) { | 225 | fn fn_item(p: &mut Parser) { |
228 | p.start(FN_ITEM); | ||
229 | |||
230 | assert!(p.at(FN_KW)); | 226 | assert!(p.at(FN_KW)); |
231 | p.bump(); | 227 | p.bump(); |
232 | 228 | ||
233 | p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN) | 229 | p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN) |
234 | && p.curly_block(|_| ()); | 230 | && p.curly_block(|_| ()); |
235 | p.finish(); | ||
236 | } | 231 | } |
237 | 232 | ||
238 | 233 | ||
diff --git a/src/parser/event_parser/grammar/mod.rs b/src/parser/event_parser/grammar/mod.rs index c3d0c8c10..d3b63c4c1 100644 --- a/src/parser/event_parser/grammar/mod.rs +++ b/src/parser/event_parser/grammar/mod.rs | |||
@@ -10,15 +10,15 @@ 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 | p.start(FILE); | 13 | let file = p.start(); |
14 | p.eat(SHEBANG); | 14 | p.eat(SHEBANG); |
15 | items::mod_contents(p); | 15 | items::mod_contents(p); |
16 | p.finish() | 16 | file.complete(p, FILE); |
17 | } | 17 | } |
18 | 18 | ||
19 | fn visibility(p: &mut Parser) { | 19 | fn visibility(p: &mut Parser) { |
20 | if p.at(PUB_KW) { | 20 | if p.at(PUB_KW) { |
21 | p.start(VISIBILITY); | 21 | let vis = p.start(); |
22 | p.bump(); | 22 | p.bump(); |
23 | if p.at(L_PAREN) { | 23 | if p.at(L_PAREN) { |
24 | match p.raw_lookahead(1) { | 24 | match p.raw_lookahead(1) { |
@@ -32,16 +32,16 @@ fn visibility(p: &mut Parser) { | |||
32 | _ => () | 32 | _ => () |
33 | } | 33 | } |
34 | } | 34 | } |
35 | p.finish(); | 35 | vis.complete(p, VISIBILITY); |
36 | } | 36 | } |
37 | } | 37 | } |
38 | 38 | ||
39 | fn alias(p: &mut Parser) -> bool { | 39 | fn alias(p: &mut Parser) -> bool { |
40 | if p.at(AS_KW) { | 40 | if p.at(AS_KW) { |
41 | p.start(ALIAS); | 41 | let alias = p.start(); |
42 | p.bump(); | 42 | p.bump(); |
43 | p.expect(IDENT); | 43 | p.expect(IDENT); |
44 | p.finish(); | 44 | alias.complete(p, ALIAS); |
45 | } | 45 | } |
46 | true //FIXME: return false if three are errors | 46 | true //FIXME: return false if three are errors |
47 | } | 47 | } |
diff --git a/src/parser/event_parser/grammar/paths.rs b/src/parser/event_parser/grammar/paths.rs index f5124cfce..b58c59aef 100644 --- a/src/parser/event_parser/grammar/paths.rs +++ b/src/parser/event_parser/grammar/paths.rs | |||
@@ -8,19 +8,16 @@ pub(crate) fn use_path(p: &mut Parser) { | |||
8 | if !is_path_start(p) { | 8 | if !is_path_start(p) { |
9 | return; | 9 | return; |
10 | } | 10 | } |
11 | let mut prev = p.mark(); | 11 | let path = p.start(); |
12 | p.start(PATH); | ||
13 | path_segment(p, true); | 12 | path_segment(p, true); |
14 | p.finish(); | 13 | let mut qual = path.complete(p, PATH); |
15 | loop { | 14 | loop { |
16 | let curr = p.mark(); | ||
17 | if p.at(COLONCOLON) && !items::is_use_tree_start(p.raw_lookahead(1)) { | 15 | if p.at(COLONCOLON) && !items::is_use_tree_start(p.raw_lookahead(1)) { |
18 | p.start(PATH); | 16 | let path = qual.precede(p); |
19 | p.bump(); | 17 | p.bump(); |
20 | path_segment(p, false); | 18 | path_segment(p, false); |
21 | p.forward_parent(prev, curr); | 19 | let path = path.complete(p, PATH); |
22 | prev = curr; | 20 | qual = path; |
23 | p.finish(); | ||
24 | } else { | 21 | } else { |
25 | break; | 22 | break; |
26 | } | 23 | } |
@@ -28,7 +25,7 @@ pub(crate) fn use_path(p: &mut Parser) { | |||
28 | } | 25 | } |
29 | 26 | ||
30 | fn path_segment(p: &mut Parser, first: bool) { | 27 | fn path_segment(p: &mut Parser, first: bool) { |
31 | p.start(PATH_SEGMENT); | 28 | let segment = p.start(); |
32 | if first { | 29 | if first { |
33 | p.eat(COLONCOLON); | 30 | p.eat(COLONCOLON); |
34 | } | 31 | } |
@@ -42,5 +39,5 @@ fn path_segment(p: &mut Parser, first: bool) { | |||
42 | .emit(); | 39 | .emit(); |
43 | } | 40 | } |
44 | }; | 41 | }; |
45 | p.finish(); | 42 | segment.complete(p, PATH_SEGMENT); |
46 | } | 43 | } |
diff --git a/src/parser/event_parser/mod.rs b/src/parser/event_parser/mod.rs index c89a3ebe7..7c81182e3 100644 --- a/src/parser/event_parser/mod.rs +++ b/src/parser/event_parser/mod.rs | |||
@@ -23,4 +23,4 @@ pub(crate) fn parse<'t>(text: &'t str, raw_tokens: &'t [Token]) -> Vec<Event> { | |||
23 | let mut parser = parser::Parser::new(text, raw_tokens); | 23 | let mut parser = parser::Parser::new(text, raw_tokens); |
24 | grammar::file(&mut parser); | 24 | grammar::file(&mut parser); |
25 | parser.into_events() | 25 | parser.into_events() |
26 | } \ No newline at end of file | 26 | } |
diff --git a/src/parser/event_parser/parser.rs b/src/parser/event_parser/parser.rs index 6171b3579..2bc9dd34f 100644 --- a/src/parser/event_parser/parser.rs +++ b/src/parser/event_parser/parser.rs | |||
@@ -1,8 +1,71 @@ | |||
1 | use {Token, SyntaxKind, TextUnit}; | 1 | use {Token, SyntaxKind, TextUnit}; |
2 | use super::{Event}; | 2 | use super::Event; |
3 | use super::super::is_insignificant; | 3 | use super::super::is_insignificant; |
4 | use syntax_kinds::{L_CURLY, R_CURLY, ERROR}; | 4 | use syntax_kinds::{L_CURLY, R_CURLY, ERROR}; |
5 | use tree::EOF; | 5 | use tree::{EOF, TOMBSTONE}; |
6 | |||
7 | pub(crate) struct Marker { | ||
8 | pos: u32 | ||
9 | } | ||
10 | |||
11 | impl Marker { | ||
12 | pub fn complete(self, p: &mut Parser, kind: SyntaxKind) -> CompleteMarker { | ||
13 | match self.event(p) { | ||
14 | &mut Event::Start { kind: ref mut slot, ..} => { | ||
15 | *slot = kind; | ||
16 | } | ||
17 | _ => unreachable!(), | ||
18 | } | ||
19 | p.event(Event::Finish); | ||
20 | let result = CompleteMarker { pos: self.pos }; | ||
21 | ::std::mem::forget(self); | ||
22 | result | ||
23 | } | ||
24 | |||
25 | pub fn abandon(self, p: &mut Parser) { | ||
26 | let idx = self.pos as usize; | ||
27 | if idx == p.events.len() - 1 { | ||
28 | match p.events.pop() { | ||
29 | Some(Event::Start { kind: TOMBSTONE, forward_parent: None }) => (), | ||
30 | _ => unreachable!() | ||
31 | } | ||
32 | } | ||
33 | ::std::mem::forget(self); | ||
34 | } | ||
35 | |||
36 | fn event<'p>(&self, p: &'p mut Parser) -> &'p mut Event { | ||
37 | &mut p.events[self.idx()] | ||
38 | } | ||
39 | |||
40 | fn idx(&self) -> usize { | ||
41 | self.pos as usize | ||
42 | } | ||
43 | } | ||
44 | |||
45 | impl Drop for Marker { | ||
46 | fn drop(&mut self) { | ||
47 | if !::std::thread::panicking() { | ||
48 | panic!("Each marker should be eithe completed or abandoned"); | ||
49 | } | ||
50 | } | ||
51 | } | ||
52 | |||
53 | pub(crate) struct CompleteMarker { | ||
54 | pos: u32 | ||
55 | } | ||
56 | |||
57 | impl CompleteMarker { | ||
58 | pub(crate) fn precede(self, p: &mut Parser) -> Marker { | ||
59 | let m = p.start(); | ||
60 | match p.events[self.pos as usize] { | ||
61 | Event::Start { ref mut forward_parent, ..} => { | ||
62 | *forward_parent = Some(m.pos - self.pos); | ||
63 | } | ||
64 | _ => unreachable!(), | ||
65 | } | ||
66 | m | ||
67 | } | ||
68 | } | ||
6 | 69 | ||
7 | 70 | ||
8 | pub(crate) struct Parser<'t> { | 71 | pub(crate) struct Parser<'t> { |
@@ -19,12 +82,9 @@ pub(crate) struct Parser<'t> { | |||
19 | curly_limit: Option<i32>, | 82 | curly_limit: Option<i32>, |
20 | } | 83 | } |
21 | 84 | ||
22 | #[derive(Debug, Clone, Copy,PartialEq, Eq)] | 85 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
23 | pub(crate) struct Pos(u32); | 86 | pub(crate) struct Pos(u32); |
24 | 87 | ||
25 | #[derive(Debug, Clone, Copy,PartialEq, Eq)] | ||
26 | pub(crate) struct Mark(u32); | ||
27 | |||
28 | impl<'t> Parser<'t> { | 88 | impl<'t> Parser<'t> { |
29 | pub(crate) fn new(text: &'t str, raw_tokens: &'t [Token]) -> Parser<'t> { | 89 | pub(crate) fn new(text: &'t str, raw_tokens: &'t [Token]) -> Parser<'t> { |
30 | let mut tokens = Vec::new(); | 90 | let mut tokens = Vec::new(); |
@@ -50,31 +110,13 @@ impl<'t> Parser<'t> { | |||
50 | } | 110 | } |
51 | } | 111 | } |
52 | 112 | ||
53 | pub(crate) fn mark(&self) -> Mark { | ||
54 | Mark(self.events.len() as u32) | ||
55 | } | ||
56 | |||
57 | pub(crate) fn forward_parent(&mut self, child: Mark, parent: Mark) { | ||
58 | if child == parent || parent == self.mark() { | ||
59 | return | ||
60 | } | ||
61 | assert!(child.0 < parent.0); | ||
62 | let diff = parent.0 - child.0; | ||
63 | match self.events[child.0 as usize] { | ||
64 | Event::Start { ref mut forward_parent, .. } => { | ||
65 | *forward_parent = Some(diff); | ||
66 | } | ||
67 | _ => unreachable!() | ||
68 | } | ||
69 | } | ||
70 | |||
71 | pub(crate) fn pos(&self) -> Pos { | 113 | pub(crate) fn pos(&self) -> Pos { |
72 | Pos(self.pos as u32) | 114 | Pos(self.pos as u32) |
73 | } | 115 | } |
74 | 116 | ||
75 | pub(crate) fn into_events(self) -> Vec<Event> { | 117 | pub(crate) fn into_events(self) -> Vec<Event> { |
76 | assert!(self.curly_limit.is_none()); | 118 | assert!(self.curly_limit.is_none()); |
77 | assert!(self.current() == EOF); | 119 | assert_eq!(self.current(), EOF); |
78 | self.events | 120 | self.events |
79 | } | 121 | } |
80 | 122 | ||
@@ -85,18 +127,16 @@ impl<'t> Parser<'t> { | |||
85 | let token = self.tokens[self.pos]; | 127 | let token = self.tokens[self.pos]; |
86 | if let Some(limit) = self.curly_limit { | 128 | if let Some(limit) = self.curly_limit { |
87 | if limit == self.curly_level && token.kind == R_CURLY { | 129 | if limit == self.curly_level && token.kind == R_CURLY { |
88 | return EOF | 130 | return EOF; |
89 | } | 131 | } |
90 | } | 132 | } |
91 | token.kind | 133 | token.kind |
92 | } | 134 | } |
93 | 135 | ||
94 | pub(crate) fn start(&mut self, kind: SyntaxKind) { | 136 | pub(crate) fn start(&mut self) -> Marker { |
95 | self.event(Event::Start { kind, forward_parent: None }); | 137 | let m = Marker { pos: self.events.len() as u32 }; |
96 | } | 138 | self.event(Event::Start { kind: TOMBSTONE, forward_parent: None }); |
97 | 139 | m | |
98 | pub(crate) fn finish(&mut self) { | ||
99 | self.event(Event::Finish); | ||
100 | } | 140 | } |
101 | 141 | ||
102 | pub(crate) fn error<'p>(&'p mut self) -> ErrorBuilder<'p, 't> { | 142 | pub(crate) fn error<'p>(&'p mut self) -> ErrorBuilder<'p, 't> { |
@@ -124,20 +164,20 @@ impl<'t> Parser<'t> { | |||
124 | let old_level = self.curly_level; | 164 | let old_level = self.curly_level; |
125 | let old_limit = self.curly_limit; | 165 | let old_limit = self.curly_limit; |
126 | if !self.expect(L_CURLY) { | 166 | if !self.expect(L_CURLY) { |
127 | return false | 167 | return false; |
128 | } | 168 | } |
129 | self.curly_limit = Some(self.curly_level); | 169 | self.curly_limit = Some(self.curly_level); |
130 | f(self); | 170 | f(self); |
131 | assert!(self.curly_level > old_level); | 171 | assert!(self.curly_level > old_level); |
132 | self.curly_limit = old_limit; | 172 | self.curly_limit = old_limit; |
133 | if !self.expect(R_CURLY) { | 173 | if !self.expect(R_CURLY) { |
134 | self.start(ERROR); | 174 | let err = self.start(); |
135 | while self.curly_level > old_level { | 175 | while self.curly_level > old_level { |
136 | if self.bump() == EOF { | 176 | if self.bump() == EOF { |
137 | break; | 177 | break; |
138 | } | 178 | } |
139 | } | 179 | } |
140 | self.finish(); | 180 | err.complete(self, ERROR); |
141 | } | 181 | } |
142 | true | 182 | true |
143 | } | 183 | } |
@@ -149,7 +189,7 @@ impl<'t> Parser<'t> { | |||
149 | 189 | ||
150 | pub(crate) struct ErrorBuilder<'p, 't: 'p> { | 190 | pub(crate) struct ErrorBuilder<'p, 't: 'p> { |
151 | message: Option<String>, | 191 | message: Option<String>, |
152 | parser: &'p mut Parser<'t> | 192 | parser: &'p mut Parser<'t>, |
153 | } | 193 | } |
154 | 194 | ||
155 | impl<'t, 'p> ErrorBuilder<'p, 't> { | 195 | impl<'t, 'p> ErrorBuilder<'p, 't> { |
diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 0c29442f9..5ec4b8e93 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use {Token, File, FileBuilder, Sink, SyntaxKind}; | 1 | use {Token, File, FileBuilder, Sink, SyntaxKind}; |
2 | 2 | ||
3 | use syntax_kinds::*; | 3 | use syntax_kinds::*; |
4 | use tree::TOMBSTONE; | ||
4 | 5 | ||
5 | mod event_parser; | 6 | mod event_parser; |
6 | use self::event_parser::Event; | 7 | use self::event_parser::Event; |
@@ -29,6 +30,8 @@ fn from_events_to_file( | |||
29 | } | 30 | } |
30 | 31 | ||
31 | match event { | 32 | match event { |
33 | &Event::Start { kind: TOMBSTONE, .. } => (), | ||
34 | |||
32 | &Event::Start { .. } => { | 35 | &Event::Start { .. } => { |
33 | forward_parents.clear(); | 36 | forward_parents.clear(); |
34 | let mut idx = i; | 37 | let mut idx = i; |
@@ -62,7 +65,7 @@ fn from_events_to_file( | |||
62 | } | 65 | } |
63 | builder.finish_internal() | 66 | builder.finish_internal() |
64 | }, | 67 | }, |
65 | &Event::Token { kind, mut n_raw_tokens } => loop { | 68 | &Event::Token { kind: _, mut n_raw_tokens } => loop { |
66 | let token = tokens[idx]; | 69 | let token = tokens[idx]; |
67 | if !is_insignificant(token.kind) { | 70 | if !is_insignificant(token.kind) { |
68 | n_raw_tokens -= 1; | 71 | n_raw_tokens -= 1; |
diff --git a/src/tree/file_builder.rs b/src/tree/file_builder.rs index 37bd5b2c8..35702ddd7 100644 --- a/src/tree/file_builder.rs +++ b/src/tree/file_builder.rs | |||
@@ -48,7 +48,9 @@ impl Sink for FileBuilder { | |||
48 | } | 48 | } |
49 | 49 | ||
50 | fn finish_internal(&mut self) { | 50 | fn finish_internal(&mut self) { |
51 | let (id, _) = self.in_progress.pop().unwrap(); | 51 | let (id, _) = self.in_progress.pop().expect( |
52 | "trying to complete a node, but there are no in-progress nodes" | ||
53 | ); | ||
52 | if !self.in_progress.is_empty() { | 54 | if !self.in_progress.is_empty() { |
53 | self.add_len(id); | 55 | self.add_len(id); |
54 | } | 56 | } |
@@ -77,8 +79,8 @@ impl FileBuilder { | |||
77 | self.in_progress.iter().map(|&(idx, _)| self.nodes[idx].kind) | 79 | self.in_progress.iter().map(|&(idx, _)| self.nodes[idx].kind) |
78 | .collect::<Vec<_>>() | 80 | .collect::<Vec<_>>() |
79 | ); | 81 | ); |
80 | assert!( | 82 | assert_eq!( |
81 | self.pos == (self.text.len() as u32).into(), | 83 | self.pos, (self.text.len() as u32).into(), |
82 | "nodes in FileBuilder do not cover the whole file" | 84 | "nodes in FileBuilder do not cover the whole file" |
83 | ); | 85 | ); |
84 | File { | 86 | File { |
diff --git a/src/tree/mod.rs b/src/tree/mod.rs index d8f843737..3315b926e 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs | |||
@@ -10,17 +10,24 @@ pub use self::file_builder::{FileBuilder, Sink}; | |||
10 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 10 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
11 | pub struct SyntaxKind(pub(crate) u32); | 11 | pub struct SyntaxKind(pub(crate) u32); |
12 | 12 | ||
13 | pub(crate) const EOF: SyntaxKind = SyntaxKind(10000); | 13 | pub(crate) const EOF: SyntaxKind = SyntaxKind(!0); |
14 | pub(crate) const EOF_INFO: SyntaxInfo = SyntaxInfo { | 14 | pub(crate) const EOF_INFO: SyntaxInfo = SyntaxInfo { |
15 | name: "EOF" | 15 | name: "EOF" |
16 | }; | 16 | }; |
17 | 17 | ||
18 | pub(crate) const TOMBSTONE: SyntaxKind = SyntaxKind(!0 - 1); | ||
19 | pub(crate) const TOMBSTONE_INFO: SyntaxInfo = SyntaxInfo { | ||
20 | name: "TOMBSTONE" | ||
21 | }; | ||
22 | |||
23 | |||
18 | impl SyntaxKind { | 24 | impl SyntaxKind { |
19 | fn info(self) -> &'static SyntaxInfo { | 25 | fn info(self) -> &'static SyntaxInfo { |
20 | if self == EOF { | 26 | match self { |
21 | return &EOF_INFO; | 27 | EOF => &EOF_INFO, |
28 | TOMBSTONE => &TOMBSTONE_INFO, | ||
29 | _ => syntax_info(self), | ||
22 | } | 30 | } |
23 | syntax_info(self) | ||
24 | } | 31 | } |
25 | } | 32 | } |
26 | 33 | ||