Add branching primitives
This commit is contained in:
parent
ca9fd3ae3a
commit
c62b73a247
4 changed files with 94 additions and 4 deletions
|
@ -27,6 +27,11 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
|
|||
return expr.value.toString();
|
||||
}
|
||||
|
||||
@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);
|
||||
|
@ -57,6 +62,20 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
|
|||
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
|
||||
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)),
|
||||
|
|
|
@ -10,6 +10,19 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
|
|||
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
|
||||
public Object visitUnaryExpr(Expr.Unary expr) {
|
||||
Object right = evaluate(expr.right);
|
||||
|
@ -115,6 +128,17 @@ class Interpreter implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
|
|||
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
|
||||
public Void visitPrintStmt(Stmt.Print stmt) {
|
||||
Object value = evaluate(stmt.expression);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue