aboutsummaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-07-31 21:38:19 +0100
committerAleksey Kladov <[email protected]>2018-07-31 21:44:31 +0100
commit7912189ec304b28c4df0030b5282cf3d21074154 (patch)
tree03a0a1b128439fdefbd1d012b392995ca8a6e264 /src/parser
parentd1400e95d7ad701fcba1191cb00968c2eae8b394 (diff)
reorganize
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/event.rs168
-rw-r--r--src/parser/grammar/attributes.rs79
-rw-r--r--src/parser/grammar/expressions.rs284
-rw-r--r--src/parser/grammar/items/consts.rs20
-rw-r--r--src/parser/grammar/items/mod.rs290
-rw-r--r--src/parser/grammar/items/structs.rs116
-rw-r--r--src/parser/grammar/items/traits.rs77
-rw-r--r--src/parser/grammar/items/use_item.rs66
-rw-r--r--src/parser/grammar/mod.rs144
-rw-r--r--src/parser/grammar/params.rs71
-rw-r--r--src/parser/grammar/paths.rs77
-rw-r--r--src/parser/grammar/patterns.rs53
-rw-r--r--src/parser/grammar/type_args.rs48
-rw-r--r--src/parser/grammar/type_params.rs96
-rw-r--r--src/parser/grammar/types.rs207
-rw-r--r--src/parser/input.rs71
-rw-r--r--src/parser/mod.rs24
-rw-r--r--src/parser/parser/imp.rs118
-rw-r--r--src/parser/parser/mod.rs141
-rw-r--r--src/parser/token_set.rs24
20 files changed, 0 insertions, 2174 deletions
diff --git a/src/parser/event.rs b/src/parser/event.rs
deleted file mode 100644
index 0086d32ea..000000000
--- a/src/parser/event.rs
+++ /dev/null
@@ -1,168 +0,0 @@
1//! This module provides a way to construct a `File`.
2//! It is intended to be completely decoupled from the
3//! parser, so as to allow to evolve the tree representation
4//! and the parser algorithm independently.
5//!
6//! The `Sink` trait is the bridge between the parser and the
7//! tree builder: the parser produces a stream of events like
8//! `start node`, `finish node`, and `FileBuilder` converts
9//! this stream to a real tree.
10use {
11 lexer::Token,
12 SyntaxKind::{self, TOMBSTONE},
13 TextUnit,
14};
15
16pub(crate) trait Sink {
17 type Tree;
18
19 fn new(text: String) -> Self;
20
21 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit);
22 fn start_internal(&mut self, kind: SyntaxKind);
23 fn finish_internal(&mut self);
24 fn error(&mut self, err: String);
25 fn finish(self) -> Self::Tree;
26}
27
28/// `Parser` produces a flat list of `Event`s.
29/// They are converted to a tree-structure in
30/// a separate pass, via `TreeBuilder`.
31#[derive(Debug)]
32pub(crate) enum Event {
33 /// This event signifies the start of the node.
34 /// It should be either abandoned (in which case the
35 /// `kind` is `TOMBSTONE`, and the event is ignored),
36 /// or completed via a `Finish` event.
37 ///
38 /// All tokens between a `Start` and a `Finish` would
39 /// become the children of the respective node.
40 ///
41 /// For left-recursive syntactic constructs, the parser produces
42 /// a child node before it sees a parent. `forward_parent`
43 /// exists to allow to tweak parent-child relationships.
44 ///
45 /// Consider this path
46 ///
47 /// foo::bar
48 ///
49 /// The events for it would look like this:
50 ///
51 ///
52 /// START(PATH) IDENT('foo') FINISH START(PATH) COLONCOLON IDENT('bar') FINISH
53 /// | /\
54 /// | |
55 /// +------forward-parent------+
56 ///
57 /// And the tree would look like this
58 ///
59 /// +--PATH---------+
60 /// | | |
61 /// | | |
62 /// | '::' 'bar'
63 /// |
64 /// PATH
65 /// |
66 /// 'foo'
67 ///
68 /// See also `CompletedMarker::precede`.
69 Start {
70 kind: SyntaxKind,
71 forward_parent: Option<u32>,
72 },
73
74 /// Complete the previous `Start` event
75 Finish,
76
77 /// Produce a single leaf-element.
78 /// `n_raw_tokens` is used to glue complex contextual tokens.
79 /// For example, lexer tokenizes `>>` as `>`, `>`, and
80 /// `n_raw_tokens = 2` is used to produced a single `>>`.
81 Token {
82 kind: SyntaxKind,
83 n_raw_tokens: u8,
84 },
85
86 Error {
87 msg: String,
88 },
89}
90
91pub(super) fn process(builder: &mut impl Sink, tokens: &[Token], events: Vec<Event>) {
92 let mut idx = 0;
93
94 let mut holes = Vec::new();
95 let mut forward_parents = Vec::new();
96
97 for (i, event) in events.iter().enumerate() {
98 if holes.last() == Some(&i) {
99 holes.pop();
100 continue;
101 }
102
103 match event {
104 &Event::Start {
105 kind: TOMBSTONE, ..
106 } => (),
107
108 &Event::Start { .. } => {
109 forward_parents.clear();
110 let mut idx = i;
111 loop {
112 let (kind, fwd) = match events[idx] {
113 Event::Start {
114 kind,
115 forward_parent,
116 } => (kind, forward_parent),
117 _ => unreachable!(),
118 };
119 forward_parents.push((idx, kind));
120 if let Some(fwd) = fwd {
121 idx += fwd as usize;
122 } else {
123 break;
124 }
125 }
126 for &(idx, kind) in forward_parents.iter().into_iter().rev() {
127 builder.start_internal(kind);
128 holes.push(idx);
129 }
130 holes.pop();
131 }
132 &Event::Finish => {
133 while idx < tokens.len() {
134 let token = tokens[idx];
135 if token.kind.is_trivia() {
136 idx += 1;
137 builder.leaf(token.kind, token.len);
138 } else {
139 break;
140 }
141 }
142 builder.finish_internal()
143 }
144 &Event::Token {
145 kind,
146 mut n_raw_tokens,
147 } => {
148 // FIXME: currently, we attach whitespace to some random node
149 // this should be done in a sensible manner instead
150 loop {
151 let token = tokens[idx];
152 if !token.kind.is_trivia() {
153 break;
154 }
155 builder.leaf(token.kind, token.len);
156 idx += 1
157 }
158 let mut len = 0.into();
159 for _ in 0..n_raw_tokens {
160 len += tokens[idx].len;
161 idx += 1;
162 }
163 builder.leaf(kind, len);
164 }
165 &Event::Error { ref msg } => builder.error(msg.clone()),
166 }
167 }
168}
diff --git a/src/parser/grammar/attributes.rs b/src/parser/grammar/attributes.rs
deleted file mode 100644
index c411d4d7f..000000000
--- a/src/parser/grammar/attributes.rs
+++ /dev/null
@@ -1,79 +0,0 @@
1use super::*;
2
3pub(super) fn inner_attributes(p: &mut Parser) {
4 while p.current() == POUND && p.nth(1) == EXCL {
5 attribute(p, true)
6 }
7}
8
9pub(super) fn outer_attributes(p: &mut Parser) {
10 while p.at(POUND) {
11 attribute(p, false)
12 }
13}
14
15fn attribute(p: &mut Parser, inner: bool) {
16 let attr = p.start();
17 assert!(p.at(POUND));
18 p.bump();
19
20 if inner {
21 assert!(p.at(EXCL));
22 p.bump();
23 }
24
25 if p.expect(L_BRACK) {
26 meta_item(p);
27 p.expect(R_BRACK);
28 }
29 attr.complete(p, ATTR);
30}
31
32fn meta_item(p: &mut Parser) {
33 if p.at(IDENT) {
34 let meta_item = p.start();
35 p.bump();
36 match p.current() {
37 EQ => {
38 p.bump();
39 if expressions::literal(p).is_none() {
40 p.error("expected literal");
41 }
42 }
43 L_PAREN => meta_item_arg_list(p),
44 _ => (),
45 }
46 meta_item.complete(p, META_ITEM);
47 } else {
48 p.error("expected attribute value");
49 }
50}
51
52fn meta_item_arg_list(p: &mut Parser) {
53 assert!(p.at(L_PAREN));
54 p.bump();
55 loop {
56 match p.current() {
57 EOF | R_PAREN => break,
58 IDENT => meta_item(p),
59 c => if expressions::literal(p).is_none() {
60 let message = "expected attribute";
61
62 if items::ITEM_FIRST.contains(c) {
63 p.error(message);
64 return;
65 }
66
67 let err = p.start();
68 p.error(message);
69 p.bump();
70 err.complete(p, ERROR);
71 continue;
72 },
73 }
74 if !p.at(R_PAREN) {
75 p.expect(COMMA);
76 }
77 }
78 p.expect(R_PAREN);
79}
diff --git a/src/parser/grammar/expressions.rs b/src/parser/grammar/expressions.rs
deleted file mode 100644
index 06f9105c6..000000000
--- a/src/parser/grammar/expressions.rs
+++ /dev/null
@@ -1,284 +0,0 @@
1use super::*;
2
3// test expr_literals
4// fn foo() {
5// let _ = true;
6// let _ = false;
7// let _ = 1;
8// let _ = 2.0;
9// let _ = b'a';
10// let _ = 'b';
11// let _ = "c";
12// let _ = r"d";
13// let _ = b"e";
14// let _ = br"f";
15// }
16pub(super) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
17 match p.current() {
18 TRUE_KW | FALSE_KW | INT_NUMBER | FLOAT_NUMBER | BYTE | CHAR | STRING | RAW_STRING
19 | BYTE_STRING | RAW_BYTE_STRING => {
20 let m = p.start();
21 p.bump();
22 Some(m.complete(p, LITERAL))
23 }
24 _ => None,
25 }
26}
27
28pub(super) fn expr(p: &mut Parser) {
29 let mut lhs = match prefix_expr(p) {
30 Some(lhs) => lhs,
31 None => return,
32 };
33
34 loop {
35 lhs = match p.current() {
36 L_PAREN => call_expr(p, lhs),
37 DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN {
38 method_call_expr(p, lhs)
39 } else {
40 field_expr(p, lhs)
41 },
42 _ => break,
43 }
44 }
45}
46
47// test block
48// fn a() {}
49// fn b() { let _ = 1; }
50// fn c() { 1; 2; }
51// fn d() { 1; 2 }
52pub(super) fn block(p: &mut Parser) {
53 if !p.at(L_CURLY) {
54 p.error("expected block");
55 }
56 let m = p.start();
57 p.bump();
58 while !p.at(EOF) && !p.at(R_CURLY) {
59 match p.current() {
60 LET_KW => let_stmt(p),
61 c => {
62 // test block_items
63 // fn a() { fn b() {} }
64 if items::ITEM_FIRST.contains(c) {
65 items::item(p)
66 } else {
67 let expr_stmt = p.start();
68 expressions::expr(p);
69 if p.eat(SEMI) {
70 expr_stmt.complete(p, EXPR_STMT);
71 } else {
72 expr_stmt.abandon(p);
73 }
74 }
75 }
76 }
77 }
78 p.expect(R_CURLY);
79 m.complete(p, BLOCK);
80}
81
82// test let_stmt;
83// fn foo() {
84// let a;
85// let b: i32;
86// let c = 92;
87// let d: i32 = 92;
88// }
89fn let_stmt(p: &mut Parser) {
90 assert!(p.at(LET_KW));
91 let m = p.start();
92 p.bump();
93 patterns::pattern(p);
94 if p.at(COLON) {
95 types::ascription(p);
96 }
97 if p.eat(EQ) {
98 expressions::expr(p);
99 }
100 p.expect(SEMI);
101 m.complete(p, LET_STMT);
102}
103
104fn prefix_expr(p: &mut Parser) -> Option<CompletedMarker> {
105 match p.current() {
106 AMPERSAND => Some(ref_expr(p)),
107 STAR => Some(deref_expr(p)),
108 _ => atom_expr(p),
109 }
110}
111
112// test ref_expr
113// fn foo() {
114// let _ = &1;
115// let _ = &mut &f();
116// }
117fn ref_expr(p: &mut Parser) -> CompletedMarker {
118 assert!(p.at(AMPERSAND));
119 let m = p.start();
120 p.bump();
121 p.eat(MUT_KW);
122 expr(p);
123 m.complete(p, REF_EXPR)
124}
125
126// test deref_expr
127// fn foo() {
128// **&1;
129// }
130fn deref_expr(p: &mut Parser) -> CompletedMarker {
131 assert!(p.at(STAR));
132 let m = p.start();
133 p.bump();
134 expr(p);
135 m.complete(p, DEREF_EXPR)
136}
137
138fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> {
139 match literal(p) {
140 Some(m) => return Some(m),
141 None => (),
142 }
143 if paths::is_path_start(p) {
144 return Some(path_expr(p));
145 }
146
147 match p.current() {
148 L_PAREN => Some(tuple_expr(p)),
149 PIPE => Some(lambda_expr(p)),
150 _ => {
151 p.err_and_bump("expected expression");
152 None
153 }
154 }
155}
156
157fn tuple_expr(p: &mut Parser) -> CompletedMarker {
158 assert!(p.at(L_PAREN));
159 let m = p.start();
160 p.expect(L_PAREN);
161 p.expect(R_PAREN);
162 m.complete(p, TUPLE_EXPR)
163}
164
165// test lambda_expr
166// fn foo() {
167// || ();
168// || -> i32 { 92 };
169// |x| x;
170// |x: i32,| x;
171// }
172fn lambda_expr(p: &mut Parser) -> CompletedMarker {
173 assert!(p.at(PIPE));
174 let m = p.start();
175 params::param_list_opt_types(p);
176 if fn_ret_type(p) {
177 block(p);
178 } else {
179 expr(p)
180 }
181 m.complete(p, LAMBDA_EXPR)
182}
183
184// test call_expr
185// fn foo() {
186// let _ = f();
187// let _ = f()(1)(1, 2,);
188// }
189fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
190 assert!(p.at(L_PAREN));
191 let m = lhs.precede(p);
192 arg_list(p);
193 m.complete(p, CALL_EXPR)
194}
195
196// test method_call_expr
197// fn foo() {
198// x.foo();
199// y.bar(1, 2,);
200// }
201fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
202 assert!(p.at(DOT) && p.nth(1) == IDENT && p.nth(2) == L_PAREN);
203 let m = lhs.precede(p);
204 p.bump();
205 p.bump();
206 arg_list(p);
207 m.complete(p, METHOD_CALL_EXPR)
208}
209
210// test field_expr
211// fn foo() {
212// x.foo.bar;
213// }
214fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
215 assert!(p.at(DOT) && p.nth(1) == IDENT);
216 let m = lhs.precede(p);
217 p.bump();
218 p.bump();
219 m.complete(p, FIELD_EXPR)
220}
221
222fn arg_list(p: &mut Parser) {
223 assert!(p.at(L_PAREN));
224 let m = p.start();
225 p.bump();
226 while !p.at(R_PAREN) && !p.at(EOF) {
227 expr(p);
228 if !p.at(R_PAREN) && !p.expect(COMMA) {
229 break;
230 }
231 }
232 p.eat(R_PAREN);
233 m.complete(p, ARG_LIST);
234}
235
236// test path_expr
237// fn foo() {
238// let _ = a;
239// let _ = a::b;
240// let _ = ::a::<b>;
241// }
242fn path_expr(p: &mut Parser) -> CompletedMarker {
243 assert!(paths::is_path_start(p));
244 let m = p.start();
245 paths::expr_path(p);
246 if p.at(L_CURLY) {
247 struct_lit(p);
248 m.complete(p, STRUCT_LIT)
249 } else {
250 m.complete(p, PATH_EXPR)
251 }
252}
253
254// test struct_lit
255// fn foo() {
256// S {};
257// S { x, y: 32, };
258// S { x, y: 32, ..Default::default() };
259// }
260fn struct_lit(p: &mut Parser) {
261 assert!(p.at(L_CURLY));
262 p.bump();
263 while !p.at(EOF) && !p.at(R_CURLY) {
264 match p.current() {
265 IDENT => {
266 let m = p.start();
267 name_ref(p);
268 if p.eat(COLON) {
269 expr(p);
270 }
271 m.complete(p, STRUCT_LIT_FIELD);
272 }
273 DOTDOT => {
274 p.bump();
275 expr(p);
276 }
277 _ => p.err_and_bump("expected identifier"),
278 }
279 if !p.at(R_CURLY) {
280 p.expect(COMMA);
281 }
282 }
283 p.expect(R_CURLY);
284}
diff --git a/src/parser/grammar/items/consts.rs b/src/parser/grammar/items/consts.rs
deleted file mode 100644
index ca26a7814..000000000
--- a/src/parser/grammar/items/consts.rs
+++ /dev/null
@@ -1,20 +0,0 @@
1use super::*;
2
3pub(super) fn static_item(p: &mut Parser) {
4 const_or_static(p, STATIC_KW)
5}
6
7pub(super) fn const_item(p: &mut Parser) {
8 const_or_static(p, CONST_KW)
9}
10
11fn const_or_static(p: &mut Parser, kw: SyntaxKind) {
12 assert!(p.at(kw));
13 p.bump();
14 p.eat(MUT_KW); // TODO: validator to forbid const mut
15 name(p);
16 types::ascription(p);
17 p.expect(EQ);
18 expressions::expr(p);
19 p.expect(SEMI);
20}
diff --git a/src/parser/grammar/items/mod.rs b/src/parser/grammar/items/mod.rs
deleted file mode 100644
index d5f75f13d..000000000
--- a/src/parser/grammar/items/mod.rs
+++ /dev/null
@@ -1,290 +0,0 @@
1use super::*;
2
3mod consts;
4mod structs;
5mod traits;
6mod use_item;
7
8pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
9 attributes::inner_attributes(p);
10 while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) {
11 item(p);
12 }
13}
14
15pub(super) const ITEM_FIRST: TokenSet =
16 token_set![EXTERN_KW, MOD_KW, USE_KW, STRUCT_KW, ENUM_KW, FN_KW, PUB_KW, POUND];
17
18pub(super) fn item(p: &mut Parser) {
19 let item = p.start();
20 attributes::outer_attributes(p);
21 visibility(p);
22 let la = p.nth(1);
23 let item_kind = match p.current() {
24 USE_KW => {
25 use_item::use_item(p);
26 USE_ITEM
27 }
28 // test extern_crate
29 // extern crate foo;
30 EXTERN_KW if la == CRATE_KW => {
31 extern_crate_item(p);
32 EXTERN_CRATE_ITEM
33 }
34 EXTERN_KW => {
35 abi(p);
36 match p.current() {
37 // test extern_fn
38 // extern fn foo() {}
39 FN_KW => {
40 fn_item(p);
41 FN_ITEM
42 }
43 // test extern_block
44 // extern {}
45 L_CURLY => {
46 extern_block(p);
47 EXTERN_BLOCK
48 }
49 // test extern_struct
50 // extern struct Foo;
51 _ => {
52 item.abandon(p);
53 p.error("expected `fn` or `{`");
54 return;
55 }
56 }
57 }
58 STATIC_KW => {
59 consts::static_item(p);
60 STATIC_ITEM
61 }
62 CONST_KW => match p.nth(1) {
63 // test const_fn
64 // const fn foo() {}
65 FN_KW => {
66 p.bump();
67 fn_item(p);
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 }
156 // test auto_trait
157 // auto trait T {}
158 IDENT if p.at_contextual_kw("auto") && la == TRAIT_KW => {
159 p.bump_remap(AUTO_KW);
160 traits::trait_item(p);
161 TRAIT_ITEM
162 }
163 IMPL_KW => {
164 traits::impl_item(p);
165 IMPL_ITEM
166 }
167 // test default_impl
168 // default impl Foo {}
169 IDENT if p.at_contextual_kw("default") && la == IMPL_KW => {
170 p.bump_remap(DEFAULT_KW);
171 traits::impl_item(p);
172 IMPL_ITEM
173 }
174
175 FN_KW => {
176 fn_item(p);
177 FN_ITEM
178 }
179 TYPE_KW => {
180 type_item(p);
181 TYPE_ITEM
182 }
183 MOD_KW => {
184 mod_item(p);
185 MOD_ITEM
186 }
187 STRUCT_KW => {
188 structs::struct_item(p);
189 STRUCT_ITEM
190 }
191 ENUM_KW => {
192 structs::enum_item(p);
193 ENUM_ITEM
194 }
195 L_CURLY => {
196 item.abandon(p);
197 error_block(p, "expected item");
198 return;
199 }
200 err_token => {
201 item.abandon(p);
202 let message = if err_token == SEMI {
203 //TODO: if the item is incomplete, this message is misleading
204 "expected item, found `;`\n\
205 consider removing this semicolon"
206 } else {
207 "expected item"
208 };
209 p.err_and_bump(message);
210 return;
211 }
212 };
213 item.complete(p, item_kind);
214}
215
216fn extern_crate_item(p: &mut Parser) {
217 assert!(p.at(EXTERN_KW));
218 p.bump();
219 assert!(p.at(CRATE_KW));
220 p.bump();
221 name(p);
222 alias(p);
223 p.expect(SEMI);
224}
225
226fn extern_block(p: &mut Parser) {
227 assert!(p.at(L_CURLY));
228 p.bump();
229 p.expect(R_CURLY);
230}
231
232fn fn_item(p: &mut Parser) {
233 assert!(p.at(FN_KW));
234 p.bump();
235
236 name(p);
237 // test fn_item_type_params
238 // fn foo<T: Clone + Copy>(){}
239 type_params::type_param_list(p);
240
241 if p.at(L_PAREN) {
242 params::param_list(p);
243 } else {
244 p.error("expected function arguments");
245 }
246 // test fn_item_ret_type
247 // fn foo() {}
248 // fn bar() -> () {}
249 fn_ret_type(p);
250
251 // test fn_item_where_clause
252 // fn foo<T>() where T: Copy {}
253 type_params::where_clause(p);
254
255 expressions::block(p);
256}
257
258// test type_item
259// type Foo = Bar;
260fn type_item(p: &mut Parser) {
261 assert!(p.at(TYPE_KW));
262 p.bump();
263
264 name(p);
265
266 // test type_item_type_params
267 // type Result<T> = ();
268 type_params::type_param_list(p);
269
270 // test type_item_where_clause
271 // type Foo where Foo: Copy = ();
272 type_params::where_clause(p);
273
274 p.expect(EQ);
275 types::type_(p);
276 p.expect(SEMI);
277}
278
279fn mod_item(p: &mut Parser) {
280 assert!(p.at(MOD_KW));
281 p.bump();
282
283 name(p);
284 if !p.eat(SEMI) {
285 if p.expect(L_CURLY) {
286 mod_contents(p, true);
287 p.expect(R_CURLY);
288 }
289 }
290}
diff --git a/src/parser/grammar/items/structs.rs b/src/parser/grammar/items/structs.rs
deleted file mode 100644
index 7ced542a4..000000000
--- a/src/parser/grammar/items/structs.rs
+++ /dev/null
@@ -1,116 +0,0 @@
1use super::*;
2
3pub(super) fn struct_item(p: &mut Parser) {
4 assert!(p.at(STRUCT_KW));
5 p.bump();
6
7 name(p);
8 type_params::type_param_list(p);
9 match p.current() {
10 WHERE_KW => {
11 type_params::where_clause(p);
12 match p.current() {
13 SEMI => {
14 p.bump();
15 return;
16 }
17 L_CURLY => named_fields(p),
18 _ => {
19 //TODO: special case `(` error message
20 p.error("expected `;` or `{`");
21 return;
22 }
23 }
24 }
25 SEMI => {
26 p.bump();
27 return;
28 }
29 L_CURLY => named_fields(p),
30 L_PAREN => {
31 pos_fields(p);
32 p.expect(SEMI);
33 }
34 _ => {
35 p.error("expected `;`, `{`, or `(`");
36 return;
37 }
38 }
39}
40
41pub(super) fn enum_item(p: &mut Parser) {
42 assert!(p.at(ENUM_KW));
43 p.bump();
44 name(p);
45 type_params::type_param_list(p);
46 type_params::where_clause(p);
47 if p.expect(L_CURLY) {
48 while !p.at(EOF) && !p.at(R_CURLY) {
49 let var = p.start();
50 attributes::outer_attributes(p);
51 if p.at(IDENT) {
52 p.bump();
53 match p.current() {
54 L_CURLY => named_fields(p),
55 L_PAREN => pos_fields(p),
56 EQ => {
57 p.bump();
58 expressions::expr(p);
59 }
60 _ => (),
61 }
62 var.complete(p, ENUM_VARIANT);
63 } else {
64 var.abandon(p);
65 p.err_and_bump("expected enum variant");
66 }
67 if !p.at(R_CURLY) {
68 p.expect(COMMA);
69 }
70 }
71 p.expect(R_CURLY);
72 }
73}
74
75fn named_fields(p: &mut Parser) {
76 assert!(p.at(L_CURLY));
77 p.bump();
78 while !p.at(R_CURLY) && !p.at(EOF) {
79 named_field(p);
80 if !p.at(R_CURLY) {
81 p.expect(COMMA);
82 }
83 }
84 p.expect(R_CURLY);
85
86 fn named_field(p: &mut Parser) {
87 let field = p.start();
88 visibility(p);
89 if p.at(IDENT) {
90 name(p);
91 p.expect(COLON);
92 types::type_(p);
93 field.complete(p, NAMED_FIELD);
94 } else {
95 field.abandon(p);
96 p.err_and_bump("expected field declaration");
97 }
98 }
99}
100
101fn pos_fields(p: &mut Parser) {
102 if !p.expect(L_PAREN) {
103 return;
104 }
105 while !p.at(R_PAREN) && !p.at(EOF) {
106 let pos_field = p.start();
107 visibility(p);
108 types::type_(p);
109 pos_field.complete(p, POS_FIELD);
110
111 if !p.at(R_PAREN) {
112 p.expect(COMMA);
113 }
114 }
115 p.expect(R_PAREN);
116}
diff --git a/src/parser/grammar/items/traits.rs b/src/parser/grammar/items/traits.rs
deleted file mode 100644
index bda13e565..000000000
--- a/src/parser/grammar/items/traits.rs
+++ /dev/null
@@ -1,77 +0,0 @@
1use super::*;
2
3// test trait_item
4// trait T<U>: Hash + Clone where U: Copy {}
5pub(super) fn trait_item(p: &mut Parser) {
6 assert!(p.at(TRAIT_KW));
7 p.bump();
8 name(p);
9 type_params::type_param_list(p);
10 if p.at(COLON) {
11 type_params::bounds(p);
12 }
13 type_params::where_clause(p);
14 p.expect(L_CURLY);
15 p.expect(R_CURLY);
16}
17
18// test impl_item
19// impl Foo {}
20pub(super) fn impl_item(p: &mut Parser) {
21 assert!(p.at(IMPL_KW));
22 p.bump();
23 if choose_type_params_over_qpath(p) {
24 type_params::type_param_list(p);
25 }
26
27 // TODO: never type
28 // impl ! {}
29
30 // test impl_item_neg
31 // impl !Send for X {}
32 p.eat(EXCL);
33 types::type_(p);
34 if p.eat(FOR_KW) {
35 types::type_(p);
36 }
37 type_params::where_clause(p);
38 p.expect(L_CURLY);
39
40 // test impl_item_items
41 // impl F {
42 // type A = i32;
43 // const B: i32 = 92;
44 // fn foo() {}
45 // fn bar(&self) {}
46 // }
47 while !p.at(EOF) && !p.at(R_CURLY) {
48 item(p);
49 }
50 p.expect(R_CURLY);
51}
52
53fn choose_type_params_over_qpath(p: &Parser) -> bool {
54 // There's an ambiguity between generic parameters and qualified paths in impls.
55 // If we see `<` it may start both, so we have to inspect some following tokens.
56 // The following combinations can only start generics,
57 // but not qualified paths (with one exception):
58 // `<` `>` - empty generic parameters
59 // `<` `#` - generic parameters with attributes
60 // `<` (LIFETIME|IDENT) `>` - single generic parameter
61 // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
62 // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
63 // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
64 // The only truly ambiguous case is
65 // `<` IDENT `>` `::` IDENT ...
66 // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
67 // because this is what almost always expected in practice, qualified paths in impls
68 // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
69 if !p.at(L_ANGLE) {
70 return false;
71 }
72 if p.nth(1) == POUND || p.nth(1) == R_ANGLE {
73 return true;
74 }
75 (p.nth(1) == LIFETIME || p.nth(1) == IDENT)
76 && (p.nth(2) == R_ANGLE || p.nth(2) == COMMA || p.nth(2) == COLON || p.nth(2) == EQ)
77}
diff --git a/src/parser/grammar/items/use_item.rs b/src/parser/grammar/items/use_item.rs
deleted file mode 100644
index a3f7f0da8..000000000
--- a/src/parser/grammar/items/use_item.rs
+++ /dev/null
@@ -1,66 +0,0 @@
1use super::*;
2
3pub(super) fn use_item(p: &mut Parser) {
4 assert!(p.at(USE_KW));
5 p.bump();
6 use_tree(p);
7 p.expect(SEMI);
8}
9
10fn use_tree(p: &mut Parser) {
11 let la = p.nth(1);
12 let m = p.start();
13 match (p.current(), la) {
14 (STAR, _) => p.bump(),
15 (COLONCOLON, STAR) => {
16 p.bump();
17 p.bump();
18 }
19 (L_CURLY, _) | (COLONCOLON, L_CURLY) => {
20 if p.at(COLONCOLON) {
21 p.bump();
22 }
23 nested_trees(p);
24 }
25 _ if paths::is_path_start(p) => {
26 paths::use_path(p);
27 match p.current() {
28 AS_KW => {
29 alias(p);
30 }
31 COLONCOLON => {
32 p.bump();
33 match p.current() {
34 STAR => {
35 p.bump();
36 }
37 L_CURLY => nested_trees(p),
38 _ => {
39 // is this unreachable?
40 p.error("expected `{` or `*`");
41 }
42 }
43 }
44 _ => (),
45 }
46 }
47 _ => {
48 m.abandon(p);
49 p.err_and_bump("expected one of `*`, `::`, `{`, `self`, `super`, `indent`");
50 return;
51 }
52 }
53 m.complete(p, USE_TREE);
54}
55
56fn nested_trees(p: &mut Parser) {
57 assert!(p.at(L_CURLY));
58 p.bump();
59 while !p.at(EOF) && !p.at(R_CURLY) {
60 use_tree(p);
61 if !p.at(R_CURLY) {
62 p.expect(COMMA);
63 }
64 }
65 p.expect(R_CURLY);
66}
diff --git a/src/parser/grammar/mod.rs b/src/parser/grammar/mod.rs
deleted file mode 100644
index d4f9b80cf..000000000
--- a/src/parser/grammar/mod.rs
+++ /dev/null
@@ -1,144 +0,0 @@
1//! This is the actual "grammar" of the Rust language.
2//!
3//! Each function in this module and its children corresponds
4//! to a production of the format grammar. Submodules roughly
5//! correspond to different *areas* of the grammar. By convention,
6//! each submodule starts with `use super::*` import and exports
7//! "public" productions via `pub(super)`.
8//!
9//! See docs for `Parser` to learn about API, available to the grammar,
10//! and see docs for `Event` to learn how this actually manages to
11//! produce parse trees.
12//!
13//! Code in this module also contains inline tests, which start with
14//! `// test name-of-the-test` comment and look like this:
15//!
16//! ```
17//! // test fn_item_with_zero_parameters
18//! // fn foo() {}
19//! ```
20//!
21//! After adding a new inline-test, run `cargo collect-tests` to extract
22//! it as a standalone text-fixture into `tests/data/parser/inline`, and
23//! run `cargo test` once to create the "gold" value.
24mod attributes;
25mod expressions;
26mod items;
27mod paths;
28mod patterns;
29mod params;
30mod type_params;
31mod type_args;
32mod types;
33
34use {
35 parser::{
36 parser::{CompletedMarker, Parser},
37 token_set::TokenSet,
38 },
39 SyntaxKind::{self, *},
40};
41
42pub(crate) fn file(p: &mut Parser) {
43 let file = p.start();
44 p.eat(SHEBANG);
45 items::mod_contents(p, false);
46 file.complete(p, FILE);
47}
48
49fn visibility(p: &mut Parser) {
50 if p.at(PUB_KW) {
51 let vis = p.start();
52 p.bump();
53 if p.at(L_PAREN) {
54 match p.nth(1) {
55 // test crate_visibility
56 // pub(crate) struct S;
57 // pub(self) struct S;
58 // pub(self) struct S;
59 // pub(self) struct S;
60 CRATE_KW | SELF_KW | SUPER_KW => {
61 p.bump();
62 p.bump();
63 p.expect(R_PAREN);
64 }
65 IN_KW => {
66 p.bump();
67 p.bump();
68 paths::use_path(p);
69 p.expect(R_PAREN);
70 }
71 _ => (),
72 }
73 }
74 vis.complete(p, VISIBILITY);
75 }
76}
77
78fn alias(p: &mut Parser) -> bool {
79 if p.at(AS_KW) {
80 let alias = p.start();
81 p.bump();
82 name(p);
83 alias.complete(p, ALIAS);
84 }
85 true //FIXME: return false if three are errors
86}
87
88fn abi(p: &mut Parser) {
89 assert!(p.at(EXTERN_KW));
90 let abi = p.start();
91 p.bump();
92 match p.current() {
93 STRING | RAW_STRING => p.bump(),
94 _ => (),
95 }
96 abi.complete(p, ABI);
97}
98
99fn fn_ret_type(p: &mut Parser) -> bool {
100 if p.at(THIN_ARROW) {
101 p.bump();
102 types::type_(p);
103 true
104 } else {
105 false
106 }
107}
108
109fn name(p: &mut Parser) {
110 if p.at(IDENT) {
111 let m = p.start();
112 p.bump();
113 m.complete(p, NAME);
114 } else {
115 p.error("expected a name");
116 }
117}
118
119fn name_ref(p: &mut Parser) {
120 if p.at(IDENT) {
121 let m = p.start();
122 p.bump();
123 m.complete(p, NAME_REF);
124 } else {
125 p.error("expected identifier");
126 }
127}
128
129fn error_block(p: &mut Parser, message: &str) {
130 assert!(p.at(L_CURLY));
131 let err = p.start();
132 p.error(message);
133 p.bump();
134 let mut level: u32 = 1;
135 while level > 0 && !p.at(EOF) {
136 match p.current() {
137 L_CURLY => level += 1,
138 R_CURLY => level -= 1,
139 _ => (),
140 }
141 p.bump();
142 }
143 err.complete(p, ERROR);
144}
diff --git a/src/parser/grammar/params.rs b/src/parser/grammar/params.rs
deleted file mode 100644
index efa882394..000000000
--- a/src/parser/grammar/params.rs
+++ /dev/null
@@ -1,71 +0,0 @@
1use super::*;
2
3// test param_list
4// fn a() {}
5// fn b(x: i32) {}
6// fn c(x: i32, ) {}
7// fn d(x: i32, y: ()) {}
8pub(super) fn param_list(p: &mut Parser) {
9 list_(p, true)
10}
11
12pub(super) fn param_list_opt_types(p: &mut Parser) {
13 list_(p, false)
14}
15
16fn list_(p: &mut Parser, require_types: bool) {
17 assert!(p.at(if require_types { L_PAREN } else { PIPE }));
18 let m = p.start();
19 p.bump();
20 if require_types {
21 self_param(p);
22 }
23 let terminator = if require_types { R_PAREN } else { PIPE };
24 while !p.at(EOF) && !p.at(terminator) {
25 value_parameter(p, require_types);
26 if !p.at(terminator) {
27 p.expect(COMMA);
28 }
29 }
30 p.expect(terminator);
31 m.complete(p, PARAM_LIST);
32}
33
34fn value_parameter(p: &mut Parser, require_type: bool) {
35 let m = p.start();
36 patterns::pattern(p);
37 if p.at(COLON) || require_type {
38 types::ascription(p)
39 }
40 m.complete(p, PARAM);
41}
42
43// test self_param
44// impl S {
45// fn a(self) {}
46// fn b(&self,) {}
47// fn c(&'a self,) {}
48// fn d(&'a mut self, x: i32) {}
49// }
50fn self_param(p: &mut Parser) {
51 let la1 = p.nth(1);
52 let la2 = p.nth(2);
53 let la3 = p.nth(3);
54 let n_toks = match (p.current(), la1, la2, la3) {
55 (SELF_KW, _, _, _) => 1,
56 (AMPERSAND, SELF_KW, _, _) => 2,
57 (AMPERSAND, MUT_KW, SELF_KW, _) => 3,
58 (AMPERSAND, LIFETIME, SELF_KW, _) => 3,
59 (AMPERSAND, LIFETIME, MUT_KW, SELF_KW) => 4,
60 _ => return,
61 };
62 let m = p.start();
63 for _ in 0..n_toks {
64 p.bump();
65 }
66 m.complete(p, SELF_PARAM);
67 if !p.at(R_PAREN) {
68 p.expect(COMMA);
69 }
70}
71
diff --git a/src/parser/grammar/paths.rs b/src/parser/grammar/paths.rs
deleted file mode 100644
index fe69db096..000000000
--- a/src/parser/grammar/paths.rs
+++ /dev/null
@@ -1,77 +0,0 @@
1use super::*;
2
3pub(super) fn is_path_start(p: &Parser) -> bool {
4 match p.current() {
5 IDENT | SELF_KW | SUPER_KW | COLONCOLON => true,
6 _ => false,
7 }
8}
9
10pub(super) fn use_path(p: &mut Parser) {
11 path(p, Mode::Use)
12}
13
14pub(super) fn type_path(p: &mut Parser) {
15 path(p, Mode::Type)
16}
17
18pub(super) fn expr_path(p: &mut Parser) {
19 path(p, Mode::Expr)
20}
21
22#[derive(Clone, Copy, Eq, PartialEq)]
23enum Mode {
24 Use,
25 Type,
26 Expr,
27}
28
29fn path(p: &mut Parser, mode: Mode) {
30 if !is_path_start(p) {
31 return;
32 }
33 let path = p.start();
34 path_segment(p, mode, true);
35 let mut qual = path.complete(p, PATH);
36 loop {
37 let use_tree = match p.nth(1) {
38 STAR | L_CURLY => true,
39 _ => false,
40 };
41 if p.at(COLONCOLON) && !use_tree {
42 let path = qual.precede(p);
43 p.bump();
44 path_segment(p, mode, false);
45 let path = path.complete(p, PATH);
46 qual = path;
47 } else {
48 break;
49 }
50 }
51}
52
53fn path_segment(p: &mut Parser, mode: Mode, first: bool) {
54 let segment = p.start();
55 if first {
56 p.eat(COLONCOLON);
57 }
58 match p.current() {
59 IDENT => {
60 name_ref(p);
61 path_generic_args(p, mode);
62 }
63 SELF_KW | SUPER_KW => p.bump(),
64 _ => {
65 p.error("expected identifier");
66 }
67 };
68 segment.complete(p, PATH_SEGMENT);
69}
70
71fn path_generic_args(p: &mut Parser, mode: Mode) {
72 match mode {
73 Mode::Use => return,
74 Mode::Type => type_args::type_arg_list(p, false),
75 Mode::Expr => type_args::type_arg_list(p, true),
76 }
77}
diff --git a/src/parser/grammar/patterns.rs b/src/parser/grammar/patterns.rs
deleted file mode 100644
index 7216807fd..000000000
--- a/src/parser/grammar/patterns.rs
+++ /dev/null
@@ -1,53 +0,0 @@
1use super::*;
2
3pub(super) fn pattern(p: &mut Parser) {
4 match p.current() {
5 UNDERSCORE => placeholder_pat(p),
6 AMPERSAND => ref_pat(p),
7 IDENT | REF_KW | MUT_KW => bind_pat(p),
8 _ => p.err_and_bump("expected pattern"),
9 }
10}
11
12// test placeholder_pat
13// fn main() { let _ = (); }
14fn placeholder_pat(p: &mut Parser) {
15 assert!(p.at(UNDERSCORE));
16 let m = p.start();
17 p.bump();
18 m.complete(p, PLACEHOLDER_PAT);
19}
20
21// test ref_pat
22// fn main() {
23// let &a = ();
24// let &mut b = ();
25// }
26fn ref_pat(p: &mut Parser) {
27 assert!(p.at(AMPERSAND));
28 let m = p.start();
29 p.bump();
30 p.eat(MUT_KW);
31 pattern(p);
32 m.complete(p, REF_PAT);
33}
34
35// test bind_pat
36// fn main() {
37// let a = ();
38// let mut b = ();
39// let ref c = ();
40// let ref mut d = ();
41// let e @ _ = ();
42// let ref mut f @ g @ _ = ();
43// }
44fn bind_pat(p: &mut Parser) {
45 let m = p.start();
46 p.eat(REF_KW);
47 p.eat(MUT_KW);
48 name(p);
49 if p.eat(AT) {
50 pattern(p);
51 }
52 m.complete(p, BIND_PAT);
53}
diff --git a/src/parser/grammar/type_args.rs b/src/parser/grammar/type_args.rs
deleted file mode 100644
index 5b960f10b..000000000
--- a/src/parser/grammar/type_args.rs
+++ /dev/null
@@ -1,48 +0,0 @@
1use super::*;
2
3pub(super) fn type_arg_list(p: &mut Parser, colon_colon_required: bool) {
4 let m;
5 match (colon_colon_required, p.nth(0), p.nth(1)) {
6 (_, COLONCOLON, L_ANGLE) => {
7 m = p.start();
8 p.bump();
9 p.bump();
10 }
11 (false, L_ANGLE, _) => {
12 m = p.start();
13 p.bump();
14 }
15 _ => return,
16 };
17
18 while !p.at(EOF) && !p.at(R_ANGLE) {
19 type_arg(p);
20 if !p.at(R_ANGLE) && !p.expect(COMMA) {
21 break;
22 }
23 }
24 p.expect(R_ANGLE);
25 m.complete(p, TYPE_ARG_LIST);
26}
27
28// test type_arg
29// type A = B<'static, i32, Item=u64>
30fn type_arg(p: &mut Parser) {
31 let m = p.start();
32 match p.current() {
33 LIFETIME => {
34 p.bump();
35 m.complete(p, LIFETIME_ARG);
36 }
37 IDENT if p.nth(1) == EQ => {
38 name_ref(p);
39 p.bump();
40 types::type_(p);
41 m.complete(p, ASSOC_TYPE_ARG);
42 }
43 _ => {
44 types::type_(p);
45 m.complete(p, TYPE_ARG);
46 }
47 }
48}
diff --git a/src/parser/grammar/type_params.rs b/src/parser/grammar/type_params.rs
deleted file mode 100644
index b31bf52b6..000000000
--- a/src/parser/grammar/type_params.rs
+++ /dev/null
@@ -1,96 +0,0 @@
1use super::*;
2
3pub(super) fn type_param_list(p: &mut Parser) {
4 if !p.at(L_ANGLE) {
5 return;
6 }
7 let m = p.start();
8 p.bump();
9
10 while !p.at(EOF) && !p.at(R_ANGLE) {
11 match p.current() {
12 LIFETIME => lifetime_param(p),
13 IDENT => type_param(p),
14 _ => p.err_and_bump("expected type parameter"),
15 }
16 if !p.at(R_ANGLE) && !p.expect(COMMA) {
17 break;
18 }
19 }
20 p.expect(R_ANGLE);
21 m.complete(p, TYPE_PARAM_LIST);
22
23 fn lifetime_param(p: &mut Parser) {
24 assert!(p.at(LIFETIME));
25 let m = p.start();
26 p.bump();
27 if p.eat(COLON) {
28 while p.at(LIFETIME) {
29 p.bump();
30 if !p.eat(PLUS) {
31 break;
32 }
33 }
34 }
35 m.complete(p, LIFETIME_PARAM);
36 }
37
38 fn type_param(p: &mut Parser) {
39 assert!(p.at(IDENT));
40 let m = p.start();
41 name(p);
42 if p.at(COLON) {
43 bounds(p);
44 }
45 // test type_param_default
46 // struct S<T = i32>;
47 if p.at(EQ) {
48 p.bump();
49 types::type_(p)
50 }
51 m.complete(p, TYPE_PARAM);
52 }
53}
54
55// test type_param_bounds
56// struct S<T: 'a + ?Sized + (Copy)>;
57pub(super) fn bounds(p: &mut Parser) {
58 assert!(p.at(COLON));
59 p.bump();
60 bounds_without_colon(p);
61}
62
63pub(super) fn bounds_without_colon(p: &mut Parser) {
64 loop {
65 let has_paren = p.eat(L_PAREN);
66 p.eat(QUESTION);
67 if p.at(FOR_KW) {
68 //TODO
69 }
70 if p.at(LIFETIME) {
71 p.bump();
72 } else if paths::is_path_start(p) {
73 paths::type_path(p);
74 } else {
75 break;
76 }
77 if has_paren {
78 p.expect(R_PAREN);
79 }
80 if !p.eat(PLUS) {
81 break;
82 }
83 }
84}
85
86
87pub(super) fn where_clause(p: &mut Parser) {
88 if p.at(WHERE_KW) {
89 let m = p.start();
90 p.bump();
91 p.expect(IDENT);
92 p.expect(COLON);
93 p.expect(IDENT);
94 m.complete(p, WHERE_CLAUSE);
95 }
96}
diff --git a/src/parser/grammar/types.rs b/src/parser/grammar/types.rs
deleted file mode 100644
index 565037cb0..000000000
--- a/src/parser/grammar/types.rs
+++ /dev/null
@@ -1,207 +0,0 @@
1use super::*;
2
3pub(super) fn type_(p: &mut Parser) {
4 match p.current() {
5 L_PAREN => paren_or_tuple_type(p),
6 EXCL => never_type(p),
7 STAR => pointer_type(p),
8 L_BRACK => array_or_slice_type(p),
9 AMPERSAND => reference_type(p),
10 UNDERSCORE => placeholder_type(p),
11 FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p),
12 FOR_KW => for_type(p),
13 IMPL_KW => impl_trait_type(p),
14 _ if paths::is_path_start(p) => path_type(p),
15 _ => {
16 p.error("expected type");
17 }
18 }
19}
20
21pub(super) fn ascription(p: &mut Parser) {
22 p.expect(COLON);
23 type_(p)
24}
25
26fn type_no_plus(p: &mut Parser) {
27 type_(p);
28}
29
30fn paren_or_tuple_type(p: &mut Parser) {
31 assert!(p.at(L_PAREN));
32 let m = p.start();
33 p.bump();
34 let mut n_types: u32 = 0;
35 let mut trailing_comma: bool = false;
36 while !p.at(EOF) && !p.at(R_PAREN) {
37 n_types += 1;
38 type_(p);
39 if p.eat(COMMA) {
40 trailing_comma = true;
41 } else {
42 trailing_comma = false;
43 break;
44 }
45 }
46 p.expect(R_PAREN);
47
48 let kind = if n_types == 1 && !trailing_comma {
49 // test paren_type
50 // type T = (i32);
51 PAREN_TYPE
52 } else {
53 // test unit_type
54 // type T = ();
55
56 // test singleton_tuple_type
57 // type T = (i32,);
58 TUPLE_TYPE
59 };
60 m.complete(p, kind);
61}
62
63// test never_type
64// type Never = !;
65fn never_type(p: &mut Parser) {
66 assert!(p.at(EXCL));
67 let m = p.start();
68 p.bump();
69 m.complete(p, NEVER_TYPE);
70}
71
72fn pointer_type(p: &mut Parser) {
73 assert!(p.at(STAR));
74 let m = p.start();
75 p.bump();
76
77 match p.current() {
78 // test pointer_type_mut
79 // type M = *mut ();
80 // type C = *mut ();
81 MUT_KW | CONST_KW => p.bump(),
82 _ => {
83 // test pointer_type_no_mutability
84 // type T = *();
85 p.error(
86 "expected mut or const in raw pointer type \
87 (use `*mut T` or `*const T` as appropriate)",
88 );
89 }
90 };
91
92 type_no_plus(p);
93 m.complete(p, POINTER_TYPE);
94}
95
96fn array_or_slice_type(p: &mut Parser) {
97 assert!(p.at(L_BRACK));
98 let m = p.start();
99 p.bump();
100
101 type_(p);
102 let kind = match p.current() {
103 // test slice_type
104 // type T = [()];
105 R_BRACK => {
106 p.bump();
107 SLICE_TYPE
108 }
109
110 // test array_type
111 // type T = [(); 92];
112 SEMI => {
113 p.bump();
114 expressions::expr(p);
115 p.expect(R_BRACK);
116 ARRAY_TYPE
117 }
118 // test array_type_missing_semi
119 // type T = [() 92];
120 _ => {
121 p.error("expected `;` or `]`");
122 SLICE_TYPE
123 }
124 };
125 m.complete(p, kind);
126}
127
128// test reference_type;
129// type A = &();
130// type B = &'static ();
131// type C = &mut ();
132fn reference_type(p: &mut Parser) {
133 assert!(p.at(AMPERSAND));
134 let m = p.start();
135 p.bump();
136 p.eat(LIFETIME);
137 p.eat(MUT_KW);
138 type_no_plus(p);
139 m.complete(p, REFERENCE_TYPE);
140}
141
142// test placeholder_type
143// type Placeholder = _;
144fn placeholder_type(p: &mut Parser) {
145 assert!(p.at(UNDERSCORE));
146 let m = p.start();
147 p.bump();
148 m.complete(p, PLACEHOLDER_TYPE);
149}
150
151// test fn_pointer_type
152// type A = fn();
153// type B = unsafe fn();
154// type C = unsafe extern "C" fn();
155fn fn_pointer_type(p: &mut Parser) {
156 let m = p.start();
157 p.eat(UNSAFE_KW);
158 if p.at(EXTERN_KW) {
159 abi(p);
160 }
161 // test fn_pointer_type_missing_fn
162 // type F = unsafe ();
163 if !p.eat(FN_KW) {
164 m.abandon(p);
165 p.error("expected `fn`");
166 return;
167 }
168
169 params::param_list(p);
170 // test fn_pointer_type_with_ret
171 // type F = fn() -> ();
172 fn_ret_type(p);
173 m.complete(p, FN_POINTER_TYPE);
174}
175
176// test for_type
177// type A = for<'a> fn() -> ();
178fn for_type(p: &mut Parser) {
179 assert!(p.at(FOR_KW));
180 let m = p.start();
181 p.bump();
182 type_params::type_param_list(p);
183 type_(p);
184 m.complete(p, FOR_TYPE);
185}
186
187// test impl_trait_type
188// type A = impl Iterator<Item=Foo<'a>> + 'a;
189fn impl_trait_type(p: &mut Parser) {
190 assert!(p.at(IMPL_KW));
191 let m = p.start();
192 p.bump();
193 type_params::bounds_without_colon(p);
194 m.complete(p, IMPL_TRAIT_TYPE);
195}
196
197// test path_type
198// type A = Foo;
199// type B = ::Foo;
200// type C = self::Foo;
201// type D = super::Foo;
202fn path_type(p: &mut Parser) {
203 assert!(paths::is_path_start(p));
204 let m = p.start();
205 paths::type_path(p);
206 m.complete(p, PATH_TYPE);
207}
diff --git a/src/parser/input.rs b/src/parser/input.rs
deleted file mode 100644
index db76364b2..000000000
--- a/src/parser/input.rs
+++ /dev/null
@@ -1,71 +0,0 @@
1use {lexer::Token, SyntaxKind, SyntaxKind::EOF, TextRange, TextUnit};
2
3use std::ops::{Add, AddAssign};
4
5pub(crate) struct ParserInput<'t> {
6 text: &'t str,
7 start_offsets: Vec<TextUnit>,
8 tokens: Vec<Token>, // non-whitespace tokens
9}
10
11impl<'t> ParserInput<'t> {
12 pub fn new(text: &'t str, raw_tokens: &'t [Token]) -> ParserInput<'t> {
13 let mut tokens = Vec::new();
14 let mut start_offsets = Vec::new();
15 let mut len = 0.into();
16 for &token in raw_tokens.iter() {
17 if !token.kind.is_trivia() {
18 tokens.push(token);
19 start_offsets.push(len);
20 }
21 len += token.len;
22 }
23
24 ParserInput {
25 text,
26 start_offsets,
27 tokens,
28 }
29 }
30
31 pub fn kind(&self, pos: InputPosition) -> SyntaxKind {
32 let idx = pos.0 as usize;
33 if !(idx < self.tokens.len()) {
34 return EOF;
35 }
36 self.tokens[idx].kind
37 }
38
39 #[allow(unused)]
40 pub fn text(&self, pos: InputPosition) -> &'t str {
41 let idx = pos.0 as usize;
42 if !(idx < self.tokens.len()) {
43 return "";
44 }
45 let range = TextRange::offset_len(self.start_offsets[idx], self.tokens[idx].len);
46 &self.text[range]
47 }
48}
49
50#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
51pub(crate) struct InputPosition(u32);
52
53impl InputPosition {
54 pub fn new() -> Self {
55 InputPosition(0)
56 }
57}
58
59impl Add<u32> for InputPosition {
60 type Output = InputPosition;
61
62 fn add(self, rhs: u32) -> InputPosition {
63 InputPosition(self.0 + rhs)
64 }
65}
66
67impl AddAssign<u32> for InputPosition {
68 fn add_assign(&mut self, rhs: u32) {
69 self.0 += rhs
70 }
71}
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
deleted file mode 100644
index 8631baa2e..000000000
--- a/src/parser/mod.rs
+++ /dev/null
@@ -1,24 +0,0 @@
1#[macro_use]
2mod token_set;
3mod event;
4mod grammar;
5mod input;
6mod parser;
7
8use {lexer::Token, parser::event::process};
9
10pub(crate) use self::event::Sink;
11
12/// Parse a sequence of tokens into the representative node tree
13pub(crate) fn parse<S: Sink>(text: String, tokens: &[Token]) -> S::Tree {
14 let events = {
15 let input = input::ParserInput::new(&text, tokens);
16 let parser_impl = parser::imp::ParserImpl::new(&input);
17 let mut parser = parser::Parser(parser_impl);
18 grammar::file(&mut parser);
19 parser.0.into_events()
20 };
21 let mut sink = S::new(text);
22 process(&mut sink, tokens, events);
23 sink.finish()
24}
diff --git a/src/parser/parser/imp.rs b/src/parser/parser/imp.rs
deleted file mode 100644
index c653e3524..000000000
--- a/src/parser/parser/imp.rs
+++ /dev/null
@@ -1,118 +0,0 @@
1use parser::event::Event;
2use parser::input::{InputPosition, ParserInput};
3
4use SyntaxKind::{self, EOF, TOMBSTONE};
5
6/// Implementation details of `Parser`, extracted
7/// to a separate struct in order not to pollute
8/// the public API of the `Parser`.
9pub(crate) struct ParserImpl<'t> {
10 inp: &'t ParserInput<'t>,
11
12 pos: InputPosition,
13 events: Vec<Event>,
14}
15
16impl<'t> ParserImpl<'t> {
17 pub(crate) fn new(inp: &'t ParserInput<'t>) -> ParserImpl<'t> {
18 ParserImpl {
19 inp,
20
21 pos: InputPosition::new(),
22 events: Vec::new(),
23 }
24 }
25
26 pub(crate) fn into_events(self) -> Vec<Event> {
27 assert_eq!(self.nth(0), EOF);
28 self.events
29 }
30
31 pub(super) fn nth(&self, n: u32) -> SyntaxKind {
32 self.inp.kind(self.pos + n)
33 }
34
35 pub(super) fn at_kw(&self, t: &str) -> bool {
36 self.inp.text(self.pos) == t
37 }
38
39 pub(super) fn start(&mut self) -> u32 {
40 let pos = self.events.len() as u32;
41 self.event(Event::Start {
42 kind: TOMBSTONE,
43 forward_parent: None,
44 });
45 pos
46 }
47
48 pub(super) fn bump(&mut self) {
49 let kind = self.nth(0);
50 if kind == EOF {
51 return;
52 }
53 self.do_bump(kind);
54 }
55
56 pub(super) fn bump_remap(&mut self, kind: SyntaxKind) {
57 if self.nth(0) == EOF {
58 // TODO: panic!?
59 return;
60 }
61 self.do_bump(kind);
62 }
63
64 fn do_bump(&mut self, kind: SyntaxKind) {
65 self.pos += 1;
66 self.event(Event::Token {
67 kind,
68 n_raw_tokens: 1,
69 });
70 }
71
72 pub(super) fn error(&mut self, msg: String) {
73 self.event(Event::Error { msg })
74 }
75
76 pub(super) fn complete(&mut self, pos: u32, kind: SyntaxKind) {
77 match self.events[pos as usize] {
78 Event::Start {
79 kind: ref mut slot, ..
80 } => {
81 *slot = kind;
82 }
83 _ => unreachable!(),
84 }
85 self.event(Event::Finish);
86 }
87
88 pub(super) fn abandon(&mut self, pos: u32) {
89 let idx = pos as usize;
90 if idx == self.events.len() - 1 {
91 match self.events.pop() {
92 Some(Event::Start {
93 kind: TOMBSTONE,
94 forward_parent: None,
95 }) => (),
96 _ => unreachable!(),
97 }
98 }
99 }
100
101 pub(super) fn precede(&mut self, pos: u32) -> u32 {
102 let new_pos = self.start();
103 match self.events[pos as usize] {
104 Event::Start {
105 ref mut forward_parent,
106 ..
107 } => {
108 *forward_parent = Some(new_pos - pos);
109 }
110 _ => unreachable!(),
111 }
112 new_pos
113 }
114
115 fn event(&mut self, event: Event) {
116 self.events.push(event)
117 }
118}
diff --git a/src/parser/parser/mod.rs b/src/parser/parser/mod.rs
deleted file mode 100644
index 0930ff9e4..000000000
--- a/src/parser/parser/mod.rs
+++ /dev/null
@@ -1,141 +0,0 @@
1use SyntaxKind::{self, ERROR};
2
3pub(super) mod imp;
4use self::imp::ParserImpl;
5
6/// `Parser` struct provides the low-level API for
7/// navigating through the stream of tokens and
8/// constructing the parse tree. The actual parsing
9/// happens in the `grammar` module.
10///
11/// However, the result of this `Parser` is not a real
12/// tree, but rather a flat stream of events of the form
13/// "start expression, consume number literal,
14/// finish expression". See `Event` docs for more.
15pub(crate) struct Parser<'t>(pub(super) ParserImpl<'t>);
16
17impl<'t> Parser<'t> {
18 /// Returns the kind of the current token.
19 /// If parser has already reached the end of input,
20 /// the special `EOF` kind is returned.
21 pub(crate) fn current(&self) -> SyntaxKind {
22 self.nth(0)
23 }
24
25 /// Lookahead operation: returns the kind of the next nth
26 /// token.
27 pub(crate) fn nth(&self, n: u32) -> SyntaxKind {
28 self.0.nth(n)
29 }
30
31 /// Checks if the current token is `kind`.
32 pub(crate) fn at(&self, kind: SyntaxKind) -> bool {
33 self.current() == kind
34 }
35
36 /// Checks if the current token is contextual keyword with text `t`.
37 pub(crate) fn at_contextual_kw(&self, t: &str) -> bool {
38 self.0.at_kw(t)
39 }
40
41 /// Starts a new node in the syntax tree. All nodes and tokens
42 /// consumed between the `start` and the corresponding `Marker::complete`
43 /// belong to the same node.
44 pub(crate) fn start(&mut self) -> Marker {
45 Marker(self.0.start())
46 }
47
48 /// Advances the parser by one token.
49 pub(crate) fn bump(&mut self) {
50 self.0.bump();
51 }
52
53 /// Advances the parser by one token, remapping its kind.
54 /// This is useful to create contextual keywords from
55 /// identifiers. For example, the lexer creates an `union`
56 /// *identifier* token, but the parser remaps it to the
57 /// `union` keyword, and keyword is what ends up in the
58 /// final tree.
59 pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) {
60 self.0.bump_remap(kind);
61 }
62
63 /// Emit error with the `message`
64 /// TODO: this should be much more fancy and support
65 /// structured errors with spans and notes, like rustc
66 /// does.
67 pub(crate) fn error<T: Into<String>>(&mut self, message: T) {
68 self.0.error(message.into())
69 }
70
71 /// Consume the next token if it is `kind`.
72 pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
73 if !self.at(kind) {
74 return false;
75 }
76 self.bump();
77 true
78 }
79
80 /// Consume the next token if it is `kind` or emit an error
81 /// otherwise.
82 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
83 if self.eat(kind) {
84 return true;
85 }
86 self.error(format!("expected {:?}", kind));
87 false
88 }
89
90 /// Create an error node and consume the next token.
91 pub(crate) fn err_and_bump(&mut self, message: &str) {
92 let m = self.start();
93 self.error(message);
94 self.bump();
95 m.complete(self, ERROR);
96 }
97}
98
99/// See `Parser::start`.
100pub(crate) struct Marker(u32);
101
102impl Marker {
103 /// Finishes the syntax tree node and assigns `kind` to it.
104 pub(crate) fn complete(self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
105 let pos = self.0;
106 ::std::mem::forget(self);
107 p.0.complete(pos, kind);
108 CompletedMarker(pos)
109 }
110
111 /// Abandons the syntax tree node. All its children
112 /// are attached to its parent instead.
113 pub(crate) fn abandon(self, p: &mut Parser) {
114 let pos = self.0;
115 ::std::mem::forget(self);
116 p.0.abandon(pos);
117 }
118}
119
120impl Drop for Marker {
121 fn drop(&mut self) {
122 if !::std::thread::panicking() {
123 panic!("Marker must be either completed or abandoned");
124 }
125 }
126}
127
128pub(crate) struct CompletedMarker(u32);
129
130impl CompletedMarker {
131 /// This one is tricky :-)
132 /// This method allows to create a new node which starts
133 /// *before* the current one. That is, parser could start
134 /// node `A`, then complete it, and then after parsing the
135 /// whole `A`, decide that it should have started some node
136 /// `B` before starting `A`. `precede` allows to do exactly
137 /// that. See also docs about `forward_parent` in `Event::Start`.
138 pub(crate) fn precede(self, p: &mut Parser) -> Marker {
139 Marker(p.0.precede(self.0))
140 }
141}
diff --git a/src/parser/token_set.rs b/src/parser/token_set.rs
deleted file mode 100644
index a800f200d..000000000
--- a/src/parser/token_set.rs
+++ /dev/null
@@ -1,24 +0,0 @@
1use SyntaxKind;
2
3pub(crate) struct TokenSet {
4 pub tokens: &'static [SyntaxKind],
5}
6
7impl TokenSet {
8 pub fn contains(&self, kind: SyntaxKind) -> bool {
9 self.tokens.contains(&kind)
10 }
11}
12
13#[macro_export]
14macro_rules! token_set {
15 ($($t:ident),*) => {
16 TokenSet {
17 tokens: &[$($t),*],
18 }
19 };
20
21 ($($t:ident),* ,) => {
22 token_set!($($t),*)
23 };
24}