support nested block comments

FossilOrigin-Name: 5ec3ea233b52addff0cdd9b20b001c919a32cbf21e5b468e67fdc31cc4480051
private
alpha 2 years ago
parent dcdd0981f5
commit a4163b0e49

@ -108,7 +108,8 @@ module Lox
when state.scan(/>=/) then state.add_token(:GREATER_EQUAL) when state.scan(/>=/) then state.add_token(:GREATER_EQUAL)
when state.scan(/>/) then state.add_token(:GREATER) when state.scan(/>/) then state.add_token(:GREATER)
when state.scan(/\/\/(?~\n)+/) # ignore line comment 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(/\//) then state.add_token(:SLASH)
when state.scan(/[ \r\t]/) # ignore whitespace when state.scan(/[ \r\t]/) # ignore whitespace
when state.scan(/\n/) then state.line += 1 when state.scan(/\n/) then state.line += 1
@ -150,6 +151,26 @@ module Lox
end end
end 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 end
Token = Struct.new(:type, :lexeme, :literal, :line) do Token = Struct.new(:type, :lexeme, :literal, :line) do

@ -103,13 +103,16 @@ class TestScanner < Minitest::Test
def test_block_comments def test_block_comments
tokens = @scanner.scan(<<~SRC) tokens = @scanner.scan(<<~SRC)
foo foo
/* here lies a block comment */ /* here lies a /* nested */ block comment
with newlines */
bar bar
SRC SRC
assert_equal [ assert_equal [
Lox::Token.new(:IDENTIFIER, "foo", nil, 1), Lox::Token.new(:IDENTIFIER, "foo", nil, 1),
Lox::Token.new(:IDENTIFIER, "bar", nil, 3), Lox::Token.new(:IDENTIFIER, "bar", nil, 4),
], tokens ], tokens
assert_equal [], @scanner.scan("/*")
end end
end end

Loading…
Cancel
Save