about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2021-03-03T11·08+0200
committertazjin <mail@tazj.in>2021-03-06T11·52+0000
commit822e5ae57f8253e83d40b6a8d686d774b1500a3f (patch)
treec93d09e9a02e988d8e47e23b90c64eb60b5a30ff
parentb810c46a45c0bbf52b8a896d6d5d37f79f027d9f (diff)
fix(tazjin/rlox): Resynchronise after panicking r/2271
Change-Id: I60939f7a2c523b6ca1e9782e58c97959da38cfff
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2591
Reviewed-by: tazjin <mail@tazj.in>
Tested-by: BuildkiteCI
-rw-r--r--users/tazjin/rlox/src/bytecode/compiler.rs33
1 files changed, 32 insertions, 1 deletions
diff --git a/users/tazjin/rlox/src/bytecode/compiler.rs b/users/tazjin/rlox/src/bytecode/compiler.rs
index 9a8f80ae2b..8e70067e31 100644
--- a/users/tazjin/rlox/src/bytecode/compiler.rs
+++ b/users/tazjin/rlox/src/bytecode/compiler.rs
@@ -174,7 +174,13 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
     }
 
     fn declaration(&mut self) -> LoxResult<()> {
-        self.statement()
+        self.statement()?;
+
+        if self.panic {
+            self.synchronise();
+        }
+
+        Ok(())
     }
 
     fn statement(&mut self) -> LoxResult<()> {
@@ -396,6 +402,31 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
     fn check(&self, token: &TokenKind) -> bool {
         return self.current().kind == *token;
     }
+
+    fn synchronise(&mut self) {
+        self.panic = false;
+
+        while self.current().kind != TokenKind::Eof {
+            if self.previous().kind == TokenKind::Semicolon {
+                return;
+            }
+
+            match self.current().kind {
+                TokenKind::Class
+                | TokenKind::Fun
+                | TokenKind::Var
+                | TokenKind::For
+                | TokenKind::If
+                | TokenKind::While
+                | TokenKind::Print
+                | TokenKind::Return => return,
+
+                _ => {
+                    self.advance();
+                }
+            }
+        }
+    }
 }
 
 pub fn compile(code: &str) -> Result<(Interner, Chunk), Vec<Error>> {