9.5.1
FossilOrigin-Name: e6003611fc9c7f22e8ab96c338f79c3f8a0ddd7ff15b21a37568b4b6c3f54329
change ozputupqrvvouqvltnsswtwzzoxkxpqt
commit 3b7aa0c39ad111cafa3c4fee98648318cffd2b9f
author alpha <alpha@kejadlen.dev>
date
parent ollskrok
diff --git a/ruby/lib/lox/parser.rb b/ruby/lib/lox/parser.rb
index cfec840..0f6ce9f 100644
--- a/ruby/lib/lox/parser.rb
+++ b/ruby/lib/lox/parser.rb
@@ -46,6 +46,7 @@ module Lox
     end
 
     def statement
+      return for_stmt if match?(:FOR)
       return if_stmt if match?(:IF)
       return print if match?(:PRINT)
       return while_stmt if match?(:WHILE)
@@ -54,6 +55,44 @@ module Lox
       expression_stmt
     end
 
+    def for_stmt
+      consume!(:LEFT_PAREN, "Expect '(' after 'if'.")
+
+      initializer = if match?(:SEMICOLON)
+                      nil
+                    elsif match?(:VAR)
+                      var_declaration
+                    else
+                      expression_stmt
+                    end
+
+      condition = !check?(:SEMICOLON) ? expression : Expr::Literal(true)
+      consume!(:SEMICOLON, "Expect ';' after loop condition.")
+
+      increment = !check?(:RIGHT_PAREN) ? expression : nil
+      consume!(:RIGHT_PAREN, "Expect ')' after for clauses.")
+
+      body = statement
+
+      if increment
+        body = Stmt::Block.new([
+          body,
+          Stmt::Expr.new(increment),
+        ])
+      end
+
+      body = Stmt::While.new(condition, body);
+
+      if initializer
+        body = Stmt::Block.new([
+          initializer,
+          body,
+        ])
+      end
+
+      body
+    end
+
     def if_stmt
       consume!(:LEFT_PAREN, "Expect '(' after 'if'.")
       cond = expression
diff --git a/ruby/test/lox/test_interpreter.rb b/ruby/test/lox/test_interpreter.rb
index e7ce24b..21a1258 100644
--- a/ruby/test/lox/test_interpreter.rb
+++ b/ruby/test/lox/test_interpreter.rb
@@ -200,6 +200,30 @@ class TestInterpreter < Lox::Test
     SRC
   end
 
+  def test_for
+    assert_interpreted <<~EXPECTED.chomp, <<~SRC
+      0
+      1
+      1
+      2
+      3
+      5
+      8
+      13
+      21
+      34
+    EXPECTED
+      var a = 0;
+      var temp;
+
+      for (var b = 1; a < 50; b = temp + b) {
+        print a;
+        temp = a;
+        a = b;
+      }
+    SRC
+  end
+
   private
 
   def assert_interpreted(expected, src)