Implement unary negation

This commit is contained in:
Daniel M 2022-01-28 14:21:57 +01:00
parent 74dbf724a5
commit 3c6fb5466e
2 changed files with 27 additions and 5 deletions

View File

@ -1,4 +1,4 @@
use crate::parser::{Ast, BinOpType}; use crate::parser::{Ast, BinOpType, UnOpType};
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum Value { pub enum Value {
@ -24,6 +24,7 @@ impl Interpreter {
match expr { match expr {
Ast::I64(val) => Value::I64(val), Ast::I64(val) => Value::I64(val),
Ast::BinOp(bo, lhs, rhs) => self.resolve_binop(bo, *lhs, *rhs), 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"), // _ => 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)] #[cfg(test)]

View File

@ -36,18 +36,27 @@ pub enum BinOpType {
Shr, Shr,
} }
/// Types for unary operators
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum UnOpType {
/// Negation
Neg,
}
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum Ast { pub enum Ast {
/// Integer literal (64-bit) /// Integer literal (64-bit)
I64(i64), I64(i64),
/// Binary operation. Consists of type, left hand side and right hand side /// Binary operation. Consists of type, left hand side and right hand side
BinOp(BinOpType, Box<Ast>, Box<Ast>), BinOp(BinOpType, Box<Ast>, Box<Ast>),
/// Unary operation. Consists of type and the value that is operated on
UnOp(UnOpType, Box<Ast>),
} }
/* /*
## Grammar ## Grammar
### Expressions ### Expressions
expr_primary = LITERAL | "(" expr ")" expr_primary = LITERAL | "(" expr ")" | "-" expr_primary
expr_mul = expr_primary (("*" | "/" | "%") expr_primary)* expr_mul = expr_primary (("*" | "/" | "%") expr_primary)*
expr_add = expr_mul (("+" | "-") expr_mul)* expr_add = expr_mul (("+" | "-") expr_mul)*
expr_shift = expr_add ((">>" | "<<") expr_add)* expr_shift = expr_add ((">>" | "<<") expr_add)*
@ -123,6 +132,8 @@ impl<T: Iterator<Item = Token>> Parser<T> {
inner inner
} }
Token::Sub => Ast::UnOp(UnOpType::Neg, self.parse_primary().into()),
tok => panic!("Error parsing primary expr: Unexpected Token '{:?}'", tok), tok => panic!("Error parsing primary expr: Unexpected Token '{:?}'", tok),
} }
} }