diff options
author | Vincent Ambo <mail@tazj.in> | 2021-01-18T17·27+0300 |
---|---|---|
committer | tazjin <mail@tazj.in> | 2021-01-19T09·57+0000 |
commit | 5868d4bd49a7b80a395f1ecabedeb0b8f4ddffce (patch) | |
tree | 7f9b786e665f7ea103b256d9cab92bbb982d4770 /users/tazjin | |
parent | 2d136e03279e481021a23948fdf5556f25394cd3 (diff) |
refactor(tazjin/rlox): Prepare scanner for shared use r/2132
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 <mail@tazj.in> Tested-by: BuildkiteCI
Diffstat (limited to 'users/tazjin')
-rw-r--r-- | users/tazjin/rlox/src/main.rs | 1 | ||||
-rw-r--r-- | users/tazjin/rlox/src/scanner.rs (renamed from users/tazjin/rlox/src/treewalk/scanner.rs) | 21 | ||||
-rw-r--r-- | users/tazjin/rlox/src/treewalk/errors.rs | 18 | ||||
-rw-r--r-- | users/tazjin/rlox/src/treewalk/interpreter.rs | 4 | ||||
-rw-r--r-- | users/tazjin/rlox/src/treewalk/mod.rs | 3 |
5 files changed, 35 insertions, 12 deletions
diff --git a/users/tazjin/rlox/src/main.rs b/users/tazjin/rlox/src/main.rs index c9cc96d2e6a9..3a956833c15d 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 index af9075484145..314b56d6d380 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<Token>, - errors: Vec<Error>, + errors: Vec<ScannerError>, 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<Token>, Vec<Error>> { +pub fn scan<'a>(input: &'a [char]) -> Result<Vec<Token>, Vec<ScannerError>> { 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 54d2718eeda2..391663d51b18 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<ScannerError> 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 1263e6cb810b..3285775bbec6 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<Value, Vec<Error>> { let chars: Vec<char> = 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 d53bd13f8ede..2d82b3320a90 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; |