support nested block comments
FossilOrigin-Name: 5ec3ea233b52addff0cdd9b20b001c919a32cbf21e5b468e67fdc31cc4480051
change poyuryqutrpuzxzwllpkloxxoynzovqx
commit 3f75f255d685b0544818d748ab05f5ea23edce7d
author alpha <alpha@kejadlen.dev>
date
parent xswqtmlz
diff --git a/ruby/lox.rb b/ruby/lox.rb
index c05554e..e09b239 100755
--- a/ruby/lox.rb
+++ b/ruby/lox.rb
@@ -108,7 +108,8 @@ module Lox
         when state.scan(/>=/) then state.add_token(:GREATER_EQUAL)
         when state.scan(/>/)  then state.add_token(:GREATER)
         when state.scan(/\/\/(?~\n)+/)       # ignore line comment
-        when state.scan(/\/\*(?~\*\/)\*\//m) # ignore block comment
+        when state.scan(/\/\*/)
+          scan_block_comment(state)
         when state.scan(/\//) then state.add_token(:SLASH)
         when state.scan(/[ \r\t]/)    # ignore whitespace
         when state.scan(/\n/)         then state.line += 1
@@ -150,6 +151,26 @@ module Lox
         end
       end
     end
+
+    def scan_block_comment(state)
+      loop do
+        case
+        when state.scan(/\/\*/)
+          scan_block_comment(state)
+        when state.scan(/\*\//)
+          return
+        when state.scan(/\n/)
+          state.line += 1
+        when state.eos?
+          state.errors << Error.new(line: state.line, message: "Unterminated block comment.")
+          return
+        when c = state.scan(/./)
+          # no-op
+        else
+          fail "unreachable!"
+        end
+      end
+    end
   end
 
   Token = Struct.new(:type, :lexeme, :literal, :line) do
diff --git a/ruby/test_lox.rb b/ruby/test_lox.rb
index d89a137..3f55a98 100644
--- a/ruby/test_lox.rb
+++ b/ruby/test_lox.rb
@@ -103,13 +103,16 @@ class TestScanner < Minitest::Test
   def test_block_comments
     tokens = @scanner.scan(<<~SRC)
       foo
-      /* here lies a block comment */
+      /* here lies a /* nested */ block comment
+      with newlines */
       bar
     SRC
 
     assert_equal [
       Lox::Token.new(:IDENTIFIER, "foo", nil, 1),
-      Lox::Token.new(:IDENTIFIER, "bar", nil, 3),
+      Lox::Token.new(:IDENTIFIER, "bar", nil, 4),
     ], tokens
+
+    assert_equal [], @scanner.scan("/*")
   end
 end