about summary refs log tree commit diff
path: root/users/tazjin/rlox
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2021-02-27T19·23+0200
committertazjin <mail@tazj.in>2021-02-27T20·19+0000
commit7778a58f8d80147a5b180e0a889c245b47d573a5 (patch)
tree3441df27854852eea1695d4e73bac96ad504f451 /users/tazjin/rlox
parentd2f24c925d67665f74b2707260f88723895b0308 (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')
-rw-r--r--users/tazjin/rlox/src/bytecode/compiler/mod.rs76
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 a4cc434910..fab06fe39c 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(