IF FOR WHILE
This commit is contained in:
		@@ -33,6 +33,11 @@ class ASTPrinter implements Expr.Visitor<String> {
 | 
				
			|||||||
    return expr.name.toString();
 | 
					    return expr.name.toString();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public String visitLogicalExpr(Expr.Logical expr) {
 | 
				
			||||||
 | 
					    return expr.left.accept(this) + expr.operator.toString() + expr.right.accept(this);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Override
 | 
					  @Override
 | 
				
			||||||
  public String visitAssignExpr(Expr.Assign expr) {
 | 
					  public String visitAssignExpr(Expr.Assign expr) {
 | 
				
			||||||
    return expr.name.toString();
 | 
					    return expr.name.toString();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ abstract class Expr {
 | 
				
			|||||||
    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 visitLogicalExpr(Logical expr);
 | 
				
			||||||
    R visitUnaryExpr(Unary expr);
 | 
					    R visitUnaryExpr(Unary expr);
 | 
				
			||||||
    R visitVariableExpr(Variable expr);
 | 
					    R visitVariableExpr(Variable expr);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -70,6 +71,23 @@ abstract class Expr {
 | 
				
			|||||||
    final Object value;
 | 
					    final Object value;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static class Logical extends Expr {
 | 
				
			||||||
 | 
					    Logical(Expr left, Token operator, Expr right) {
 | 
				
			||||||
 | 
					      this.left = left;
 | 
				
			||||||
 | 
					      this.operator = operator;
 | 
				
			||||||
 | 
					      this.right = right;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    <R> R accept(Visitor<R> visitor) {
 | 
				
			||||||
 | 
					      return visitor.visitLogicalExpr(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final Expr left;
 | 
				
			||||||
 | 
					    final Token operator;
 | 
				
			||||||
 | 
					    final Expr right;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static class Unary extends Expr {
 | 
					  static class Unary extends Expr {
 | 
				
			||||||
    Unary(Token operator, Expr right) {
 | 
					    Unary(Token operator, Expr right) {
 | 
				
			||||||
      this.operator = operator;
 | 
					      this.operator = operator;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,23 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
 | 
				
			|||||||
    return expr.value;
 | 
					    return expr.value;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public Object visitLogicalExpr(Expr.Logical expr) {
 | 
				
			||||||
 | 
					    Object left = evaluate(expr.left);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (expr.operator.type == TokenType.OR) {
 | 
				
			||||||
 | 
					      if (isTruthy(left)) {
 | 
				
			||||||
 | 
					        return left;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        if (!isTruthy(left)) {
 | 
				
			||||||
 | 
					          return left;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return evaluate(expr.right);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Override
 | 
					  @Override
 | 
				
			||||||
  public Object visitGroupingExpr(Expr.Grouping expr) {
 | 
					  public Object visitGroupingExpr(Expr.Grouping expr) {
 | 
				
			||||||
    return evaluate(expr.expression);
 | 
					    return evaluate(expr.expression);
 | 
				
			||||||
@@ -102,6 +119,16 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
 | 
				
			|||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public Void visitIfStmt(Stmt.If stmt) {
 | 
				
			||||||
 | 
					    if (isTruthy(evaluate(stmt.condition))) {
 | 
				
			||||||
 | 
					      execute(stmt.thenBranch);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      execute(stmt.elseBranch);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Override
 | 
					  @Override
 | 
				
			||||||
  public Void visitPrintStmt(Stmt.Print stmt) {
 | 
					  public Void visitPrintStmt(Stmt.Print stmt) {
 | 
				
			||||||
    Object value = evaluate(stmt.expression);
 | 
					    Object value = evaluate(stmt.expression);
 | 
				
			||||||
@@ -119,6 +146,14 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
 | 
				
			|||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public Void visitWhileStmt(Stmt.While stmt) {
 | 
				
			||||||
 | 
					    while (isTruthy(stmt.condition)) {
 | 
				
			||||||
 | 
					      execute(stmt.body);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Override
 | 
					  @Override
 | 
				
			||||||
  public Void visitBlockStmt(Stmt.Block stmt) {
 | 
					  public Void visitBlockStmt(Stmt.Block stmt) {
 | 
				
			||||||
    executeBlock(stmt.statements, new Environment(environment));
 | 
					    executeBlock(stmt.statements, new Environment(environment));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package lox;
 | 
					package lox;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.Arrays;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static lox.TokenType.*;
 | 
					import static lox.TokenType.*;
 | 
				
			||||||
@@ -47,9 +48,18 @@ class Parser {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private Stmt statement() {
 | 
					  private Stmt statement() {
 | 
				
			||||||
 | 
					    if (match(FOR)) {
 | 
				
			||||||
 | 
					      return forStatement();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (match(IF)) {
 | 
				
			||||||
 | 
					      return ifStatement();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (match(PRINT)) {
 | 
					    if (match(PRINT)) {
 | 
				
			||||||
      return printStatement();
 | 
					      return printStatement();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (match(WHILE)) {
 | 
				
			||||||
 | 
					      return whileStatement();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (match(LEFT_BRACE)) {
 | 
					    if (match(LEFT_BRACE)) {
 | 
				
			||||||
      return new Stmt.Block(block());
 | 
					      return new Stmt.Block(block());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -62,12 +72,78 @@ class Parser {
 | 
				
			|||||||
    return new Stmt.Print(value);
 | 
					    return new Stmt.Print(value);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private Stmt whileStatement() {
 | 
				
			||||||
 | 
					    consume(LEFT_PAREN, "Expect '(' after 'while");
 | 
				
			||||||
 | 
					    Expr condition = expression();
 | 
				
			||||||
 | 
					    consume(RIGHT_PAREN, "Expect ')' after while condition");
 | 
				
			||||||
 | 
					    Stmt body = statement();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return new Stmt.While(condition, body);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private Stmt expressionStatement() {
 | 
					  private Stmt expressionStatement() {
 | 
				
			||||||
    Expr value = expression();
 | 
					    Expr value = expression();
 | 
				
			||||||
    consume(SEMICOLON, "Expect ';' after value.");
 | 
					    consume(SEMICOLON, "Expect ';' after value.");
 | 
				
			||||||
    return new Stmt.Expression(value);
 | 
					    return new Stmt.Expression(value);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private Stmt ifStatement() {
 | 
				
			||||||
 | 
					    consume(LEFT_PAREN, "Expect '(' after 'if'.");
 | 
				
			||||||
 | 
					    Expr condition = expression();
 | 
				
			||||||
 | 
					    consume(RIGHT_PAREN, "Expect ')' after if condition");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Stmt thenBranch = statement();
 | 
				
			||||||
 | 
					    Stmt elseBranch = null;
 | 
				
			||||||
 | 
					    if (match(ELSE)) {
 | 
				
			||||||
 | 
					      elseBranch = statement();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return new Stmt.If(condition, thenBranch, elseBranch);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private Stmt forStatement() {
 | 
				
			||||||
 | 
					    consume(LEFT_PAREN, "Expect '(' after 'for'.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Stmt initializer;
 | 
				
			||||||
 | 
					    if (match(SEMICOLON)) {
 | 
				
			||||||
 | 
					      initializer = null;
 | 
				
			||||||
 | 
					    } else if (match(VAR)) {
 | 
				
			||||||
 | 
					      initializer = varDeclaration();
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      initializer = expressionStatement();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Expr condition = null;
 | 
				
			||||||
 | 
					    if (!check(SEMICOLON)) {
 | 
				
			||||||
 | 
					      condition = expression();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    consume(SEMICOLON, "Expect ';' after loop condition.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Expr increment = null;
 | 
				
			||||||
 | 
					    if (!check(RIGHT_PAREN)) {
 | 
				
			||||||
 | 
					      increment = expression();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    consume(RIGHT_PAREN, "Expect ')' after for clauses");
 | 
				
			||||||
 | 
					    Stmt body = statement();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (increment != null) {
 | 
				
			||||||
 | 
					      // move incrementer into the body
 | 
				
			||||||
 | 
					      body = new Stmt.Block(Arrays.asList(body, new Stmt.Expression(increment)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (condition == null) {
 | 
				
			||||||
 | 
					      // set an infinite loop up if no condition given
 | 
				
			||||||
 | 
					      condition = new Expr.Literal(true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    body = new Stmt.While(condition, body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (initializer != null) {
 | 
				
			||||||
 | 
					      // insert the initializer before the while statement
 | 
				
			||||||
 | 
					      body = new Stmt.Block(Arrays.asList(initializer, body));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return body;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private List<Stmt> block() {
 | 
					  private List<Stmt> block() {
 | 
				
			||||||
    List<Stmt> statements = new ArrayList<>();
 | 
					    List<Stmt> statements = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -79,7 +155,7 @@ class Parser {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private Expr assignment() {
 | 
					  private Expr assignment() {
 | 
				
			||||||
    Expr expr = equality();
 | 
					    Expr expr = or();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (match(EQUAL)) {
 | 
					    if (match(EQUAL)) {
 | 
				
			||||||
      Token equals = previous();
 | 
					      Token equals = previous();
 | 
				
			||||||
@@ -95,6 +171,30 @@ class Parser {
 | 
				
			|||||||
    return expr;
 | 
					    return expr;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private Expr or() {
 | 
				
			||||||
 | 
					    Expr expr  = and();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (match(OR)) {
 | 
				
			||||||
 | 
					      Token operator = previous();
 | 
				
			||||||
 | 
					      Expr right = and();
 | 
				
			||||||
 | 
					      expr = new Expr.Logical(expr, operator, right);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return expr;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private Expr and() {
 | 
				
			||||||
 | 
					    Expr expr = equality();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (match(AND)) {
 | 
				
			||||||
 | 
					      Token operator = previous();
 | 
				
			||||||
 | 
					      Expr right = equality();
 | 
				
			||||||
 | 
					      expr = new Expr.Logical(expr, operator, right);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return expr;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private Expr expression() {
 | 
					  private Expr expression() {
 | 
				
			||||||
    return assignment();
 | 
					    return assignment();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,10 @@ abstract class Stmt {
 | 
				
			|||||||
  interface Visitor<R> {
 | 
					  interface Visitor<R> {
 | 
				
			||||||
    R visitBlockStmt(Block stmt);
 | 
					    R visitBlockStmt(Block stmt);
 | 
				
			||||||
    R visitExpressionStmt(Expression stmt);
 | 
					    R visitExpressionStmt(Expression stmt);
 | 
				
			||||||
 | 
					    R visitIfStmt(If stmt);
 | 
				
			||||||
    R visitVarStmt(Var stmt);
 | 
					    R visitVarStmt(Var stmt);
 | 
				
			||||||
    R visitPrintStmt(Print stmt);
 | 
					    R visitPrintStmt(Print stmt);
 | 
				
			||||||
 | 
					    R visitWhileStmt(While stmt);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static class Block extends Stmt {
 | 
					  static class Block extends Stmt {
 | 
				
			||||||
@@ -36,6 +38,23 @@ abstract class Stmt {
 | 
				
			|||||||
    final Expr expression;
 | 
					    final Expr expression;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static class If extends Stmt {
 | 
				
			||||||
 | 
					    If(Expr condition, Stmt thenBranch, Stmt elseBranch) {
 | 
				
			||||||
 | 
					      this.condition = condition;
 | 
				
			||||||
 | 
					      this.thenBranch = thenBranch;
 | 
				
			||||||
 | 
					      this.elseBranch = elseBranch;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    <R> R accept(Visitor<R> visitor) {
 | 
				
			||||||
 | 
					      return visitor.visitIfStmt(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final Expr condition;
 | 
				
			||||||
 | 
					    final Stmt thenBranch;
 | 
				
			||||||
 | 
					    final Stmt elseBranch;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static class Var extends Stmt {
 | 
					  static class Var extends Stmt {
 | 
				
			||||||
    Var(Token name, Expr initializer) {
 | 
					    Var(Token name, Expr initializer) {
 | 
				
			||||||
      this.name = name;
 | 
					      this.name = name;
 | 
				
			||||||
@@ -64,5 +83,20 @@ abstract class Stmt {
 | 
				
			|||||||
    final Expr expression;
 | 
					    final Expr expression;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static class While extends Stmt {
 | 
				
			||||||
 | 
					    While(Expr condition, Stmt body) {
 | 
				
			||||||
 | 
					      this.condition = condition;
 | 
				
			||||||
 | 
					      this.body = body;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    <R> R accept(Visitor<R> visitor) {
 | 
				
			||||||
 | 
					      return visitor.visitWhileStmt(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final Expr condition;
 | 
				
			||||||
 | 
					    final Stmt body;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  abstract <R> R accept(Visitor<R> visitor);
 | 
					  abstract <R> R accept(Visitor<R> visitor);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ 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",
 | 
				
			||||||
 | 
					            "Logical  : Expr left, Token operator, Expr right",
 | 
				
			||||||
            "Unary    : Token operator, Expr right",
 | 
					            "Unary    : Token operator, Expr right",
 | 
				
			||||||
            "Variable : Token name"));
 | 
					            "Variable : Token name"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -31,8 +32,10 @@ public class GenerateAST {
 | 
				
			|||||||
        Arrays.asList(
 | 
					        Arrays.asList(
 | 
				
			||||||
            "Block      : List<Stmt> statements",
 | 
					            "Block      : List<Stmt> statements",
 | 
				
			||||||
            "Expression : Expr expression",
 | 
					            "Expression : Expr expression",
 | 
				
			||||||
 | 
					            "If         : Expr condition, Stmt thenBranch, Stmt elseBranch",
 | 
				
			||||||
            "Var        : Token name, Expr initializer",
 | 
					            "Var        : Token name, Expr initializer",
 | 
				
			||||||
            "Print      : Expr expression"));
 | 
					            "Print      : Expr expression",
 | 
				
			||||||
 | 
					            "While      : Expr condition, Stmt body"));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private static void defineAST(String outputDir, String baseName, List<String> types)
 | 
					  private static void defineAST(String outputDir, String baseName, List<String> types)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user