From 89bb18a1ad21ad747305230ea6d1c18e181c228b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Baltasar=20S=C3=A1nchez=20E?= Date: Sat, 6 May 2023 20:58:03 -0600 Subject: [PATCH] ternary expressions added. seem ok --- exp.lox | 4 ++++ expressions.py | 8 ++++++++ interpreter.py | 7 +++++++ parser.py | 27 +++++++++++++++++++++++---- scanner.py | 3 +++ src.lox | 12 +++++++----- statements.py | 2 +- 7 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 exp.lox diff --git a/exp.lox b/exp.lox new file mode 100644 index 0000000..e8a8b61 --- /dev/null +++ b/exp.lox @@ -0,0 +1,4 @@ +(13 > (5 * 3 + 9)); +123 != 12312 + (2.3 == 123) * 9.12 +// asf asf +1+2-3*4/5 // saywha diff --git a/expressions.py b/expressions.py index 29118c0..221c43d 100644 --- a/expressions.py +++ b/expressions.py @@ -32,6 +32,12 @@ class Unary(Expr): class Variable(Expr): name: Token #identifier +@dataclass +class Ternary(Expr): + comparison: Expr + left: Expr # true evaluation, comparison must be boolean + right: Expr + class AstPrinter(Visitor): """only good at printing out (and making strings) from binary expressions""" @@ -65,6 +71,8 @@ def visitUnary(self, expr): def visitBinary(self, expr): return self.parensiffy(expr.op.lexeme, expr.left, expr.right) + def visitTernary(self, expr): + return f'if [{expr.comparison}]; then [{expr.left}]; else [{expr.right}]' """ def visitExpr(self, expr): return self.parensiffy(expr.expr) diff --git a/interpreter.py b/interpreter.py index 1c41d73..e3ac530 100644 --- a/interpreter.py +++ b/interpreter.py @@ -25,6 +25,13 @@ def visitStmtPrint(self, stmt): print(val) return val + def visitStmtVar(self, stmt): + """ + stmt.name + stmt.initializer + """ + ... + def visitLiteral(self, expr): return expr.value diff --git a/parser.py b/parser.py index 4308527..b7ed80e 100644 --- a/parser.py +++ b/parser.py @@ -87,7 +87,9 @@ class Parser(ParserNav): exprStmt → expression ";" ; printStmt → "print" expression ";" ; - expression → equality ; + expression → equality | + ternary ; + ternary → equality "?" expression ":" expression ; equality → comparison ( ( "!=" | "==" ) comparison )* ; comparison → term ( ( ">" | ">=" | "<" | "<=" ) term )* ; term → factor ( ( "-" | "+" ) factor )* ; @@ -97,7 +99,7 @@ class Parser(ParserNav): primary → NUMBER | STRING | "true" | "false" | "nil" | "(" expression ")" | IDENTIFIER ; - """ + """ def __init__(self, tokens: list[Token]): self.tokens = tokens @@ -147,12 +149,29 @@ def printStmt(self): def expressionStmt(self): val = self.expression() - assert isinstance(val, Expr) + + # if val is None: + # val = Expr() + # next assert is now guaranteed... lame + assert isinstance(val, (Stmt, Expr)), f"{val}. repr: `"+repr(val)+"`" + self.consume(TokenType.SEMICOLON, "expected a ';' after expressionStmt. where is my ; !?") return StmtExpr(val) def expression(self): - return self.equality() + """ + expression → equality | + ternary ; + """ + eq = self.equality() + + if self.match(TokenType.QUESTION): + left = self.expression() + self.consume(TokenType.COLON, "Expected ':' for a ternary expr.") + right = self.expression() + return Ternary(eq, left, right) + else: + return eq def equality(self): expr = self.comparison() diff --git a/scanner.py b/scanner.py index 87bb436..425a490 100644 --- a/scanner.py +++ b/scanner.py @@ -35,6 +35,9 @@ class TokenType(Enum): LESS = '<' LESS_EQUAL = '<=' + QUESTION = '?' + COLON = ':' + # // Literals. IDENTIFIER = auto() STRING = auto() diff --git a/src.lox b/src.lox index 38e3caf..728edff 100644 --- a/src.lox +++ b/src.lox @@ -1,6 +1,8 @@ -// sample, should write a real program. -() [] [ ] ([]) (]) -"strings" -123 -123.1233 var language = "lox"; +var test = + 1 == 2 ? "help" : "we cool, no help"; + + +"strings"; +123; +123.1233; // sample, should write a real program. diff --git a/statements.py b/statements.py index 5b5960a..eb37028 100644 --- a/statements.py +++ b/statements.py @@ -30,7 +30,7 @@ def __init__(self): def print(self, stmt): # Visitor.start_walk - print(stmt.accept(visitor=self)) + print(f'{stmt.__class__.__name__}({stmt.accept(visitor=self)})') def _exprVisit(self, expr): return expr.accept(visitor=self.exprPrinter)