diff --git a/src/interpreter.rs b/src/interpreter.rs index e67c1ad..993a291 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -35,6 +35,8 @@ impl Interpreter { (Value::I64(lhs), Value::I64(rhs)) => match bo { BinOpType::Add => Value::I64(lhs + rhs), BinOpType::Mul => Value::I64(lhs * rhs), + BinOpType::Sub => Value::I64(lhs - rhs), + BinOpType::Div => Value::I64(lhs / rhs), }, // _ => panic!("Value types are not compatible"), } diff --git a/src/lexer.rs b/src/lexer.rs index ee328fc..45a1d07 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -10,9 +10,15 @@ pub enum Token { /// Plus (+) Add, + /// Minus (-) + Sub, + /// Asterisk (*) Mul, + /// Slash (/) + Div, + /// End of file EoF, } @@ -60,7 +66,9 @@ impl<'a> Lexer<'a> { } '+' => tokens.push(Token::Add), + '-' => tokens.push(Token::Sub), '*' => tokens.push(Token::Mul), + '/' => tokens.push(Token::Div), //TODO: Don't panic, keep calm _ => panic!("Lexer encountered unexpected char: '{}'", ch), @@ -93,7 +101,9 @@ impl Token { pub fn try_to_binop(&self) -> Option { Some(match self { Token::Add => BinOpType::Add, + Token::Sub => BinOpType::Sub, Token::Mul => BinOpType::Mul, + Token::Div => BinOpType::Div, _ => return None, }) } diff --git a/src/parser.rs b/src/parser.rs index 1f4573e..f8af0d8 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -8,8 +8,14 @@ pub enum BinOpType { /// Addition Add, + /// Subtraction + Sub, + /// Multiplication Mul, + + /// Divide + Div, } #[derive(Debug, PartialEq, Eq, Clone)] @@ -20,6 +26,15 @@ pub enum Ast { BinOp(BinOpType, Box, Box), } +/* +## Grammar +### Expressions +`expr_primary = LITERAL` \ +`expr_mul = expr_primary (("*" | "/") expr_primary)*` \ +`expr_add = expr_mul (("+" | "-") expr_mul)*` \ +`expr = expr_add` \ +*/ + struct Parser> { tokens: Peekable, } @@ -40,9 +55,12 @@ impl> Parser { self.parse_expr_precedence(lhs, 0) } + + /// Parse binary expressions with a precedence equal to or higher than min_prec fn parse_expr_precedence(&mut self, mut lhs: Ast, min_prec: u8) -> Ast { while let Some(binop) = &self.peek().try_to_binop() { + // Stop if the next operator has a lower binding power if !(binop.precedence() >= min_prec) { break; } @@ -97,8 +115,8 @@ impl BinOpType { /// For example Multiplication is stronger than addition, so Mul has higher precedence than Add. fn precedence(&self) -> u8 { match self { - BinOpType::Add => 0, - BinOpType::Mul => 1, + BinOpType::Add | BinOpType::Sub => 0, + BinOpType::Mul | BinOpType::Div => 1, } } }