Add branching primitives

This commit is contained in:
Tom Willemse 2021-01-14 23:53:47 -08:00
parent ca9fd3ae3a
commit c62b73a247
4 changed files with 94 additions and 4 deletions

View file

@ -27,6 +27,11 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
return expr.value.toString(); return expr.value.toString();
} }
@Override
public String visitLogicalExpr(Expr.Logical expr) {
return parenthesize(expr.operator.type.toString(), expr.left, expr.right);
}
@Override @Override
public String visitUnaryExpr(Expr.Unary expr) { public String visitUnaryExpr(Expr.Unary expr) {
return parenthesize(expr.operator.lexeme, expr.right); return parenthesize(expr.operator.lexeme, expr.right);
@ -57,6 +62,20 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
return expression.expression.accept(this); return expression.expression.accept(this);
} }
@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 @Override
public String visitBlockStmt(Stmt.Block block) { public String visitBlockStmt(Stmt.Block block) {
return parenthesize("", block.statements); return parenthesize("", block.statements);
@ -88,6 +107,10 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
return builder.toString(); return builder.toString();
} }
private String parenthesize(String name, Stmt... statements) {
return parenthesize(name, statements);
}
public static void main(String[] args) { public static void main(String[] args) {
Expr expression = new Expr.Binary( Expr expression = new Expr.Binary(
new Expr.Unary(new Token(TokenType.MINUS, "-", null, 1), new Expr.Literal(123)), new Expr.Unary(new Token(TokenType.MINUS, "-", null, 1), new Expr.Literal(123)),

View file

@ -10,6 +10,19 @@ 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 visitUnaryExpr(Expr.Unary expr) { public Object visitUnaryExpr(Expr.Unary expr) {
Object right = evaluate(expr.right); Object right = evaluate(expr.right);
@ -115,6 +128,17 @@ 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 if (stmt.elseBranch != null) {
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);

View file

@ -43,6 +43,8 @@ class Parser {
} }
private Stmt statement() { private Stmt statement() {
if (match(IF))
return ifStatement();
if (match(PRINT)) if (match(PRINT))
return printStatement(); return printStatement();
if (match(LEFT_BRACE)) if (match(LEFT_BRACE))
@ -51,6 +53,20 @@ class Parser {
return expressionStatement(); 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() { private Stmt printStatement() {
Expr value = expression(); Expr value = expression();
consume(SEMICOLON, "Expect ';' after value."); consume(SEMICOLON, "Expect ';' after value.");
@ -87,7 +103,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();
@ -104,6 +120,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 equality() { private Expr equality() {
Expr expr = comparison(); Expr expr = comparison();

View file

@ -16,10 +16,13 @@ public class GenerateAst {
defineAst(outputDir, "Expr", defineAst(outputDir, "Expr",
Arrays.asList("Assign : Token name, Expr value", "Binary : Expr left, Token operator, Expr right", 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")); "Variable : Token name"));
defineAst(outputDir, "Stmt", Arrays.asList("Block : List<Stmt> statements", "Expression : Expr expression", defineAst(outputDir, "Stmt",
"Print : Expr expression", "Var : Token name, Expr initializer")); 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 { private static void defineAst(String outputDir, String baseName, List<String> types) throws IOException {