aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-01-08 19:40:14 +0000
committerAleksey Kladov <[email protected]>2018-01-08 19:40:14 +0000
commit0cf2d6afee52fe248c8a032346c5bdb6dc7cd928 (patch)
treef98f950ada46f596502d8d9987efc67848c46321 /src
parentbdddfc9eb89ee717c38a117383a313e5a49bb267 (diff)
Generalized lookahead
Diffstat (limited to 'src')
-rw-r--r--src/parser/event_parser/grammar/attributes.rs17
-rw-r--r--src/parser/event_parser/grammar/expressions.rs19
-rw-r--r--src/parser/event_parser/grammar/items.rs2
-rw-r--r--src/parser/event_parser/grammar/mod.rs68
-rw-r--r--src/parser/event_parser/parser.rs8
-rw-r--r--src/parser/mod.rs2
6 files changed, 78 insertions, 38 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
11fn attribute(p: &mut Parser, inner: bool) -> bool { 11fn 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
24fn meta_item(p: &mut Parser) -> bool { 23fn 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 @@
1use super::*; 1use super::*;
2 2
3pub(super) fn literal(p: &mut Parser) -> bool { 3pub(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
59fn fn_item(p: &mut Parser) { 59fn 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) {
18fn visibility(_: &mut Parser) { 18fn visibility(_: &mut Parser) {
19} 19}
20 20
21fn node_if<F: FnOnce(&mut Parser)>( 21fn 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
30fn node<F: FnOnce(&mut Parser)>(p: &mut Parser, node_kind: SyntaxKind, rest: F) { 30fn 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
107trait Lookahead: Copy {
108 fn is_ahead(self, p: &Parser) -> bool;
109 fn consume(p: &mut Parser);
110}
111
112impl 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
122impl 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
134impl 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)]
149struct AnyOf<'a>(&'a [SyntaxKind]);
150
151impl<'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
diff --git a/src/parser/event_parser/parser.rs b/src/parser/event_parser/parser.rs
index bec9dbab4..a1a0ebfea 100644
--- a/src/parser/event_parser/parser.rs
+++ b/src/parser/event_parser/parser.rs
@@ -88,12 +88,8 @@ impl<'t> Parser<'t> {
88 kind 88 kind
89 } 89 }
90 90
91 pub(crate) fn lookahead(&self, kinds: &[SyntaxKind]) -> bool { 91 pub(crate) fn raw_lookahead(&self, n: usize) -> SyntaxKind {
92 if self.tokens[self.pos..].len() < kinds.len() { 92 self.tokens.get(self.pos + n).map(|t| t.kind).unwrap_or(EOF)
93 return false
94 }
95 kinds.iter().zip(self.tokens[self.pos..].iter().map(|t| t.kind))
96 .all(|(&k1, k2)| k1 == k2)
97 } 93 }
98 94
99 pub(crate) fn curly_block<F: FnOnce(&mut Parser)>(&mut self, f: F) -> bool { 95 pub(crate) fn curly_block<F: FnOnce(&mut Parser)>(&mut self, f: F) -> bool {
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index a76356eb5..742755142 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -56,4 +56,4 @@ fn is_insignificant(kind: SyntaxKind) -> bool {
56 WHITESPACE | COMMENT => true, 56 WHITESPACE | COMMENT => true,
57 _ => false, 57 _ => false,
58 } 58 }
59} \ No newline at end of file 59}