Bläddra i källkod

Parsing variables -- ForLoop Statements

runningwater 2 år sedan
förälder
incheckning
2ec2b3f920

+ 4 - 1
README.md

@@ -112,9 +112,12 @@
               logic_and      → equality ( "and" equality )* ;
             ```
             statement      → exprStmt
+            | forStmt
             | ifStmt
             | printStmt
             | whileStmt
             | block ;
 
-            whileStmt      → "while" "(" expression ")" statement ;
+            whileStmt   → "while" "(" expression ")" statement ;
+            forStmt     → "for" " (" (varDecl | exprStmt | ";") 
+                          expression? ";" expression? ")" statement ;

+ 43 - 1
src/main/java/com/craftinginterpreters/lox/Parser.java

@@ -5,6 +5,7 @@ package com.craftinginterpreters.lox;
 import static com.craftinginterpreters.lox.TokenType.*;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -53,8 +54,9 @@ public class Parser {
     }
   }
 
-  // statement  → exprStmt | ifStmt | printStmt | whileStmt | block;
+  // statement  → exprStmt | forStmt | ifStmt | printStmt | whileStmt | block;
   private Stmt statement() {
+    if (match(FOR)) return forStatement();
     if (match(IF)) return ifStatement();
     if (match(PRINT)) return printStatement();
     if (match(WHILE)) return whileStatement();
@@ -62,6 +64,46 @@ public class Parser {
     return expressionStatement();
   }
 
+  private Stmt forStatement() {
+    consume(LEFT_PARAM, "Expect '(' after 'for'.");
+
+    Stmt initializer;
+    if (match(SEMICOLON)) {
+      initializer = null;
+    } else if (match(VAR)) {
+      initializer = varDecl();
+    } else {
+      initializer = expressionStatement();
+    }
+
+    Expr condition = null;
+    if (!check(SEMICOLON)) {
+      condition = expression();
+    }
+    consume(SEMICOLON, "Expect ';' after loop condition.");
+
+    Expr increment = null;
+    if (!check(SEMICOLON)) {
+      increment = expression();
+    }
+    consume(RIGHT_PARAM, "Expect ')' after for clauses.");
+
+    Stmt body = statement();
+
+    // desugaring
+    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;
+  }
+
   // whileStmt      → "while" "(" expression ")" statement ;
   private Stmt whileStatement() {
     consume(LEFT_PARAM, "Expect '(' after 'while'.");

+ 1 - 0
src/main/java/com/craftinginterpreters/lox/Scanner.java

@@ -34,6 +34,7 @@ public class Scanner {
     keywords.put("true", TRUE);
     keywords.put("var", VAR);
     keywords.put("while", WHILE);
+    keywords.put("for", FOR);
   }
 
   private final String source;