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