aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/craftinginterpreters/lox/AstPrinter.java12
-rw-r--r--src/com/craftinginterpreters/lox/Parser.java45
2 files changed, 57 insertions, 0 deletions
diff --git a/src/com/craftinginterpreters/lox/AstPrinter.java b/src/com/craftinginterpreters/lox/AstPrinter.java
index 8f7be78..65f1916 100644
--- a/src/com/craftinginterpreters/lox/AstPrinter.java
+++ b/src/com/craftinginterpreters/lox/AstPrinter.java
@@ -53,6 +53,18 @@ class AstPrinter implements Expr.Visitor<String>, Stmt.Visitor<String> {
}
@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
public String visitPrintStmt(Stmt.Print statement) {
return parenthesize("print", statement.expression);
}
diff --git a/src/com/craftinginterpreters/lox/Parser.java b/src/com/craftinginterpreters/lox/Parser.java
index a85d70f..7d7b27a 100644
--- a/src/com/craftinginterpreters/lox/Parser.java
+++ b/src/com/craftinginterpreters/lox/Parser.java
@@ -4,6 +4,7 @@ import static com.craftinginterpreters.lox.TokenType.*;
import java.util.ArrayList;
import java.util.List;
+import java.util.Arrays;
class Parser {
private static class ParseError extends RuntimeException {
@@ -43,6 +44,8 @@ class Parser {
}
private Stmt statement() {
+ if (match(FOR))
+ return forStatement();
if (match(IF))
return ifStatement();
if (match(PRINT))
@@ -55,6 +58,48 @@ class Parser {
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() {
consume(LEFT_PAREN, "Expect '(' after 'if'.");
Expr condition = expression();