From 7778a58f8d80147a5b180e0a889c245b47d573a5 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sat, 27 Feb 2021 21:23:22 +0200 Subject: [PATCH] feat(tazjin/rlox): Add initial Pratt parser table lookup Change-Id: I1b894d2f84d23ddddcd1bb8794f771512b7d677e Reviewed-on: https://cl.tvl.fyi/c/depot/+/2560 Reviewed-by: tazjin Tested-by: BuildkiteCI --- .../tazjin/rlox/src/bytecode/compiler/mod.rs | 76 ++++++++++++++++--- 1 file 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 a4cc43491..fab06fe39 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 = fn(&mut Compiler) -> LoxResult<()>; + +struct ParseRule> { + prefix: Option>, + infix: Option>, + precedence: Precedence, +} + +impl> ParseRule { + fn new( + prefix: Option>, + infix: Option>, + 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>(token: &TokenKind) -> ParseRule { + 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> Compiler { fn compile(&mut self) -> LoxResult<()> { self.advance(); @@ -77,11 +131,12 @@ impl> Compiler { // 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> Compiler { 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 = rule_for(&operator); + self.parse_precedence(rule.precedence)?; // Emit operator instruction match operator { @@ -125,12 +180,15 @@ impl> Compiler { 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 = rule_for(&self.previous().kind); + + if let Some(func) = rule.prefix { + func(self)?; + } + + unimplemented!("expect expression?") } fn consume(