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();
|
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)),
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue