diff options
author | Aleksey Kladov <[email protected]> | 2018-01-08 19:40:14 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-01-08 19:40:14 +0000 |
commit | 0cf2d6afee52fe248c8a032346c5bdb6dc7cd928 (patch) | |
tree | f98f950ada46f596502d8d9987efc67848c46321 /src/parser/event_parser/grammar | |
parent | bdddfc9eb89ee717c38a117383a313e5a49bb267 (diff) |
Generalized lookahead
Diffstat (limited to 'src/parser/event_parser/grammar')
-rw-r--r-- | src/parser/event_parser/grammar/attributes.rs | 17 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/expressions.rs | 19 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/items.rs | 2 | ||||
-rw-r--r-- | src/parser/event_parser/grammar/mod.rs | 68 |
4 files changed, 75 insertions, 31 deletions
diff --git a/src/parser/event_parser/grammar/attributes.rs b/src/parser/event_parser/grammar/attributes.rs index c80f782ab..52210ccad 100644 --- a/src/parser/event_parser/grammar/attributes.rs +++ b/src/parser/event_parser/grammar/attributes.rs | |||
@@ -9,16 +9,15 @@ pub(super) fn outer_attributes(_: &mut Parser) { | |||
9 | 9 | ||
10 | 10 | ||
11 | fn attribute(p: &mut Parser, inner: bool) -> bool { | 11 | fn attribute(p: &mut Parser, inner: bool) -> bool { |
12 | let attr_start = inner && p.lookahead(&[POUND, EXCL, L_BRACK]) | 12 | fn attr_tail(p: &mut Parser) { |
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); | 13 | meta_item(p) && p.expect(R_BRACK); |
20 | }); | 14 | } |
21 | true | 15 | |
16 | if inner { | ||
17 | node_if(p, [POUND, EXCL, L_BRACK], ATTR, attr_tail) | ||
18 | } else { | ||
19 | node_if(p, [POUND, L_BRACK], ATTR, attr_tail) | ||
20 | } | ||
22 | } | 21 | } |
23 | 22 | ||
24 | fn meta_item(p: &mut Parser) -> bool { | 23 | fn meta_item(p: &mut Parser) -> bool { |
diff --git a/src/parser/event_parser/grammar/expressions.rs b/src/parser/event_parser/grammar/expressions.rs index a6a1b302b..f40a3cce2 100644 --- a/src/parser/event_parser/grammar/expressions.rs +++ b/src/parser/event_parser/grammar/expressions.rs | |||
@@ -1,16 +1,11 @@ | |||
1 | use super::*; | 1 | use super::*; |
2 | 2 | ||
3 | pub(super) fn literal(p: &mut Parser) -> bool { | 3 | pub(super) fn literal(p: &mut Parser) -> bool { |
4 | match p.current() { | 4 | let literals = [ |
5 | TRUE_KW | FALSE_KW | 5 | TRUE_KW, FALSE_KW, |
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 | node(p, LITERAL, |p| { | 9 | ]; |
10 | p.bump(); | 10 | node_if(p, AnyOf(&literals), LITERAL, |_| ()) |
11 | }); | ||
12 | true | ||
13 | } | ||
14 | _ => false | ||
15 | } | ||
16 | } \ No newline at end of file | 11 | } \ No newline at end of file |
diff --git a/src/parser/event_parser/grammar/items.rs b/src/parser/event_parser/grammar/items.rs index b6d260fd8..68b444b69 100644 --- a/src/parser/event_parser/grammar/items.rs +++ b/src/parser/event_parser/grammar/items.rs | |||
@@ -58,7 +58,7 @@ fn struct_field(p: &mut Parser) -> bool { | |||
58 | 58 | ||
59 | fn fn_item(p: &mut Parser) { | 59 | fn fn_item(p: &mut Parser) { |
60 | p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN) | 60 | p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN) |
61 | && p.curly_block(|p| ()); | 61 | && p.curly_block(|_| ()); |
62 | } | 62 | } |
63 | 63 | ||
64 | 64 | ||
diff --git a/src/parser/event_parser/grammar/mod.rs b/src/parser/event_parser/grammar/mod.rs index 274c2cdb4..78309aa83 100644 --- a/src/parser/event_parser/grammar/mod.rs +++ b/src/parser/event_parser/grammar/mod.rs | |||
@@ -18,13 +18,13 @@ pub(crate) fn file(p: &mut Parser) { | |||
18 | fn visibility(_: &mut Parser) { | 18 | fn visibility(_: &mut Parser) { |
19 | } | 19 | } |
20 | 20 | ||
21 | fn node_if<F: FnOnce(&mut Parser)>( | 21 | fn node_if<F: FnOnce(&mut Parser), L: Lookahead>( |
22 | p: &mut Parser, | 22 | p: &mut Parser, |
23 | first: SyntaxKind, | 23 | first: L, |
24 | node_kind: SyntaxKind, | 24 | node_kind: SyntaxKind, |
25 | rest: F | 25 | rest: F |
26 | ) -> bool { | 26 | ) -> bool { |
27 | p.current() == first && { node(p, node_kind, |p| { p.bump(); rest(p); }); true } | 27 | first.is_ahead(p) && { node(p, node_kind, |p| { L::consume(p); rest(p); }); true } |
28 | } | 28 | } |
29 | 29 | ||
30 | fn node<F: FnOnce(&mut Parser)>(p: &mut Parser, node_kind: SyntaxKind, rest: F) { | 30 | fn node<F: FnOnce(&mut Parser)>(p: &mut Parser, node_kind: SyntaxKind, rest: F) { |
@@ -99,13 +99,63 @@ impl<'p> Parser<'p> { | |||
99 | } | 99 | } |
100 | } | 100 | } |
101 | 101 | ||
102 | fn bump_n(&mut self, n: u8) { | ||
103 | for _ in 0..n { | ||
104 | self.bump(); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | fn eat(&mut self, kind: SyntaxKind) -> bool { | 102 | fn eat(&mut self, kind: SyntaxKind) -> bool { |
109 | self.current() == kind && { self.bump(); true } | 103 | self.current() == kind && { self.bump(); true } |
110 | } | 104 | } |
105 | } | ||
106 | |||
107 | trait Lookahead: Copy { | ||
108 | fn is_ahead(self, p: &Parser) -> bool; | ||
109 | fn consume(p: &mut Parser); | ||
110 | } | ||
111 | |||
112 | impl Lookahead for SyntaxKind { | ||
113 | fn is_ahead(self, p: &Parser) -> bool { | ||
114 | p.current() == self | ||
115 | } | ||
116 | |||
117 | fn consume(p: &mut Parser) { | ||
118 | p.bump(); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | impl Lookahead for [SyntaxKind; 2] { | ||
123 | fn is_ahead(self, p: &Parser) -> bool { | ||
124 | p.current() == self[0] | ||
125 | && p.raw_lookahead(1) == self[1] | ||
126 | } | ||
127 | |||
128 | fn consume(p: &mut Parser) { | ||
129 | p.bump(); | ||
130 | p.bump(); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | impl Lookahead for [SyntaxKind; 3] { | ||
135 | fn is_ahead(self, p: &Parser) -> bool { | ||
136 | p.current() == self[0] | ||
137 | && p.raw_lookahead(1) == self[1] | ||
138 | && p.raw_lookahead(2) == self[2] | ||
139 | } | ||
140 | |||
141 | fn consume(p: &mut Parser) { | ||
142 | p.bump(); | ||
143 | p.bump(); | ||
144 | p.bump(); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | #[derive(Clone, Copy)] | ||
149 | struct AnyOf<'a>(&'a [SyntaxKind]); | ||
150 | |||
151 | impl<'a> Lookahead for AnyOf<'a> { | ||
152 | fn is_ahead(self, p: &Parser) -> bool { | ||
153 | let curr = p.current(); | ||
154 | self.0.iter().any(|&k| k == curr) | ||
155 | } | ||
156 | |||
157 | fn consume(p: &mut Parser) { | ||
158 | p.bump(); | ||
159 | } | ||
160 | |||
111 | } \ No newline at end of file | 161 | } \ No newline at end of file |