From 57e87978ef416ce2898a65a9b67e37be91263e67 Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Wed, 25 Nov 2020 22:06:42 -0800 Subject: Chapter 8: Add assignment --- src/com/craftinginterpreters/lox/AstPrinter.java | 5 +++++ src/com/craftinginterpreters/lox/Environment.java | 9 +++++++++ src/com/craftinginterpreters/lox/Interpreter.java | 7 +++++++ src/com/craftinginterpreters/lox/Parser.java | 20 +++++++++++++++++++- src/com/craftinginterpreters/tool/GenerateAst.java | 2 +- 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/com/craftinginterpreters/lox/AstPrinter.java b/src/com/craftinginterpreters/lox/AstPrinter.java index 82294c6..58376cb 100644 --- a/src/com/craftinginterpreters/lox/AstPrinter.java +++ b/src/com/craftinginterpreters/lox/AstPrinter.java @@ -35,6 +35,11 @@ class AstPrinter implements Expr.Visitor, Stmt.Visitor { return expr.name.lexeme; } + @Override + public String visitAssignExpr(Expr.Assign expression) { + return parenthesize(expression.name.lexeme + " = ", expression.value); + } + @Override public String visitVarStmt(Stmt.Var statement) { return parenthesize("define " + statement.name.lexeme + " = ", statement.initializer); diff --git a/src/com/craftinginterpreters/lox/Environment.java b/src/com/craftinginterpreters/lox/Environment.java index 634659b..8d8a374 100644 --- a/src/com/craftinginterpreters/lox/Environment.java +++ b/src/com/craftinginterpreters/lox/Environment.java @@ -14,6 +14,15 @@ class Environment { throw new RuntimeError(name, "Undefined variable '" + name.lexeme + "'."); } + void assign(Token name, Object value) { + if (values.containsKey(name.lexeme)) { + values.put(name.lexeme, value); + return; + } + + throw new RuntimeError(name, "Undefined variable '" + name.lexeme + "'."); + } + void define(String name, Object value) { values.put(name, value); } diff --git a/src/com/craftinginterpreters/lox/Interpreter.java b/src/com/craftinginterpreters/lox/Interpreter.java index f4e7f99..7378164 100644 --- a/src/com/craftinginterpreters/lox/Interpreter.java +++ b/src/com/craftinginterpreters/lox/Interpreter.java @@ -113,6 +113,13 @@ class Interpreter implements Expr.Visitor, Stmt.Visitor { return null; } + @Override + public Object visitAssignExpr(Expr.Assign expr) { + Object value = evaluate(expr.value); + environment.assign(expr.name, value); + return value; + } + @Override public Object visitBinaryExpr(Expr.Binary expr) { Object left = evaluate(expr.left); diff --git a/src/com/craftinginterpreters/lox/Parser.java b/src/com/craftinginterpreters/lox/Parser.java index 9a9c0e6..9e76a54 100644 --- a/src/com/craftinginterpreters/lox/Parser.java +++ b/src/com/craftinginterpreters/lox/Parser.java @@ -27,7 +27,7 @@ class Parser { } private Expr expression() { - return equality(); + return assignment(); } private Stmt declaration() { @@ -73,6 +73,24 @@ class Parser { return new Stmt.Expression(expr); } + private Expr assignment() { + Expr expr = equality(); + + if (match(EQUAL)) { + Token equals = previous(); + Expr value = assignment(); + + if (expr instanceof Expr.Variable) { + Token name = ((Expr.Variable) expr).name; + return new Expr.Assign(name, value); + } + + error(equals, "Invalid assignment target."); + } + + return expr; + } + private Expr equality() { Expr expr = comparison(); diff --git a/src/com/craftinginterpreters/tool/GenerateAst.java b/src/com/craftinginterpreters/tool/GenerateAst.java index d2cb5cf..f96e315 100644 --- a/src/com/craftinginterpreters/tool/GenerateAst.java +++ b/src/com/craftinginterpreters/tool/GenerateAst.java @@ -15,7 +15,7 @@ public class GenerateAst { String outputDir = args[0]; defineAst(outputDir, "Expr", - Arrays.asList("Binary : Expr left, Token operator, Expr right", "Grouping : Expr expression", + Arrays.asList("Assign : Token name, Expr value", "Binary : Expr left, Token operator, Expr right", "Grouping : Expr expression", "Literal : Object value", "Unary : Token operator, Expr right", "Variable : Token name")); defineAst(outputDir, "Stmt", Arrays.asList("Expression : Expr expression", "Print : Expr expression", "Var : Token name, Expr initializer")); -- cgit v1.2.3-54-g00ecf