Implement unary negate
This commit is contained in:
parent
3535fec208
commit
fabe3ef2ad
@ -10,8 +10,8 @@
|
||||
## Language features
|
||||
|
||||
- [x] Math expressions
|
||||
- [ ] Unary operators
|
||||
- [ ] Negate `-X`
|
||||
- [x] Unary operators
|
||||
- [x] Negate `-X`
|
||||
- [x] Parentheses `(X+Y)*Z`
|
||||
- [ ] Logical boolean operators
|
||||
- [ ] Variables
|
||||
|
||||
@ -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,16 @@ impl Interpreter {
|
||||
match expr {
|
||||
Ast::I64(val) => Value::I64(val),
|
||||
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"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -36,18 +36,26 @@ pub enum BinOpType {
|
||||
Shr,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum UnOpType {
|
||||
/// Unary Negate
|
||||
Negate,
|
||||
}
|
||||
|
||||
#[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<Ast>, Box<Ast>),
|
||||
/// Unary operation. Consists of type and operand
|
||||
UnOp(UnOpType, Box<Ast>),
|
||||
}
|
||||
|
||||
/*
|
||||
## Grammar
|
||||
### Expressions
|
||||
expr_primary = LITERAL | "(" expr ")"
|
||||
expr_primary = LITERAL | "(" expr p | "-" expr_primary
|
||||
expr_mul = expr_primary (("*" | "/" | "%") expr_primary)*
|
||||
expr_add = expr_mul (("+" | "-") expr_mul)*
|
||||
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)
|
||||
fn parse_primary(&mut self) -> Ast {
|
||||
match self.next() {
|
||||
// Literal i64
|
||||
Token::I64(val) => Ast::I64(val),
|
||||
|
||||
// Parentheses grouping
|
||||
Token::LParen => {
|
||||
let inner_expr = self.parse_expr();
|
||||
|
||||
@ -121,6 +131,12 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user