From 5868d4bd49a7b80a395f1ecabedeb0b8f4ddffce Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Mon, 18 Jan 2021 20:27:14 +0300 Subject: [PATCH] refactor(tazjin/rlox): Prepare scanner for shared use In the book, the clox interpreter has its own scanner which uses a pull-based model for a single pass compiler. I can't be bothered to write another scanner, or amend this one into pull-mode to work with the treewalk interpreter, so instead I will just reuse it and pull from a vector of tokens. The tokens are shared between both interpreters and the scanner is not what I'm interested in here. Change-Id: Ib07e89127fce2b047f9b3e1ff7e9908d798b3b2b Reviewed-on: https://cl.tvl.fyi/c/depot/+/2420 Reviewed-by: tazjin Tested-by: BuildkiteCI --- users/tazjin/rlox/src/main.rs | 1 + .../tazjin/rlox/src/{treewalk => }/scanner.rs | 21 ++++++++++--------- users/tazjin/rlox/src/treewalk/errors.rs | 18 ++++++++++++++++ users/tazjin/rlox/src/treewalk/interpreter.rs | 4 +++- users/tazjin/rlox/src/treewalk/mod.rs | 3 ++- 5 files changed, 35 insertions(+), 12 deletions(-) rename users/tazjin/rlox/src/{treewalk => }/scanner.rs (94%) diff --git a/users/tazjin/rlox/src/main.rs b/users/tazjin/rlox/src/main.rs index c9cc96d2e..3a956833c 100644 --- a/users/tazjin/rlox/src/main.rs +++ b/users/tazjin/rlox/src/main.rs @@ -5,6 +5,7 @@ use std::io::Write; use std::process; mod bytecode; +mod scanner; mod treewalk; /// Trait for making the different interpreters callable in the same diff --git a/users/tazjin/rlox/src/treewalk/scanner.rs b/users/tazjin/rlox/src/scanner.rs similarity index 94% rename from users/tazjin/rlox/src/treewalk/scanner.rs rename to users/tazjin/rlox/src/scanner.rs index af9075484..314b56d6d 100644 --- a/users/tazjin/rlox/src/treewalk/scanner.rs +++ b/users/tazjin/rlox/src/scanner.rs @@ -1,5 +1,3 @@ -use crate::treewalk::errors::{Error, ErrorKind}; - #[derive(Clone, Debug, PartialEq)] pub enum TokenKind { // Single-character tokens. @@ -59,10 +57,15 @@ pub struct Token { pub line: usize, } +pub enum ScannerError { + UnexpectedChar { line: usize, unexpected: char }, + UnterminatedString { line: usize }, +} + struct Scanner<'a> { source: &'a [char], tokens: Vec, - errors: Vec, + errors: Vec, start: usize, // offset of first character in current lexeme current: usize, // current offset into source line: usize, // current line in source @@ -131,9 +134,9 @@ impl<'a> Scanner<'a> { chr if chr.is_alphabetic() || chr == '_' => self.scan_identifier(), - unexpected => self.errors.push(Error { + unexpected => self.errors.push(ScannerError::UnexpectedChar { line: self.line, - kind: ErrorKind::UnexpectedChar(unexpected), + unexpected, }), }; } @@ -181,10 +184,8 @@ impl<'a> Scanner<'a> { } if self.is_at_end() { - self.errors.push(Error { - line: self.line, - kind: ErrorKind::UnterminatedString, - }); + self.errors + .push(ScannerError::UnterminatedString { line: self.line }); return; } @@ -263,7 +264,7 @@ impl<'a> Scanner<'a> { } } -pub fn scan<'a>(input: &'a [char]) -> Result, Vec> { +pub fn scan<'a>(input: &'a [char]) -> Result, Vec> { let mut scanner = Scanner { source: &input, tokens: vec![], diff --git a/users/tazjin/rlox/src/treewalk/errors.rs b/users/tazjin/rlox/src/treewalk/errors.rs index 54d2718ee..391663d51 100644 --- a/users/tazjin/rlox/src/treewalk/errors.rs +++ b/users/tazjin/rlox/src/treewalk/errors.rs @@ -1,4 +1,6 @@ +use crate::scanner::ScannerError; use crate::treewalk::interpreter::Value; + use std::fmt; #[derive(Debug)] @@ -39,3 +41,19 @@ impl fmt::Display for Error { write!(f, "[line {}] Error: {:?}", self.line, self.kind) } } + +impl From for Error { + fn from(err: ScannerError) -> Self { + match err { + ScannerError::UnexpectedChar { line, unexpected } => Error { + line, + kind: ErrorKind::UnexpectedChar(unexpected), + }, + + ScannerError::UnterminatedString { line } => Error { + line, + kind: ErrorKind::UnterminatedString, + }, + } + } +} diff --git a/users/tazjin/rlox/src/treewalk/interpreter.rs b/users/tazjin/rlox/src/treewalk/interpreter.rs index 1263e6cb8..3285775bb 100644 --- a/users/tazjin/rlox/src/treewalk/interpreter.rs +++ b/users/tazjin/rlox/src/treewalk/interpreter.rs @@ -200,7 +200,9 @@ impl Lox for Interpreter { fn interpret(&mut self, code: String) -> Result> { let chars: Vec = code.chars().collect(); - let mut program = scanner::scan(&chars).and_then(|tokens| parser::parse(tokens))?; + let mut program = scanner::scan(&chars) + .map_err(|errors| errors.into_iter().map(Into::into).collect()) + .and_then(|tokens| parser::parse(tokens))?; let globals = self .env diff --git a/users/tazjin/rlox/src/treewalk/mod.rs b/users/tazjin/rlox/src/treewalk/mod.rs index d53bd13f8..2d82b3320 100644 --- a/users/tazjin/rlox/src/treewalk/mod.rs +++ b/users/tazjin/rlox/src/treewalk/mod.rs @@ -1,5 +1,6 @@ +use crate::scanner; + mod errors; pub mod interpreter; mod parser; mod resolver; -mod scanner;