diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/parser/event_parser/grammar/attributes.rs | 42 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/expressions.rs | 5 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/items.rs | 33 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/mod.rs | 88 |
4 files changed, 85 insertions, 83 deletions
diff --git a/src/parser/event_parser/grammar/attributes.rs b/src/parser/event_parser/grammar/attributes.rs new file mode 100644 index 000000000..c80f782ab --- /dev/null +++ b/src/parser/event_parser/grammar/attributes.rs | |||
@@ -0,0 +1,42 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) fn inner_attributes(p: &mut Parser) { | ||
4 | many(p, |p| attribute(p, true)) | ||
5 | } | ||
6 | |||
7 | pub(super) fn outer_attributes(_: &mut Parser) { | ||
8 | } | ||
9 | |||
10 | |||
11 | fn attribute(p: &mut Parser, inner: bool) -> bool { | ||
12 | let attr_start = inner && p.lookahead(&[POUND, EXCL, L_BRACK]) | ||
13 | || !inner && p.lookahead(&[POUND, L_BRACK]); | ||
14 | if !attr_start { | ||
15 | return false; | ||
16 | } | ||
17 | node(p, ATTR, |p| { | ||
18 | p.bump_n(if inner { 3 } else { 2 }); | ||
19 | meta_item(p) && p.expect(R_BRACK); | ||
20 | }); | ||
21 | true | ||
22 | } | ||
23 | |||
24 | fn meta_item(p: &mut Parser) -> bool { | ||
25 | node_if(p, IDENT, META_ITEM, |p| { | ||
26 | if p.eat(EQ) { | ||
27 | if !expressions::literal(p) { | ||
28 | p.error() | ||
29 | .message("expected literal") | ||
30 | .emit(); | ||
31 | } | ||
32 | } else if p.eat(L_PAREN) { | ||
33 | comma_list(p, R_PAREN, meta_item_inner); | ||
34 | p.expect(R_PAREN); | ||
35 | } | ||
36 | }) | ||
37 | } | ||
38 | |||
39 | fn meta_item_inner(p: &mut Parser) -> bool { | ||
40 | meta_item(p) || expressions::literal(p) | ||
41 | } | ||
42 | |||
diff --git a/src/parser/event_parser/grammar/expressions.rs b/src/parser/event_parser/grammar/expressions.rs new file mode 100644 index 000000000..9b43bdf2a --- /dev/null +++ b/src/parser/event_parser/grammar/expressions.rs | |||
@@ -0,0 +1,5 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) fn literal(p: &mut Parser) -> bool { | ||
4 | p.eat(INT_NUMBER) || p.eat(FLOAT_NUMBER) | ||
5 | } \ No newline at end of file | ||
diff --git a/src/parser/event_parser/grammar/items.rs b/src/parser/event_parser/grammar/items.rs new file mode 100644 index 000000000..b9eb1934c --- /dev/null +++ b/src/parser/event_parser/grammar/items.rs | |||
@@ -0,0 +1,33 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) fn item_first(p: &Parser) -> bool { | ||
4 | match p.current() { | ||
5 | STRUCT_KW | FN_KW => true, | ||
6 | _ => false, | ||
7 | } | ||
8 | } | ||
9 | |||
10 | pub(super) fn item(p: &mut Parser) { | ||
11 | attributes::outer_attributes(p); | ||
12 | visibility(p); | ||
13 | node_if(p, STRUCT_KW, STRUCT_ITEM, struct_item) | ||
14 | || node_if(p, FN_KW, FN_ITEM, fn_item); | ||
15 | } | ||
16 | |||
17 | fn struct_item(p: &mut Parser) { | ||
18 | p.expect(IDENT) | ||
19 | && p.curly_block(|p| comma_list(p, EOF, struct_field)); | ||
20 | } | ||
21 | |||
22 | fn struct_field(p: &mut Parser) -> bool { | ||
23 | node_if(p, IDENT, STRUCT_FIELD, |p| { | ||
24 | p.expect(COLON) && p.expect(IDENT); | ||
25 | }) | ||
26 | } | ||
27 | |||
28 | fn fn_item(p: &mut Parser) { | ||
29 | p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN) | ||
30 | && p.curly_block(|p| ()); | ||
31 | } | ||
32 | |||
33 | |||
diff --git a/src/parser/event_parser/grammar/mod.rs b/src/parser/event_parser/grammar/mod.rs index acf27aec9..b67ceeb13 100644 --- a/src/parser/event_parser/grammar/mod.rs +++ b/src/parser/event_parser/grammar/mod.rs | |||
@@ -3,104 +3,26 @@ use {SyntaxKind}; | |||
3 | use tree::EOF; | 3 | use tree::EOF; |
4 | use syntax_kinds::*; | 4 | use syntax_kinds::*; |
5 | 5 | ||
6 | // Items // | 6 | mod items; |
7 | mod attributes; | ||
8 | mod expressions; | ||
7 | 9 | ||
8 | pub(crate) fn file(p: &mut Parser) { | 10 | pub(crate) fn file(p: &mut Parser) { |
9 | node(p, FILE, |p| { | 11 | node(p, FILE, |p| { |
10 | p.optional(SHEBANG); | 12 | p.optional(SHEBANG); |
11 | inner_attributes(p); | 13 | attributes::inner_attributes(p); |
12 | many(p, |p| { | 14 | many(p, |p| { |
13 | skip_to_first( | 15 | skip_to_first( |
14 | p, item_first, item, | 16 | p, items::item_first, items::item, |
15 | "expected item", | 17 | "expected item", |
16 | ) | 18 | ) |
17 | }); | 19 | }); |
18 | }) | 20 | }) |
19 | } | 21 | } |
20 | 22 | ||
21 | fn item_first(p: &Parser) -> bool { | ||
22 | match p.current() { | ||
23 | STRUCT_KW | FN_KW => true, | ||
24 | _ => false, | ||
25 | } | ||
26 | } | ||
27 | |||
28 | fn item(p: &mut Parser) { | ||
29 | outer_attributes(p); | ||
30 | visibility(p); | ||
31 | node_if(p, STRUCT_KW, STRUCT_ITEM, struct_item) | ||
32 | || node_if(p, FN_KW, FN_ITEM, fn_item); | ||
33 | } | ||
34 | |||
35 | fn struct_item(p: &mut Parser) { | ||
36 | p.expect(IDENT) | ||
37 | && p.curly_block(|p| comma_list(p, EOF, struct_field)); | ||
38 | } | ||
39 | |||
40 | fn struct_field(p: &mut Parser) -> bool { | ||
41 | node_if(p, IDENT, STRUCT_FIELD, |p| { | ||
42 | p.expect(COLON) && p.expect(IDENT); | ||
43 | }) | ||
44 | } | ||
45 | |||
46 | fn fn_item(p: &mut Parser) { | ||
47 | p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN) | ||
48 | && p.curly_block(|p| ()); | ||
49 | } | ||
50 | |||
51 | |||
52 | // Paths, types, attributes, and stuff // | ||
53 | |||
54 | fn inner_attributes(p: &mut Parser) { | ||
55 | many(p, |p| attribute(p, true)) | ||
56 | } | ||
57 | |||
58 | fn attribute(p: &mut Parser, inner: bool) -> bool { | ||
59 | let attr_start = inner && p.lookahead(&[POUND, EXCL, L_BRACK]) | ||
60 | || !inner && p.lookahead(&[POUND, L_BRACK]); | ||
61 | if !attr_start { | ||
62 | return false; | ||
63 | } | ||
64 | node(p, ATTR, |p| { | ||
65 | p.bump_n(if inner { 3 } else { 2 }); | ||
66 | meta_item(p) && p.expect(R_BRACK); | ||
67 | }); | ||
68 | true | ||
69 | } | ||
70 | |||
71 | fn meta_item(p: &mut Parser) -> bool { | ||
72 | node_if(p, IDENT, META_ITEM, |p| { | ||
73 | if p.eat(EQ) { | ||
74 | if !literal(p) { | ||
75 | p.error() | ||
76 | .message("expected literal") | ||
77 | .emit(); | ||
78 | } | ||
79 | } else if p.eat(L_PAREN) { | ||
80 | comma_list(p, R_PAREN, meta_item_inner); | ||
81 | p.expect(R_PAREN); | ||
82 | } | ||
83 | }) | ||
84 | } | ||
85 | |||
86 | fn meta_item_inner(p: &mut Parser) -> bool { | ||
87 | meta_item(p) || literal(p) | ||
88 | } | ||
89 | |||
90 | fn literal(p: &mut Parser) -> bool { | ||
91 | p.eat(INT_NUMBER) || p.eat(FLOAT_NUMBER) | ||
92 | } | ||
93 | |||
94 | fn outer_attributes(_: &mut Parser) { | ||
95 | } | ||
96 | |||
97 | fn visibility(_: &mut Parser) { | 23 | fn visibility(_: &mut Parser) { |
98 | } | 24 | } |
99 | 25 | ||
100 | // Expressions // | ||
101 | |||
102 | // Error recovery and high-order utils // | ||
103 | |||
104 | fn node_if<F: FnOnce(&mut Parser)>( | 26 | fn node_if<F: FnOnce(&mut Parser)>( |
105 | p: &mut Parser, | 27 | p: &mut Parser, |
106 | first: SyntaxKind, | 28 | first: SyntaxKind, |