From cdad648f584a4db9be490ffee06429cd83324cd2 Mon Sep 17 00:00:00 2001 From: NikolajDanger Date: Tue, 31 Mar 2026 22:02:22 +0200 Subject: [PATCH] :goat: Negation --- centvrion/ast_nodes.py | 12 ++++++++++++ centvrion/parser.py | 7 ++++++- tests.py | 6 +++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/centvrion/ast_nodes.py b/centvrion/ast_nodes.py index b9e2ce5..ad0f461 100644 --- a/centvrion/ast_nodes.py +++ b/centvrion/ast_nodes.py @@ -330,6 +330,18 @@ class BinOp(Node): raise Exception(self.op) +class UnaryMinus(Node): + def __init__(self, expr): + self.expr = expr + + def __repr__(self): + return f"UnaryMinus({self.expr!r})" + + def _eval(self, vtable): + vtable, val = self.expr.eval(vtable) + return vtable, ValInt(-val.value()) + + class SiStatement(Node): def __init__(self, test, statements, else_part) -> None: self.test = test diff --git a/centvrion/parser.py b/centvrion/parser.py index 1a276f0..6d9a4ad 100644 --- a/centvrion/parser.py +++ b/centvrion/parser.py @@ -14,7 +14,8 @@ class Parser(): ('left', ["KEYWORD_ET"]), ('left', ["KEYWORD_PLVS", "KEYWORD_MINVS", "KEYWORD_EST"]), ('left', ["SYMBOL_PLUS", "SYMBOL_MINUS"]), - ('left', ["SYMBOL_TIMES", "SYMBOL_DIVIDE"]) + ('left', ["SYMBOL_TIMES", "SYMBOL_DIVIDE"]), + ('right', ["UMINUS"]), ] ) @@ -173,6 +174,10 @@ class Parser(): def binop(tokens): return ast_nodes.BinOp(tokens[0], tokens[2], tokens[1].name) + @self.pg.production('expression : SYMBOL_MINUS expression', precedence='UMINUS') + def unary_minus(tokens): + return ast_nodes.UnaryMinus(tokens[1]) + @self.pg.production('expression : KEYWORD_INVOCA id expressions') def invoca(tokens): return ast_nodes.Invoca(tokens[1], tokens[2]) diff --git a/tests.py b/tests.py index 39e4c76..a8d2b66 100644 --- a/tests.py +++ b/tests.py @@ -8,7 +8,7 @@ from centvrion.ast_nodes import ( Bool, BinOp, BuiltIn, DataArray, DataRangeArray, Defini, Designa, DumStatement, Erumpe, ExpressionStatement, ID, Invoca, ModuleCall, Nullus, Numeral, PerStatement, - Program, Redi, SiStatement, String, + Program, Redi, SiStatement, String, UnaryMinus, num_to_int, int_to_num, make_string, ) from centvrion.lexer import Lexer @@ -105,6 +105,10 @@ arithmetic_tests = [ ("X / III", None, ValInt(3)), # integer division: 10 // 3 = 3 ("II + III * IV", None, ValInt(14)), # precedence: 2 + (3*4) = 14 ("(II + III) * IV", None, ValInt(20)), # parens: (2+3)*4 = 20 + ("- III", None, ValInt(-3)), # unary negation + ("- (II + III)", None, ValInt(-5)), # unary negation of expression + ("- - II", None, ValInt(2)), # double negation + ("III + - II", None, ValInt(1)), # unary in binary context ] class TestArithmetic(unittest.TestCase):