diff options
| -rw-r--r-- | src/interpret/mod.rs | 1 | ||||
| -rw-r--r-- | src/interpret/walker.rs | 150 | ||||
| -rw-r--r-- | src/main.rs | 10 |
3 files changed, 159 insertions, 2 deletions
diff --git a/src/interpret/mod.rs b/src/interpret/mod.rs new file mode 100644 index 0000000..2544ca3 --- /dev/null +++ b/src/interpret/mod.rs @@ -0,0 +1 @@ +pub mod walker; \ No newline at end of file diff --git a/src/interpret/walker.rs b/src/interpret/walker.rs new file mode 100644 index 0000000..1602cd2 --- /dev/null +++ b/src/interpret/walker.rs @@ -0,0 +1,150 @@ +use std::{ + fmt::Display, + ops::{Add, Div, Mul, Neg, Sub}, +}; + +use crate::{lex::token::TokenVariant::*, parse::ast::Expression}; +use anyhow::Result; + +// No state for now. +pub struct Walker {} + +impl Walker { + pub fn new() -> Self { + Walker {} + } + + pub fn walk(&self, node: &Expression) -> Result<WalkValue> { + match node { + Expression::Binary { left, op, right } => { + let left_value = self.walk(left)?; + let right_value = self.walk(right)?; + + let new_value = match op.variant { + OpPlus => left_value + right_value, + OpMinus => left_value - right_value, + OpStar => left_value * right_value, + OpSlash => left_value / right_value, + _ => unreachable!(), + }; + + Ok(new_value) + } + Expression::Unary { op, right } => { + let value = self.walk(right)?; + + let new_value = match op.variant { + OpPlus => value, + OpMinus => -value, + OpNot => todo!("Implement boolean arithmetic."), + _ => unreachable!(), + }; + + Ok(new_value) + } + Expression::Group(node) => self.walk(node), + Expression::Literal(token) => { + let value = match token.variant { + Int(int) => WalkValue::Int(int as i64), + Float(float) => WalkValue::Float(float as f64), + _ => unreachable!(), + }; + + Ok(value) + } + } + } +} + +pub enum WalkValue { + Float(f64), + Int(i64), +} + +impl Add for WalkValue { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + match self { + Self::Float(float) => match rhs { + Self::Float(other_float) => Self::Float(float + other_float), + Self::Int(other_int) => Self::Float(float + other_int as f64), + }, + Self::Int(int) => match rhs { + Self::Float(other_float) => Self::Float(int as f64 + other_float), + Self::Int(other_int) => Self::Int(int + other_int), + }, + } + } +} + +impl Sub for WalkValue { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + match self { + Self::Float(float) => match rhs { + Self::Float(other_float) => Self::Float(float - other_float), + Self::Int(other_int) => Self::Float(float - other_int as f64), + }, + Self::Int(int) => match rhs { + Self::Float(other_float) => Self::Float(int as f64 - other_float), + Self::Int(other_int) => Self::Int(int - other_int), + }, + } + } +} + +impl Mul for WalkValue { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + match self { + Self::Float(float) => match rhs { + Self::Float(other_float) => Self::Float(float * other_float), + Self::Int(other_int) => Self::Float(float * other_int as f64), + }, + Self::Int(int) => match rhs { + Self::Float(other_float) => Self::Float(int as f64 * other_float), + Self::Int(other_int) => Self::Int(int * other_int), + }, + } + } +} + +impl Div for WalkValue { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + match self { + Self::Float(float) => match rhs { + Self::Float(other_float) => Self::Float(float / other_float), + Self::Int(other_int) => Self::Float(float / other_int as f64), + }, + Self::Int(int) => match rhs { + Self::Float(other_float) => Self::Float(int as f64 / other_float), + Self::Int(other_int) => Self::Int(int / other_int), + }, + } + } +} + +impl Neg for WalkValue { + type Output = Self; + + fn neg(self) -> Self::Output { + match self { + Self::Float(float) => Self::Float(-float), + Self::Int(int) => Self::Int(-int), + } + } +} + +impl Display for WalkValue { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Float(float) => write!(f, "{}", float), + Self::Int(int) => write!(f, "{}", int), + } + } +} diff --git a/src/main.rs b/src/main.rs index 3fa6bbf..1825af5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,11 @@ +mod interpret; mod lex; mod parse; use lex::lexer::Lexer; -use crate::parse::parser::Parser; +use interpret::walker::Walker; +use parse::parser::Parser; fn main() { let source = "1 * 2 + 3 + (-1)"; @@ -11,5 +13,9 @@ fn main() { let lexer = Lexer::new(source); let mut parser = Parser::new(lexer); - println!("{}", parser.parse().expect("Failed parsing.")); + let node = parser.parse().expect("Failed parsing."); + + let walker = Walker::new(); + let result = walker.walk(&node).expect("Failed interpreting."); + println!("{}", result); } |
