diff --git a/src/interpreter.rs b/src/interpreter.rs index a97b21e..05a73c5 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -1,4 +1,4 @@ -use crate::parser::{Ast, BinOpType}; +use crate::parser::{Ast, BinOpType, UnOpType}; #[derive(Debug, PartialEq, Eq, Clone)] pub enum Value { @@ -24,6 +24,7 @@ impl Interpreter { match expr { Ast::I64(val) => Value::I64(val), Ast::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, *lhs, *rhs), + Ast::UnOp(uo, val) => self.resolve_unop(uo, *val), } } @@ -47,6 +48,16 @@ impl Interpreter { // _ => panic!("Value types are not compatible"), } } + + fn resolve_unop(&mut self, uo: UnOpType, val: Ast) -> Value { + let val = self.resolve_expr(val); + match val { + Value::I64(val) => match uo { + UnOpType::Neg => Value::I64(-val), + } + } + } + } #[cfg(test)] diff --git a/src/parser.rs b/src/parser.rs index 1813719..ecda899 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -36,18 +36,27 @@ pub enum BinOpType { Shr, } +/// Types for unary operators +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum UnOpType { + /// Negation + Neg, +} + #[derive(Debug, PartialEq, Eq, Clone)] pub enum Ast { /// Integer literal (64-bit) I64(i64), /// Binary operation. Consists of type, left hand side and right hand side BinOp(BinOpType, Box, Box), + /// Unary operation. Consists of type and the value that is operated on + UnOp(UnOpType, Box), } /* ## Grammar ### Expressions -expr_primary = LITERAL | "(" expr ")" +expr_primary = LITERAL | "(" expr ")" | "-" expr_primary expr_mul = expr_primary (("*" | "/" | "%") expr_primary)* expr_add = expr_mul (("+" | "-") expr_mul)* expr_shift = expr_add ((">>" | "<<") expr_add)* @@ -111,7 +120,7 @@ impl> Parser { Token::I64(val) => Ast::I64(val), Token::LParen => { - // The tokens was an opening parenthesis, so parse a full expression again as the + // The tokens was an opening parenthesis, so parse a full expression again as the // expression inside the parentheses `"(" expr ")"` let inner = self.parse_expr(); @@ -123,6 +132,8 @@ impl> Parser { inner } + Token::Sub => Ast::UnOp(UnOpType::Neg, self.parse_primary().into()), + tok => panic!("Error parsing primary expr: Unexpected Token '{:?}'", tok), } } @@ -146,9 +157,9 @@ pub fn parse, A: IntoIterator>(tokens: A impl BinOpType { /// Get the precedence for a binary operator. Higher value means the OP is stronger binding. /// For example Multiplication is stronger than addition, so Mul has higher precedence than Add. - /// + /// /// The operator precedences are derived from the C language operator precedences. While not all - /// C operators are included or the exact same, the precedence oder is the same. + /// C operators are included or the exact same, the precedence oder is the same. /// See: https://en.cppreference.com/w/c/language/operator_precedence fn precedence(&self) -> u8 { match self {