diff options
author | Vincent Ambo <mail@tazj.in> | 2021-02-27T19·23+0200 |
---|---|---|
committer | tazjin <mail@tazj.in> | 2021-02-27T20·19+0000 |
commit | 7778a58f8d80147a5b180e0a889c245b47d573a5 (patch) | |
tree | 3441df27854852eea1695d4e73bac96ad504f451 /users/tazjin/rlox/src | |
parent | d2f24c925d67665f74b2707260f88723895b0308 (diff) |
feat(tazjin/rlox): Add initial Pratt parser table lookup r/2241
Change-Id: I1b894d2f84d23ddddcd1bb8794f771512b7d677e Reviewed-on: https://cl.tvl.fyi/c/depot/+/2560 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
Diffstat (limited to 'users/tazjin/rlox/src')
-rw-r--r-- | users/tazjin/rlox/src/bytecode/compiler/mod.rs | 76 |
1 files changed, 67 insertions, 9 deletions
diff --git a/users/tazjin/rlox/src/bytecode/compiler/mod.rs b/users/tazjin/rlox/src/bytecode/compiler/mod.rs index a4cc43491030..fab06fe39cf2 100644 --- a/users/tazjin/rlox/src/bytecode/compiler/mod.rs +++ b/users/tazjin/rlox/src/bytecode/compiler/mod.rs @@ -33,6 +33,28 @@ enum Precedence { Primary, } +type ParseFn<T> = fn(&mut Compiler<T>) -> LoxResult<()>; + +struct ParseRule<T: Iterator<Item = Token>> { + prefix: Option<ParseFn<T>>, + infix: Option<ParseFn<T>>, + precedence: Precedence, +} + +impl<T: Iterator<Item = Token>> ParseRule<T> { + fn new( + prefix: Option<ParseFn<T>>, + infix: Option<ParseFn<T>>, + precedence: Precedence, + ) -> Self { + ParseRule { + prefix, + infix, + precedence, + } + } +} + impl Precedence { // Return the next highest precedence, if there is one. fn next(&self) -> Self { @@ -54,6 +76,38 @@ impl Precedence { } } +fn rule_for<T: Iterator<Item = Token>>(token: &TokenKind) -> ParseRule<T> { + match token { + TokenKind::LeftParen => { + ParseRule::new(Some(Compiler::grouping), None, Precedence::None) + } + + TokenKind::Minus => ParseRule::new( + Some(Compiler::unary), + Some(Compiler::binary), + Precedence::Term, + ), + + TokenKind::Plus => { + ParseRule::new(None, Some(Compiler::binary), Precedence::Term) + } + + TokenKind::Slash => { + ParseRule::new(None, Some(Compiler::binary), Precedence::Factor) + } + + TokenKind::Star => { + ParseRule::new(None, Some(Compiler::binary), Precedence::Factor) + } + + TokenKind::Number(_) => { + ParseRule::new(Some(Compiler::number), None, Precedence::None) + } + + _ => ParseRule::new(None, None, Precedence::None), + } +} + impl<T: Iterator<Item = Token>> Compiler<T> { fn compile(&mut self) -> LoxResult<()> { self.advance(); @@ -77,11 +131,12 @@ impl<T: Iterator<Item = Token>> Compiler<T> { // TODO(tazjin): Assumption is that we have access to the previous // token wherever this ends up invoked. True? - fn number(&mut self, num: f64) { + fn number(&mut self) -> LoxResult<()> { + let num = unimplemented!("get out of previous()"); self.emit_constant(num); } - fn grouping(&mut self, num: f64) -> LoxResult<()> { + fn grouping(&mut self) -> LoxResult<()> { self.expression()?; self.consume( &TokenKind::RightParen, @@ -110,8 +165,8 @@ impl<T: Iterator<Item = Token>> Compiler<T> { let operator = self.previous().kind.clone(); // Compile the right operand - let rule = self.get_rule(&operator); - self.parse_precedence(unimplemented!("rule.precendece.next()"))?; + let rule: ParseRule<T> = rule_for(&operator); + self.parse_precedence(rule.precedence)?; // Emit operator instruction match operator { @@ -125,12 +180,15 @@ impl<T: Iterator<Item = Token>> Compiler<T> { unimplemented!() } - fn get_rule(&mut self, op: &TokenKind) -> usize { - unimplemented!(); - } - fn parse_precedence(&mut self, precedence: Precedence) -> LoxResult<()> { - unimplemented!("what goes here?") + self.advance(); + let rule: ParseRule<T> = rule_for(&self.previous().kind); + + if let Some(func) = rule.prefix { + func(self)?; + } + + unimplemented!("expect expression?") } fn consume( |