From a516090b4ff8e4437cb50abd0a5653322a6dab45 Mon Sep 17 00:00:00 2001 From: ctsk <9384305+ctsk@users.noreply.github.com> Date: Sat, 10 Sep 2022 11:46:18 +0200 Subject: [PATCH] [jlox] Add for loops (using syntactic sugar!) --- .../src/main/java/xyz/ctsk/lox/Parser.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/jlox/lox/src/main/java/xyz/ctsk/lox/Parser.java b/jlox/lox/src/main/java/xyz/ctsk/lox/Parser.java index 7e40615..3e12ecc 100644 --- a/jlox/lox/src/main/java/xyz/ctsk/lox/Parser.java +++ b/jlox/lox/src/main/java/xyz/ctsk/lox/Parser.java @@ -15,11 +15,15 @@ import static xyz.ctsk.lox.TokenType.*; * | statement ; * varDecl → "var" IDENTIFIER ( "=" expression )? ";" ; * statement → exprStmt + * | forStmt * | ifStmt * | printStmt * | whileStmt * | block ; * block → "{" declaration* "}" ; + * forStmt → "for" "(" (varDecl | exprStmt | ";") + * expression? ";" + * expression? ")" statement ; * ifStmt → "if" "(" expression ")" statement ( "else" statement )? ; * whileStmt → "while" "(" expression ")" statement ; * printStmt → "print" expression ";" ; @@ -82,6 +86,7 @@ public class Parser { private Stmt statement() { + if (match(FOR)) return forStatement(); if (match(IF)) return ifStatement(); if (match(PRINT)) return printStatement(); if (match(WHILE)) return whileStatement(); @@ -89,6 +94,42 @@ public 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 = check(SEMICOLON) ? null : expression(); + consume(SEMICOLON, "Expect ';' after loop condition."); + + Expr increment = check(RIGHT_PAREN) ? null : expression(); + consume(RIGHT_PAREN, "Expect ')' after for clauses."); + + Stmt body = statement(); + + if (increment != null) { + body = new Stmt.Block(List.of(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(List.of(initializer, body)); + } + + return body; + } + private Stmt ifStatement() { consume(LEFT_PAREN, "Expect '(' after 'if'.");