Add for statement

This commit is contained in:
Tom Willemse 2021-01-17 19:48:17 -08:00
parent 2a72de9f81
commit 613c2388be
2 changed files with 57 additions and 0 deletions

View file

@ -52,6 +52,18 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
return parenthesize("define " + statement.name.lexeme + " = ", statement.initializer); return parenthesize("define " + statement.name.lexeme + " = ", statement.initializer);
} }
@Override
public String visitWhileStmt(Stmt.While statement) {
StringBuilder builder = new StringBuilder();
builder.append('(');
builder.append(parenthesize("while", statement.condition));
builder.append(parenthesize("do", statement.body));
builder.append(')');
return builder.toString();
}
@Override @Override
public String visitPrintStmt(Stmt.Print statement) { public String visitPrintStmt(Stmt.Print statement) {
return parenthesize("print", statement.expression); return parenthesize("print", statement.expression);

View file

@ -4,6 +4,7 @@ import static com.craftinginterpreters.lox.TokenType.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Arrays;
class Parser { class Parser {
private static class ParseError extends RuntimeException { private static class ParseError extends RuntimeException {
@ -43,6 +44,8 @@ class Parser {
} }
private Stmt statement() { private Stmt statement() {
if (match(FOR))
return forStatement();
if (match(IF)) if (match(IF))
return ifStatement(); return ifStatement();
if (match(PRINT)) if (match(PRINT))
@ -55,6 +58,48 @@ class Parser {
return expressionStatement(); return expressionStatement();
} }
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) {
body = new Stmt.Block(
Arrays.asList(
body,
new Stmt.Expression(increment)));
}
if (condition == null) condition = new Expr.Literal(true);
body = new Stmt.While(condition, body);
if (initializer != null) {
body = new Stmt.Block(Arrays.asList(initializer, body));
}
return body;
}
private Stmt ifStatement() { private Stmt ifStatement() {
consume(LEFT_PAREN, "Expect '(' after 'if'."); consume(LEFT_PAREN, "Expect '(' after 'if'.");
Expr condition = expression(); Expr condition = expression();