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