support nested block comments
FossilOrigin-Name: 5ec3ea233b52addff0cdd9b20b001c919a32cbf21e5b468e67fdc31cc4480051
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