Implement unary negate

This commit is contained in:
Kai-Philipp Nosper 2022-01-29 21:12:01 +01:00
parent 8f79440219
commit 2a59fe8c84
3 changed files with 30 additions and 4 deletions

View File

@ -10,8 +10,8 @@
## Language features ## Language features
- [x] Math expressions - [x] Math expressions
- [ ] Unary operators - [x] Unary operators
- [ ] Negate `-X` - [x] Negate `-X`
- [x] Parentheses `(X+Y)*Z` - [x] Parentheses `(X+Y)*Z`
- [ ] Logical boolean operators - [ ] Logical boolean operators
- [ ] Variables - [ ] Variables

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,16 @@ 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, operand) => self.resolve_unop(uo, *operand),
}
}
fn resolve_unop(&mut self, uo: UnOpType, operand: Ast) -> Value {
let operand = self.resolve_expr(operand);
match (operand, uo) {
(Value::I64(val), UnOpType::Negate) => Value::I64(-val),
// _ => panic!("Value type is not compatible with unary operation"),
} }
} }

View File

@ -36,18 +36,26 @@ pub enum BinOpType {
Shr, Shr,
} }
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum UnOpType {
/// Unary Negate
Negate,
}
#[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 operand
UnOp(UnOpType, Box<Ast>),
} }
/* /*
## Grammar ## Grammar
### Expressions ### Expressions
expr_primary = LITERAL | "(" expr ")" expr_primary = LITERAL | "(" expr p | "-" 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)*
@ -108,8 +116,10 @@ impl<T: Iterator<Item = Token>> Parser<T> {
/// Parse a primary expression (for now only number) /// Parse a primary expression (for now only number)
fn parse_primary(&mut self) -> Ast { fn parse_primary(&mut self) -> Ast {
match self.next() { match self.next() {
// Literal i64
Token::I64(val) => Ast::I64(val), Token::I64(val) => Ast::I64(val),
// Parentheses grouping
Token::LParen => { Token::LParen => {
let inner_expr = self.parse_expr(); let inner_expr = self.parse_expr();
@ -121,6 +131,12 @@ impl<T: Iterator<Item = Token>> Parser<T> {
inner_expr inner_expr
} }
// Unary negation
Token::Sub => {
let operand = self.parse_primary();
Ast::UnOp(UnOpType::Negate, operand.into())
}
tok => panic!("Error parsing primary expr: Unexpected Token '{:?}'", tok), tok => panic!("Error parsing primary expr: Unexpected Token '{:?}'", tok),
} }
} }