summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Tom Willemse2021-01-14 23:53:47 -0800
committerGravatar Tom Willemse2021-01-14 23:53:47 -0800
commitc62b73a2477b9fa625285e9c2ca1e51c2bcb8024 (patch)
treed8ea9b22fcdc28d34a1aec9f40a87ddd2dfd9660
parentca9fd3ae3a1ef5ca1fbe33a83abb12e656a2556f (diff)
downloadcrafting-interpreters-c62b73a2477b9fa625285e9c2ca1e51c2bcb8024.tar.gz
crafting-interpreters-c62b73a2477b9fa625285e9c2ca1e51c2bcb8024.zip
Add branching primitives
-rw-r--r--src/com/craftinginterpreters/lox/AstPrinter.java23
-rw-r--r--src/com/craftinginterpreters/lox/Interpreter.java24
-rw-r--r--src/com/craftinginterpreters/lox/Parser.java42
-rw-r--r--src/com/craftinginterpreters/tool/GenerateAst.java9
4 files changed, 94 insertions, 4 deletions
diff --git a/src/com/craftinginterpreters/lox/AstPrinter.java b/src/com/craftinginterpreters/lox/AstPrinter.java
index d5163df..8f7be78 100644
--- a/src/com/craftinginterpreters/lox/AstPrinter.java
+++ b/src/com/craftinginterpreters/lox/AstPrinter.java
@@ -28,6 +28,11 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
}
@Override
+ public String visitLogicalExpr(Expr.Logical expr) {
+ return parenthesize(expr.operator.type.toString(), expr.left, expr.right);
+ }
+
+ @Override
public String visitUnaryExpr(Expr.Unary expr) {
return parenthesize(expr.operator.lexeme, expr.right);
}
@@ -58,6 +63,20 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
}
@Override
+ public String visitIfStmt(Stmt.If stmt) {
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("(");
+ builder.append(parenthesize("if", stmt.condition));
+ builder.append(parenthesize("then", stmt.thenBranch));
+
+ if (stmt.elseBranch != null) {
+ builder.append(parenthesize("else", stmt.elseBranch));
+ }
+ return builder.toString();
+ }
+
+ @Override
public String visitBlockStmt(Stmt.Block block) {
return parenthesize("", block.statements);
}
@@ -88,6 +107,10 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
return builder.toString();
}
+ private String parenthesize(String name, Stmt... statements) {
+ return parenthesize(name, statements);
+ }
+
public static void main(String[] args) {
Expr expression = new Expr.Binary(
new Expr.Unary(new Token(TokenType.MINUS, "-", null, 1), new Expr.Literal(123)),
diff --git a/src/com/craftinginterpreters/lox/Interpreter.java b/src/com/craftinginterpreters/lox/Interpreter.java
index e03ca37..6c32233 100644
--- a/src/com/craftinginterpreters/lox/Interpreter.java
+++ b/src/com/craftinginterpreters/lox/Interpreter.java
@@ -11,6 +11,19 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
}
@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
public Object visitUnaryExpr(Expr.Unary expr) {
Object right = evaluate(expr.right);
@@ -116,6 +129,17 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
}
@Override
+ public Void visitIfStmt(Stmt.If stmt) {
+ if (isTruthy(evaluate(stmt.condition))) {
+ execute(stmt.thenBranch);
+ } else if (stmt.elseBranch != null) {
+ execute(stmt.elseBranch);
+ }
+
+ return null;
+ }
+
+ @Override
public Void visitPrintStmt(Stmt.Print stmt) {
Object value = evaluate(stmt.expression);
System.out.println(stringify(value));
diff --git a/src/com/craftinginterpreters/lox/Parser.java b/src/com/craftinginterpreters/lox/Parser.java
index f044feb..1643129 100644
--- a/src/com/craftinginterpreters/lox/Parser.java
+++ b/src/com/craftinginterpreters/lox/Parser.java
@@ -43,6 +43,8 @@ class Parser {
}
private Stmt statement() {
+ if (match(IF))
+ return ifStatement();
if (match(PRINT))
return printStatement();
if (match(LEFT_BRACE))
@@ -51,6 +53,20 @@ class Parser {
return expressionStatement();
}
+ 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 printStatement() {
Expr value = expression();
consume(SEMICOLON, "Expect ';' after value.");
@@ -87,7 +103,7 @@ class Parser {
}
private Expr assignment() {
- Expr expr = equality();
+ Expr expr = or();
if (match(EQUAL)) {
Token equals = previous();
@@ -104,6 +120,30 @@ class Parser {
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 equality() {
Expr expr = comparison();
diff --git a/src/com/craftinginterpreters/tool/GenerateAst.java b/src/com/craftinginterpreters/tool/GenerateAst.java
index c9f1398..a3935e1 100644
--- a/src/com/craftinginterpreters/tool/GenerateAst.java
+++ b/src/com/craftinginterpreters/tool/GenerateAst.java
@@ -16,10 +16,13 @@ public class GenerateAst {
defineAst(outputDir, "Expr",
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",
+ "Grouping : Expr expression", "Literal : Object value",
+ "Logical : Expr left, Token operator, Expr right", "Unary : Token operator, Expr right",
"Variable : Token name"));
- defineAst(outputDir, "Stmt", Arrays.asList("Block : List<Stmt> statements", "Expression : Expr expression",
- "Print : Expr expression", "Var : Token name, Expr initializer"));
+ defineAst(outputDir, "Stmt",
+ Arrays.asList("Block : List<Stmt> statements", "Expression : Expr expression",
+ "If : Expr condition, Stmt thenBranch, Stmt elseBranch", "Print : Expr expression",
+ "Var : Token name, Expr initializer"));
}
private static void defineAst(String outputDir, String baseName, List<String> types) throws IOException {