aboutsummaryrefslogtreecommitdiff
path: root/src/parser/event_parser/grammar
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-01-07 18:41:00 +0000
committerAleksey Kladov <[email protected]>2018-01-07 18:41:00 +0000
commit0aef78e512bfa271e8ff411359072dc1132e2c65 (patch)
tree37ce21dca0418031c44a6366cf5aee6a3d5871a3 /src/parser/event_parser/grammar
parent7bc974ab2c29f896a0d9ca952ad306a9ed38f6f2 (diff)
grammar.rs is folder
Diffstat (limited to 'src/parser/event_parser/grammar')
-rw-r--r--src/parser/event_parser/grammar/mod.rs194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/parser/event_parser/grammar/mod.rs b/src/parser/event_parser/grammar/mod.rs
new file mode 100644
index 000000000..acf27aec9
--- /dev/null
+++ b/src/parser/event_parser/grammar/mod.rs
@@ -0,0 +1,194 @@
1use super::parser::Parser;
2use {SyntaxKind};
3use tree::EOF;
4use syntax_kinds::*;
5
6// Items //
7
8pub(crate) fn file(p: &mut Parser) {
9 node(p, FILE, |p| {
10 p.optional(SHEBANG);
11 inner_attributes(p);
12 many(p, |p| {
13 skip_to_first(
14 p, item_first, item,
15 "expected item",
16 )
17 });
18 })
19}
20
21fn item_first(p: &Parser) -> bool {
22 match p.current() {
23 STRUCT_KW | FN_KW => true,
24 _ => false,
25 }
26}
27
28fn 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
35fn struct_item(p: &mut Parser) {
36 p.expect(IDENT)
37 && p.curly_block(|p| comma_list(p, EOF, struct_field));
38}
39
40fn struct_field(p: &mut Parser) -> bool {
41 node_if(p, IDENT, STRUCT_FIELD, |p| {
42 p.expect(COLON) && p.expect(IDENT);
43 })
44}
45
46fn 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
54fn inner_attributes(p: &mut Parser) {
55 many(p, |p| attribute(p, true))
56}
57
58fn 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
71fn 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
86fn meta_item_inner(p: &mut Parser) -> bool {
87 meta_item(p) || literal(p)
88}
89
90fn literal(p: &mut Parser) -> bool {
91 p.eat(INT_NUMBER) || p.eat(FLOAT_NUMBER)
92}
93
94fn outer_attributes(_: &mut Parser) {
95}
96
97fn visibility(_: &mut Parser) {
98}
99
100// Expressions //
101
102// Error recovery and high-order utils //
103
104fn node_if<F: FnOnce(&mut Parser)>(
105 p: &mut Parser,
106 first: SyntaxKind,
107 node_kind: SyntaxKind,
108 rest: F
109) -> bool {
110 p.current() == first && { node(p, node_kind, |p| { p.bump(); rest(p); }); true }
111}
112
113fn node<F: FnOnce(&mut Parser)>(p: &mut Parser, node_kind: SyntaxKind, rest: F) {
114 p.start(node_kind);
115 rest(p);
116 p.finish();
117}
118
119fn many<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) {
120 while f(p) { }
121}
122
123fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, end: SyntaxKind, f: F) {
124 many(p, |p| {
125 if !f(p) || p.current() == end {
126 false
127 } else {
128 p.expect(COMMA);
129 true
130 }
131 })
132}
133
134
135fn skip_to_first<C, F>(p: &mut Parser, cond: C, f: F, message: &str) -> bool
136where
137 C: Fn(&Parser) -> bool,
138 F: FnOnce(&mut Parser),
139{
140 let mut skipped = false;
141 loop {
142 if cond(p) {
143 if skipped {
144 p.finish();
145 }
146 f(p);
147 return true;
148 }
149 if p.current() == EOF {
150 if skipped {
151 p.finish();
152 }
153 return false;
154 }
155 if !skipped {
156 p.start(ERROR);
157 p.error()
158 .message(message)
159 .emit();
160 }
161 p.bump();
162 skipped = true;
163 }
164}
165
166impl<'p> Parser<'p> {
167 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
168 if self.current() == kind {
169 self.bump();
170 true
171 } else {
172 self.error()
173 .message(format!("expected {:?}", kind))
174 .emit();
175 false
176 }
177 }
178
179 fn optional(&mut self, kind: SyntaxKind) {
180 if self.current() == kind {
181 self.bump();
182 }
183 }
184
185 fn bump_n(&mut self, n: u8) {
186 for _ in 0..n {
187 self.bump();
188 }
189 }
190
191 fn eat(&mut self, kind: SyntaxKind) -> bool {
192 self.current() == kind && { self.bump(); true }
193 }
194} \ No newline at end of file