global variables
This commit is contained in:
		@@ -28,6 +28,11 @@ class ASTPrinter implements Expr.Visitor<String> {
 | 
			
		||||
    return parenthesize(expr.operator.lexeme, expr.right);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public String visitVariableExpr(Expr.Variable expr) {
 | 
			
		||||
    return expr.name.toString();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private String parenthesize(String name, Expr... exprs) {
 | 
			
		||||
    StringBuilder builder = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								src/lox/Environment.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/lox/Environment.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
package lox;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
class Environment {
 | 
			
		||||
  private final Map<String, Object> values = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
  void define(String name, Object value) {
 | 
			
		||||
    values.put(name, value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Object get(Token name) {
 | 
			
		||||
    if (values.containsKey(name.lexeme)) {
 | 
			
		||||
      return values.get(name.lexeme);
 | 
			
		||||
    }
 | 
			
		||||
    throw new RuntimeError(name, "Undefined variable '" + name.lexeme + "'.");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,13 +1,12 @@
 | 
			
		||||
package lox;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
abstract class Expr {
 | 
			
		||||
  interface Visitor<R> {
 | 
			
		||||
    R visitBinaryExpr(Binary expr);
 | 
			
		||||
    R visitGroupingExpr(Grouping expr);
 | 
			
		||||
    R visitLiteralExpr(Literal expr);
 | 
			
		||||
    R visitUnaryExpr(Unary expr);
 | 
			
		||||
    R visitVariableExpr(Variable expr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static class Binary extends Expr {
 | 
			
		||||
@@ -68,5 +67,18 @@ abstract class Expr {
 | 
			
		||||
    final Expr right;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,8 @@ package lox;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
 | 
			
		||||
  private Environment environment = new Environment();
 | 
			
		||||
 | 
			
		||||
  void interpret(List<Stmt> statements) {
 | 
			
		||||
    try {
 | 
			
		||||
      for (Stmt statement : statements) {
 | 
			
		||||
@@ -82,6 +84,11 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Object visitVariableExpr(Expr.Variable expr) {
 | 
			
		||||
    return environment.get(expr.name);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Void visitExpressionStmt(Stmt.Expression stmt) {
 | 
			
		||||
    evaluate(stmt.expression);
 | 
			
		||||
@@ -95,6 +102,16 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Void visitVarStmt(Stmt.Var stmt) {
 | 
			
		||||
    Object value = null;
 | 
			
		||||
    if (stmt.initializer != null) {
 | 
			
		||||
      value = evaluate(stmt.initializer);
 | 
			
		||||
    }
 | 
			
		||||
    environment.define(stmt.name.lexeme, value);
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void checkNumberOperand(Token operator, Object operand) {
 | 
			
		||||
    if (operand instanceof Double) {
 | 
			
		||||
      return;
 | 
			
		||||
 
 | 
			
		||||
@@ -18,11 +18,34 @@ class Parser {
 | 
			
		||||
  List<Stmt> parse() {
 | 
			
		||||
    List<Stmt> statements = new ArrayList<>();
 | 
			
		||||
    while (!isAtEnd()) {
 | 
			
		||||
      statements.add(statement());
 | 
			
		||||
      statements.add(declaration());
 | 
			
		||||
    }
 | 
			
		||||
    return statements;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private Stmt declaration() {
 | 
			
		||||
    try {
 | 
			
		||||
      if (match(VAR)) {
 | 
			
		||||
        return varDeclaration();
 | 
			
		||||
      }
 | 
			
		||||
      return statement();
 | 
			
		||||
    } catch (ParseError error) {
 | 
			
		||||
      synchronize();
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private Stmt varDeclaration() {
 | 
			
		||||
    Token name = consume(IDENTIFIER, "Expect variable name.");
 | 
			
		||||
 | 
			
		||||
    Expr initializer = null;
 | 
			
		||||
    if (match(EQUAL)) {
 | 
			
		||||
      initializer = expression();
 | 
			
		||||
    }
 | 
			
		||||
    consume(SEMICOLON, "Expect semicolon.");
 | 
			
		||||
    return new Stmt.Var(name, initializer);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private Stmt statement() {
 | 
			
		||||
    if (match(PRINT)) {
 | 
			
		||||
      return printStatement();
 | 
			
		||||
@@ -113,6 +136,9 @@ class Parser {
 | 
			
		||||
      consume(RIGHT_PAREN, "Expect ')' after expression.");
 | 
			
		||||
      return new Expr.Grouping(expr);
 | 
			
		||||
    }
 | 
			
		||||
    if (match(IDENTIFIER)) {
 | 
			
		||||
      return new Expr.Variable(previous());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    throw error(peek(), "Expected expression.");
 | 
			
		||||
  }
 | 
			
		||||
@@ -172,14 +198,7 @@ class Parser {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      switch (peek().type) {
 | 
			
		||||
        case CLASS:
 | 
			
		||||
        case FOR:
 | 
			
		||||
        case FUN:
 | 
			
		||||
        case IF:
 | 
			
		||||
        case PRINT:
 | 
			
		||||
        case RETURN:
 | 
			
		||||
        case VAR:
 | 
			
		||||
        case WHILE:
 | 
			
		||||
        case CLASS, FOR, FUN, IF, PRINT, RETURN, VAR, WHILE:
 | 
			
		||||
          return;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -106,9 +106,7 @@ class Scanner {
 | 
			
		||||
          addToken(SLASH);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case ' ':
 | 
			
		||||
      case '\r':
 | 
			
		||||
      case '\t':
 | 
			
		||||
      case ' ', '\r', '\t':
 | 
			
		||||
        break; // skip whitespace
 | 
			
		||||
      case '\n':
 | 
			
		||||
        line++;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ package lox;
 | 
			
		||||
abstract class Stmt {
 | 
			
		||||
  interface Visitor<R> {
 | 
			
		||||
    R visitExpressionStmt(Expression stmt);
 | 
			
		||||
 | 
			
		||||
    R visitVarStmt(Var stmt);
 | 
			
		||||
    R visitPrintStmt(Print stmt);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -20,6 +20,21 @@ abstract class Stmt {
 | 
			
		||||
    final Expr expression;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static class Var extends Stmt {
 | 
			
		||||
    Var(Token name, Expr initializer) {
 | 
			
		||||
      this.name = name;
 | 
			
		||||
      this.initializer = initializer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    <R> R accept(Visitor<R> visitor) {
 | 
			
		||||
      return visitor.visitVarStmt(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    final Token name;
 | 
			
		||||
    final Expr initializer;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static class Print extends Stmt {
 | 
			
		||||
    Print(Expr expression) {
 | 
			
		||||
      this.expression = expression;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,12 +20,16 @@ public class GenerateAST {
 | 
			
		||||
            "Binary : Expr left, Token operator, Expr right",
 | 
			
		||||
            "Grouping : Expr expression",
 | 
			
		||||
            "Literal : Object value",
 | 
			
		||||
            "Unary : Token operator, Expr right"));
 | 
			
		||||
            "Unary : Token operator, Expr right",
 | 
			
		||||
            "Variable : Token name"));
 | 
			
		||||
 | 
			
		||||
    defineAST(
 | 
			
		||||
        outputDir,
 | 
			
		||||
        "Stmt",
 | 
			
		||||
        Arrays.asList("Expression : Expr expression", "Print : Expr expression"));
 | 
			
		||||
        Arrays.asList(
 | 
			
		||||
            "Expression : Expr expression",
 | 
			
		||||
            "Var : Token name, Expr initializer",
 | 
			
		||||
            "Print : Expr expression"));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static void defineAST(String outputDir, String baseName, List<String> types)
 | 
			
		||||
@@ -35,8 +39,8 @@ public class GenerateAST {
 | 
			
		||||
 | 
			
		||||
    writer.println("package lox;");
 | 
			
		||||
    writer.println();
 | 
			
		||||
    writer.println("import java.util.List;");
 | 
			
		||||
    writer.println();
 | 
			
		||||
    //    writer.println("import java.util.List;");
 | 
			
		||||
    //    writer.println();
 | 
			
		||||
    writer.println("abstract class " + baseName + " {");
 | 
			
		||||
 | 
			
		||||
    defineVisitor(writer, baseName, types);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user