lib/rbs/parser.y in rbs-1.0.6 vs lib/rbs/parser.y in rbs-1.1.0

- old
+ new

@@ -758,12 +758,12 @@ } | kLBRACKET kRBRACKET { location = val[0].location + val[1].location result = Types::Tuple.new(types: [], location: location) } - | kLBRACKET type_list kRBRACKET { - location = val[0].location + val[2].location + | kLBRACKET type_list comma_opt kRBRACKET { + location = val[0].location + val[3].location types = val[1] result = Types::Tuple.new(types: types, location: location) } | kLPAREN type kRPAREN { type = val[1].dup @@ -792,22 +792,22 @@ | type_list kCOMMA type { result = val[0] + [val[2]] } record_type: - kLBRACE record_fields kRBRACE { + kLBRACE record_fields comma_opt kRBRACE { result = Types::Record.new( fields: val[1], - location: val[0].location + val[2].location + location: val[0].location + val[3].location ) } record_fields: record_field { result = val[0] } - | record_field kCOMMA record_fields { + | record_fields kCOMMA record_field { result = val[0].merge!(val[2]) } record_field: tSYMBOL kFATARROW type { @@ -1060,10 +1060,14 @@ } | tNAMESPACE { namespace = Namespace.parse(val[0].value) result = LocatedValue.new(value: namespace, location: val[0].location) } + + comma_opt: + kCOMMA | # empty + end ---- inner Types = RBS::Types @@ -1082,21 +1086,19 @@ @location = location @value = value end end -require "strscan" - attr_reader :input attr_reader :buffer attr_reader :eof_re def initialize(type, buffer:, eof_re:) super() @type = type @buffer = buffer - @input = StringScanner.new(buffer.content) + @input = CharScanner.new(buffer.content) @eof_re = eof_re @eof = false @bound_variables_stack = [] @comments = {} @ascii_only = buffer.content.ascii_only? @@ -1208,15 +1210,11 @@ [false, nil] end end def charpos(scanner) - if @ascii_only - scanner.pos - else - scanner.charpos - end + scanner.charpos end def empty_params_result [ [], @@ -1419,19 +1417,23 @@ new_token(:tSTRING, s) when input.scan(/'(\\'|[^'])*'/) s = input.matched.yield_self {|s| s[1, s.length - 2] }.gsub(/\\'/, "'") new_token(:tSTRING, s) else - raise "Unexpected token: #{input.peek(10)}..." + text = input.peek(10) + start_index = charpos(input) + end_index = start_index + text.length + location = RBS::Location.new(buffer: buffer, start_pos: start_index, end_pos: end_index) + raise LexerError.new(input: text, location: location) end end def on_error(token_id, error_value, value_stack) raise SyntaxError.new(token_str: token_to_str(token_id), error_value: error_value, value_stack: value_stack) end -class SyntaxError < StandardError +class SyntaxError < ParsingError attr_reader :token_str, :error_value, :value_stack def initialize(token_str:, error_value:, value_stack: nil) @token_str = token_str @error_value = error_value @@ -1439,18 +1441,29 @@ super "parse error on value: #{error_value.inspect} (#{token_str})" end end -class SemanticsError < StandardError +class SemanticsError < ParsingError attr_reader :subject, :location, :original_message def initialize(message, subject:, location:) @subject = subject @location = location @original_message = message super "parse error on #{location}: #{message}" + end +end + +class LexerError < ParsingError + attr_reader :location, :input + + def initialize(input:, location:) + @input = input + @location = location + + super "Unexpected string: #{input}..." end end ---- footer