Implement unary negate
This commit is contained in:
parent
8f79440219
commit
2a59fe8c84
@ -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
|
||||||
|
|||||||
@ -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"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user