From fabe3ef2ad1cd44250b64fbf9e894f136228a21e Mon Sep 17 00:00:00 2001 From: Daniel M Date: Sat, 29 Jan 2022 21:12:01 +0100 Subject: [PATCH] Implement unary negate --- README.md | 4 ++-- src/interpreter.rs | 12 +++++++++++- src/parser.rs | 18 +++++++++++++++++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index efc6e0a..6be08cb 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/interpreter.rs b/src/interpreter.rs index a97b21e..3899908 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,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"), } } diff --git a/src/parser.rs b/src/parser.rs index 4ee2034..54debc9 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -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, Box), + /// Unary operation. Consists of type and operand + UnOp(UnOpType, Box), } /* ## 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> Parser { /// 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> Parser { 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), } }