From 0cf2d6afee52fe248c8a032346c5bdb6dc7cd928 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 8 Jan 2018 22:40:14 +0300 Subject: Generalized lookahead --- src/parser/event_parser/grammar/attributes.rs | 17 +++---- src/parser/event_parser/grammar/expressions.rs | 19 +++---- src/parser/event_parser/grammar/items.rs | 2 +- src/parser/event_parser/grammar/mod.rs | 68 ++++++++++++++++++++++---- src/parser/event_parser/parser.rs | 8 +-- src/parser/mod.rs | 2 +- 6 files changed, 78 insertions(+), 38 deletions(-) (limited to 'src') 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) { fn attribute(p: &mut Parser, inner: bool) -> bool { - let attr_start = inner && p.lookahead(&[POUND, EXCL, L_BRACK]) - || !inner && p.lookahead(&[POUND, L_BRACK]); - if !attr_start { - return false; - } - node(p, ATTR, |p| { - p.bump_n(if inner { 3 } else { 2 }); + fn attr_tail(p: &mut Parser) { meta_item(p) && p.expect(R_BRACK); - }); - true + } + + if inner { + node_if(p, [POUND, EXCL, L_BRACK], ATTR, attr_tail) + } else { + node_if(p, [POUND, L_BRACK], ATTR, attr_tail) + } } 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 @@ use super::*; pub(super) fn literal(p: &mut Parser) -> bool { - match p.current() { - TRUE_KW | FALSE_KW - | INT_NUMBER | FLOAT_NUMBER - | BYTE | CHAR - |STRING | RAW_STRING | BYTE_STRING | RAW_BYTE_STRING => { - node(p, LITERAL, |p| { - p.bump(); - }); - true - } - _ => false - } + let literals = [ + TRUE_KW, FALSE_KW, + INT_NUMBER, FLOAT_NUMBER, + BYTE, CHAR, + STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING, + ]; + node_if(p, AnyOf(&literals), LITERAL, |_| ()) } \ 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 { fn fn_item(p: &mut Parser) { p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN) - && p.curly_block(|p| ()); + && p.curly_block(|_| ()); } 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) { fn visibility(_: &mut Parser) { } -fn node_if( +fn node_if( p: &mut Parser, - first: SyntaxKind, + first: L, node_kind: SyntaxKind, rest: F ) -> bool { - p.current() == first && { node(p, node_kind, |p| { p.bump(); rest(p); }); true } + first.is_ahead(p) && { node(p, node_kind, |p| { L::consume(p); rest(p); }); true } } fn node(p: &mut Parser, node_kind: SyntaxKind, rest: F) { @@ -99,13 +99,63 @@ impl<'p> Parser<'p> { } } - fn bump_n(&mut self, n: u8) { - for _ in 0..n { - self.bump(); - } - } - fn eat(&mut self, kind: SyntaxKind) -> bool { self.current() == kind && { self.bump(); true } } +} + +trait Lookahead: Copy { + fn is_ahead(self, p: &Parser) -> bool; + fn consume(p: &mut Parser); +} + +impl Lookahead for SyntaxKind { + fn is_ahead(self, p: &Parser) -> bool { + p.current() == self + } + + fn consume(p: &mut Parser) { + p.bump(); + } +} + +impl Lookahead for [SyntaxKind; 2] { + fn is_ahead(self, p: &Parser) -> bool { + p.current() == self[0] + && p.raw_lookahead(1) == self[1] + } + + fn consume(p: &mut Parser) { + p.bump(); + p.bump(); + } +} + +impl Lookahead for [SyntaxKind; 3] { + fn is_ahead(self, p: &Parser) -> bool { + p.current() == self[0] + && p.raw_lookahead(1) == self[1] + && p.raw_lookahead(2) == self[2] + } + + fn consume(p: &mut Parser) { + p.bump(); + p.bump(); + p.bump(); + } +} + +#[derive(Clone, Copy)] +struct AnyOf<'a>(&'a [SyntaxKind]); + +impl<'a> Lookahead for AnyOf<'a> { + fn is_ahead(self, p: &Parser) -> bool { + let curr = p.current(); + self.0.iter().any(|&k| k == curr) + } + + fn consume(p: &mut Parser) { + p.bump(); + } + } \ 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> { kind } - pub(crate) fn lookahead(&self, kinds: &[SyntaxKind]) -> bool { - if self.tokens[self.pos..].len() < kinds.len() { - return false - } - kinds.iter().zip(self.tokens[self.pos..].iter().map(|t| t.kind)) - .all(|(&k1, k2)| k1 == k2) + pub(crate) fn raw_lookahead(&self, n: usize) -> SyntaxKind { + self.tokens.get(self.pos + n).map(|t| t.kind).unwrap_or(EOF) } pub(crate) fn curly_block(&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 { WHITESPACE | COMMENT => true, _ => false, } -} \ No newline at end of file +} -- cgit v1.2.3