ソースを参照

Parsing variables -- Assignment statement

runningwater 2 年 前
コミット
9a4fe6d1f2

+ 7 - 1
src/main/java/com/craftinginterpreters/lox/AstPrinter.java

@@ -32,7 +32,13 @@ public class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
 
   @Override
   public String visitVarStmt(Stmt.Var stmt) {
-    return parenthesize("var", stmt.initializer == null ? new Expr.Literal(null): stmt.initializer);
+    return parenthesize(
+        "var", stmt.initializer == null ? new Expr.Literal(null) : stmt.initializer);
+  }
+
+  @Override
+  public String visitAssignExpr(Expr.Assign expr) {
+    return parenthesize("assign", expr.value);
   }
 
   @Override

+ 9 - 0
src/main/java/com/craftinginterpreters/lox/Environment.java

@@ -24,4 +24,13 @@ public 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 + "'.");
+  }
 }

+ 78 - 59
src/main/java/com/craftinginterpreters/lox/Expr.java

@@ -2,91 +2,110 @@ package com.craftinginterpreters.lox;
 
 /**
  * @author GenerateAst
- * @date 2023-06-09 16:00
+ * @date 2023-06-12 16:03
  */
 abstract class Expr {
-  interface Visitor<R> {
-    R visitBinaryExpr(Binary expr);
+    interface Visitor<R> {
+        R visitAssignExpr(Assign expr);
 
-    R visitGroupingExpr(Grouping expr);
+        R visitBinaryExpr(Binary expr);
 
-    R visitLiteralExpr(Literal expr);
+        R visitGroupingExpr(Grouping expr);
 
-    R visitUnaryExpr(Unary expr);
+        R visitLiteralExpr(Literal expr);
 
-    R visitVariableExpr(Variable expr);
-  }
+        R visitUnaryExpr(Unary expr);
 
-  static class Binary extends Expr {
-    Binary(Expr left, Token operator, Expr right) {
-      this.left = left;
-      this.operator = operator;
-      this.right = right;
-    }
+        R visitVariableExpr(Variable expr);
 
-    @Override
-    <R> R accept(Visitor<R> visitor) {
-      return visitor.visitBinaryExpr(this);
     }
 
-    final Expr left;
-    final Token operator;
-    final Expr right;
-  }
 
-  static class Grouping extends Expr {
-    Grouping(Expr expression) {
-      this.expression = expression;
+    static class Assign extends Expr {
+        Assign(Token name, Expr value) {
+            this.name = name;
+            this.value = value;
+        }
+
+        @Override
+        <R> R accept(Visitor<R> visitor) {
+            return visitor.visitAssignExpr(this);
+        }
+
+        final Token name;
+        final  Expr value;
     }
 
-    @Override
-    <R> R accept(Visitor<R> visitor) {
-      return visitor.visitGroupingExpr(this);
+    static class Binary extends Expr {
+        Binary(Expr left, Token operator, Expr right) {
+            this.left = left;
+            this.operator = operator;
+            this.right = right;
+        }
+
+        @Override
+        <R> R accept(Visitor<R> visitor) {
+            return visitor.visitBinaryExpr(this);
+        }
+
+        final Expr left;
+        final  Token operator;
+        final  Expr right;
     }
 
-    final Expr expression;
-  }
+    static class Grouping extends Expr {
+        Grouping(Expr expression) {
+            this.expression = expression;
+        }
 
-  static class Literal extends Expr {
-    Literal(Object value) {
-      this.value = value;
-    }
+        @Override
+        <R> R accept(Visitor<R> visitor) {
+            return visitor.visitGroupingExpr(this);
+        }
 
-    @Override
-    <R> R accept(Visitor<R> visitor) {
-      return visitor.visitLiteralExpr(this);
+        final Expr expression;
     }
 
-    final Object value;
-  }
+    static class Literal extends Expr {
+        Literal(Object value) {
+            this.value = value;
+        }
 
-  static class Unary extends Expr {
-    Unary(Token operator, Expr right) {
-      this.operator = operator;
-      this.right = right;
-    }
+        @Override
+        <R> R accept(Visitor<R> visitor) {
+            return visitor.visitLiteralExpr(this);
+        }
 
-    @Override
-    <R> R accept(Visitor<R> visitor) {
-      return visitor.visitUnaryExpr(this);
+        final Object value;
     }
 
-    final Token operator;
-    final Expr right;
-  }
+    static class Unary extends Expr {
+        Unary(Token operator, Expr right) {
+            this.operator = operator;
+            this.right = right;
+        }
 
-  static class Variable extends Expr {
-    Variable(Token name) {
-      this.name = name;
-    }
+        @Override
+        <R> R accept(Visitor<R> visitor) {
+            return visitor.visitUnaryExpr(this);
+        }
 
-    @Override
-    <R> R accept(Visitor<R> visitor) {
-      return visitor.visitVariableExpr(this);
+        final Token operator;
+        final  Expr right;
     }
 
-    final Token name;
-  }
+    static class Variable extends Expr {
+        Variable(Token name) {
+            this.name = name;
+        }
+
+        @Override
+        <R> R accept(Visitor<R> visitor) {
+            return visitor.visitVariableExpr(this);
+        }
+
+        final Token name;
+    }
 
-  abstract <R> R accept(Visitor<R> visitor);
+    abstract <R> R accept(Visitor<R> visitor);
 }

+ 7 - 0
src/main/java/com/craftinginterpreters/lox/Interpreter.java

@@ -31,6 +31,13 @@ public class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
   }
 
   @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);
     Object right = evaluate(expr.right);

+ 21 - 3
src/main/java/com/craftinginterpreters/lox/Parser.java

@@ -15,7 +15,8 @@ import java.util.List;
  *     <p>|------------|-----------|------------| | Equality | == != | Left | | Comparison | > >= <
  *     <= | Left | | Term | - + | Left | | Factor | / * | Left | | Unary | ! - | Right |
  *     <p>
- *     <p>expression → equality ;
+ *     <p>expression → assignment;
+ *     <p>assignment → IDENTIFIER "=" assignment | equality
  *     <p>equality → comparison ( ( "!=" | "==" ) comparison )* ;
  *     <p>comparison → term ( ( ">" | ">=" | "<" | "<=" ) term )* ;
  *     <p>term → factor ( ( "-" | "+" ) factor )* ;
@@ -85,9 +86,26 @@ public class Parser {
     return new Stmt.Var(name, initializer);
   }
 
-  // expression  → equality ;
+  // expression  → assignment ;
   private Expr expression() {
-    return equality();
+    return assignment();
+  }
+
+  // assignment → IDENTIFIER "=" assignment | equality
+  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;
   }
 
   // equality  → comparison ( ( "!=" | "==" ) comparison )* ;

+ 1 - 0
src/main/java/com/craftinginterpreters/tool/GenerateAst.java

@@ -43,6 +43,7 @@ public class GenerateAst {
         }
         String outputDir = args[0];
         defineAst(outputDir, "Expr", Arrays.asList(
+                "Assign   : Token name, Expr value",
                 "Binary   : Expr left, Token operator, Expr right",
                 "Grouping : Expr expression",
                 "Literal  : Object value",