lib/rbs/parser.y in rbs-1.1.1 vs lib/rbs/parser.y in rbs-1.2.0

- old
+ new

@@ -63,68 +63,123 @@ class_decl: annotations kCLASS start_new_scope class_name module_type_params super_class class_members kEND { reset_variable_scope location = val[1].location + val[7].location + location = location.with_children( + required: { + keyword: val[1].location, + name: val[3].location, + end: val[7].location + }, + optional: { + type_params: val[4]&.location, + lt: val[5]&.location + } + ) result = Declarations::Class.new( name: val[3].value, type_params: val[4]&.value || Declarations::ModuleTypeParams.empty, - super_class: val[5], + super_class: val[5]&.value, members: val[6], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location) ) } super_class: { result = nil } | kLT class_name { - result = Declarations::Class::Super.new(name: val[1].value, - args: [], - location: val[1].location) + loc = val[1].location.with_children( + required: { name: val[1].location }, + optional: { args: nil } + ) + sup = Declarations::Class::Super.new(name: val[1].value, args: [], location: loc) + result = LocatedValue.new(value: sup, location: val[0].location) } | kLT class_name kLBRACKET type_list kRBRACKET { - result = Declarations::Class::Super.new(name: val[1].value, - args: val[3], - location: val[1].location + val[4].location) + loc = (val[1].location + val[4].location).with_children( + required: { name: val[1].location }, + optional: { args: val[2].location + val[4].location } + ) + sup = Declarations::Class::Super.new(name: val[1].value, args: val[3], location: loc) + result = LocatedValue.new(value: sup, location: val[0].location) } module_decl: annotations kMODULE start_new_scope class_name module_type_params colon_module_self_types class_members kEND { reset_variable_scope + colon_loc = val[5].location + self_loc = val[5].value.yield_self do |params| + case params.size + when 0 + nil + when 1 + params[0].location + else + params.first.location + params.last.location + end + end + location = val[1].location + val[7].location + location = location.with_children( + required: { + keyword: val[1].location, + name: val[3].location, + end: val[7].location + }, + optional: { + type_params: val[4]&.location, + colon: colon_loc, + self_types: self_loc + } + ) result = Declarations::Module.new( name: val[3].value, type_params: val[4]&.value || Declarations::ModuleTypeParams.empty, - self_types: val[5], + self_types: val[5].value, members: val[6], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location) ) } - | annotations kMODULE start_new_scope tUKEYWORD module_self_types class_members kEND { + | annotations kMODULE start_new_scope namespace tUKEYWORD module_self_types class_members kEND { reset_variable_scope - location = val[1].location + val[6].location + location = val[1].location + val[7].location + name_loc, colon_loc = split_kw_loc(val[4].location) + self_loc = case val[5].size + when 0 + nil + when 1 + val[5][0].location + else + val[5].first.location + val[5].last.location + end + location = location.with_children( + required: { keyword: val[1].location, name: name_loc, end: val[7].location }, + optional: { colon: colon_loc, type_params: nil, self_types: self_loc } + ) + result = Declarations::Module.new( - name: val[3].value, + name: RBS::TypeName.new(name: val[4].value, namespace: val[3]&.value || RBS::Namespace.empty), type_params: Declarations::ModuleTypeParams.empty, - self_types: val[4], - members: val[5], + self_types: val[5], + members: val[6], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location) ) } colon_module_self_types: - { result = [] } + { result = LocatedValue.new(value: [], location: nil) } | kCOLON module_self_types { - result = val[1] + result = LocatedValue.new(value: val[1], location: val[0].location) } module_self_types: module_self_type { result = [val[0]] @@ -136,10 +191,14 @@ module_self_type: qualified_name kLBRACKET type_list kRBRACKET { name = val[0].value args = val[2] location = val[0].location + val[3].location + location = location.with_children( + required: { name: val[0].location }, + optional: { args: val[1].location + val[3].location } + ) case when name.class? result = Declarations::Module::Self.new(name: name, args: args, location: location) when name.interface? @@ -149,11 +208,14 @@ end } | qualified_name { name = val[0].value args = [] - location = val[0].location + location = val[0].location.with_children( + required: { name: val[0].location }, + optional: { args: nil } + ) case when name.class? result = Declarations::Module::Self.new(name: name, args: args, location: location) when name.interface? @@ -184,83 +246,158 @@ } | alias_member | signature attribute_kind: - { result = :instance } - | kSELF kDOT { result = :singleton } + { result = LocatedValue.new(value: :instance, location: nil) } + | kSELF kDOT { result = LocatedValue.new(value: :singleton, location: val[0].location + val[1].location) } attribute_member: annotations kATTRREADER attribute_kind keyword type { location = val[1].location + val[4].location + name_loc, colon_loc = split_kw_loc(val[3].location) + location = location.with_children( + required: { keyword: val[1].location, name: name_loc, colon: colon_loc }, + optional: { ivar: nil, ivar_name: nil, kind: val[2].location } + ) result = Members::AttrReader.new(name: val[3].value, ivar_name: nil, type: val[4], - kind: val[2], + kind: val[2].value, annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) } | annotations kATTRREADER attribute_kind method_name attr_var_opt kCOLON type { location = val[1].location + val[6].location + ivar_loc = val[4]&.location + case name_value = val[4]&.value + when LocatedValue + ivar_name = name_value.value + ivar_name_loc = name_value.location + when false + ivar_name = false + ivar_name_loc = nil + else + ivar_name = nil + ivar_loc = nil + end + location = location.with_children( + required: { keyword: val[1].location, name: val[3].location, colon: val[5].location }, + optional: { ivar: ivar_loc, ivar_name: ivar_name_loc, kind: val[2].location } + ) result = Members::AttrReader.new(name: val[3].value.to_sym, - ivar_name: val[4], + ivar_name: ivar_name, type: val[6], - kind: val[2], + kind: val[2].value, annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) } | annotations kATTRWRITER attribute_kind keyword type { location = val[1].location + val[4].location + name_loc, colon_loc = split_kw_loc(val[3].location) + location = location.with_children( + required: { keyword: val[1].location, name: name_loc, colon: colon_loc }, + optional: { ivar: nil, ivar_name: nil, kind: val[2].location } + ) result = Members::AttrWriter.new(name: val[3].value, ivar_name: nil, - kind: val[2], + kind: val[2].value, type: val[4], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) } | annotations kATTRWRITER attribute_kind method_name attr_var_opt kCOLON type { location = val[1].location + val[6].location + ivar_loc = val[4]&.location + case name_value = val[4]&.value + when LocatedValue + ivar_name = name_value.value + ivar_name_loc = name_value.location + when false + ivar_name = false + ivar_name_loc = nil + else + ivar_name = nil + ivar_loc = nil + end + location = location.with_children( + required: { keyword: val[1].location, name: val[3].location, colon: val[5].location }, + optional: { ivar: ivar_loc, ivar_name: ivar_name_loc, kind: val[2].location } + ) + result = Members::AttrWriter.new(name: val[3].value.to_sym, - ivar_name: val[4], - kind: val[2], + ivar_name: ivar_name, + kind: val[2].value, type: val[6], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) } | annotations kATTRACCESSOR attribute_kind keyword type { location = val[1].location + val[4].location + name_loc, colon_loc = split_kw_loc(val[3].location) + location = location.with_children( + required: { keyword: val[1].location, name: name_loc, colon: colon_loc }, + optional: { ivar: nil, ivar_name: nil, kind: val[2].location } + ) + result = Members::AttrAccessor.new(name: val[3].value, ivar_name: nil, - kind: val[2], + kind: val[2].value, type: val[4], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) } | annotations kATTRACCESSOR attribute_kind method_name attr_var_opt kCOLON type { location = val[1].location + val[6].location + ivar_loc = val[4]&.location + case name_value = val[4]&.value + when LocatedValue + ivar_name = name_value.value + ivar_name_loc = name_value.location + when false + ivar_name = false + ivar_name_loc = nil + else + ivar_name = nil + ivar_loc = nil + end + location = location.with_children( + required: { keyword: val[1].location, name: val[3].location, colon: val[5].location }, + optional: { ivar: ivar_loc, ivar_name: ivar_name_loc, kind: val[2].location } + ) + result = Members::AttrAccessor.new(name: val[3].value.to_sym, - ivar_name: val[4], - kind: val[2], + ivar_name: ivar_name, + kind: val[2].value, type: val[6], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) } attr_var_opt: { result = nil } - | kLPAREN kRPAREN { result = false } - | kLPAREN tIVAR kRPAREN { result = val[1].value } + | kLPAREN kRPAREN { result = LocatedValue.new(value: false, location: val[0].location + val[1].location) } + | kLPAREN tIVAR kRPAREN { + result = LocatedValue.new( + value: val[1], + location: val[0].location + val[2].location + ) + } var_type_member: tIVAR kCOLON type { - location = val[0].location + val[2].location + location = (val[0].location + val[2].location).with_children( + required: { name: val[0].location, colon: val[1].location }, + optional: { kind: nil } + ) + result = Members::InstanceVariable.new( name: val[0].value, type: val[2], location: location, comment: leading_comment(location) @@ -275,11 +412,15 @@ args: [], location: type.location ) end - location = val[0].location + val[2].location + location = (val[0].location + val[2].location).with_children( + required: { name: val[0].location, colon: val[1].location }, + optional: { kind: nil } + ) + result = Members::ClassVariable.new( name: val[0].value, type: type, location: location, comment: leading_comment(location) @@ -294,11 +435,15 @@ args: [], location: type.location ) end - location = val[0].location + val[4].location + location = (val[0].location + val[4].location).with_children( + required: { name: val[2].location, colon: val[3].location }, + optional: { kind: val[0].location + val[1].location } + ) + result = Members::ClassInstanceVariable.new( name: val[2].value, type: type, location: location, comment: leading_comment(location) @@ -308,10 +453,14 @@ interface_decl: annotations kINTERFACE start_new_scope interface_name module_type_params interface_members kEND { reset_variable_scope location = val[1].location + val[6].location + location = location.with_children( + required: { keyword: val[1].location, name: val[3].location, end: val[6].location }, + optional: { type_params: val[4]&.location } + ) result = Declarations::Interface.new( name: val[3].value, type_params: val[4]&.value || Declarations::ModuleTypeParams.empty, members: val[5], annotations: val[0], @@ -350,22 +499,32 @@ include_member: annotations kINCLUDE qualified_name { if val[2].value.alias? raise SemanticsError.new("Should include module or interface", subject: val[2].value, location: val[2].location) end - location = val[1].location + val[2].location + + location = (val[1].location + val[2].location).with_children( + required: { keyword: val[1].location, name: val[2].location }, + optional: { args: nil } + ) + result = Members::Include.new(name: val[2].value, args: [], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) } | annotations kINCLUDE qualified_name kLBRACKET type_list kRBRACKET { if val[2].value.alias? raise SemanticsError.new("Should include module or interface", subject: val[2].value, location: val[2].location) end - location = val[1].location + val[5].location + + location = (val[1].location + val[5].location).with_children( + required: { keyword: val[1].location, name: val[2].location }, + optional: { args: val[3].location + val[5].location } + ) + result = Members::Include.new(name: val[2].value, args: val[4], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) @@ -374,22 +533,32 @@ extend_member: annotations kEXTEND qualified_name { if val[2].value.alias? raise SemanticsError.new("Should extend module or interface", subject: val[2].value, location: val[2].location) end - location = val[1].location + val[2].location + + location = (val[1].location + val[2].location).with_children( + required: { keyword: val[1].location, name: val[2].location }, + optional: { args: nil } + ) + result = Members::Extend.new(name: val[2].value, args: [], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) } | annotations kEXTEND qualified_name kLBRACKET type_list kRBRACKET { if val[2].value.alias? raise SemanticsError.new("Should extend module or interface", subject: val[2].value, location: val[2].location) end - location = val[1].location + val[5].location + + location = (val[1].location + val[5].location).with_children( + required: { keyword: val[1].location, name: val[2].location }, + optional: { args: val[3].location + val[5].location } + ) + result = Members::Extend.new(name: val[2].value, args: val[4], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) @@ -398,22 +567,32 @@ prepend_member: annotations kPREPEND qualified_name { unless val[2].value.class? raise SemanticsError.new("Should prepend module", subject: val[2].value, location: val[2].location) end - location = val[1].location + val[2].location + + location = (val[1].location + val[2].location).with_children( + required: { keyword: val[1].location, name: val[2].location }, + optional: { args: nil } + ) + result = Members::Prepend.new(name: val[2].value, args: [], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) } | annotations kPREPEND qualified_name kLBRACKET type_list kRBRACKET { unless val[2].value.class? raise SemanticsError.new("Should prepend module", subject: val[2].value, location: val[2].location) end - location = val[1].location + val[5].location + + location = (val[1].location + val[5].location).with_children( + required: { keyword: val[1].location, name: val[2].location }, + optional: { args: val[3].location + val[5].location } + ) + result = Members::Prepend.new(name: val[2].value, args: val[4], annotations: val[0], location: location, comment: leading_comment(val[0].first&.location || location)) @@ -427,25 +606,37 @@ } method_member: annotations attributes overload kDEF method_kind def_name method_types { location = val[3].location + val[6].last.location + children = {} + required_children = { keyword: val[3].location, name: val[5].location } + optional_children = { kind: nil, overload: nil } + + if val[4] + kind = val[4].value + optional_children[:kind] = val[4].location + else + kind = :instance + end + last_type = val[6].last if last_type.is_a?(LocatedValue) && last_type.value == :dot3 overload = true + optional_children[:overload] = last_type.location val[6].pop else overload = false end result = Members::MethodDefinition.new( name: val[5].value, - kind: val[4], + kind: kind, types: val[6], annotations: val[0], - location: location, + location: location.with_children(required: required_children, optional: optional_children), comment: leading_comment(val[0].first&.location || val[2]&.location || val[3].location), overload: overload || !!val[2] ) } @@ -453,13 +644,13 @@ | attributes kINCOMPATIBLE { RBS.logger.warn "`incompatible` method attribute is deprecated and ignored." } method_kind: - { result = :instance } - | kSELF kDOT { result = :singleton } - | kSELFQ kDOT { result = :singleton_instance } + { result = nil } + | kSELF kDOT { result = LocatedValue.new(value: :singleton, location: val[0].location + val[1].location) } + | kSELFQ kDOT { result = LocatedValue.new(value: :singleton_instance, location: val[0].location + val[1].location) } method_types: method_type { result = [val[0]] } | kDOT3 { result = [LocatedValue.new(value: :dot3, location: val[0].location)] } | method_type kBAR method_types { @@ -496,11 +687,18 @@ block = Types::Block.new(type: val[2].value, required: false) result = LocatedValue.new(value: block, location: val[0].location + val[3].location) } def_name: - keyword + keyword { + loc = val[0].location + + result = LocatedValue.new( + value: val[0].value, + location: Location.new(buffer: loc.buffer, start_pos: loc.start_pos, end_pos: loc.end_pos - 1) + ) + } | method_name kCOLON { result = LocatedValue.new(value: val[0].value.to_sym, location: val[0].location + val[1].location) } @@ -553,23 +751,38 @@ result = val[0].add(val[2]) } module_type_param: type_param_check type_param_variance tUIDENT { - result = Declarations::ModuleTypeParams::TypeParam.new(name: val[2].value.to_sym, - variance: val[1], - skip_validation: val[0]) + loc = case + when l0 = val[0].location + l0 + val[2].location + when l1 = val[1].location + l1 + val[2].location + else + val[2].location + end + loc = loc.with_children( + required: { name: val[2].location }, + optional: { variance: val[1].location, unchecked: val[0].location } + ) + result = Declarations::ModuleTypeParams::TypeParam.new( + name: val[2].value.to_sym, + variance: val[1].value, + skip_validation: val[0].value, + location: loc + ) } type_param_variance: - { result = :invariant } - | kOUT { result = :covariant } - | kIN { result = :contravariant } + { result = LocatedValue.new(value: :invariant, location: nil) } + | kOUT { result = LocatedValue.new(value: :covariant, location: val[0].location) } + | kIN { result = LocatedValue.new(value: :contravariant, location: val[0].location) } type_param_check: - { result = false } - | kUNCHECKED { result = true } + { result = LocatedValue.new(value: false, location: nil) } + | kUNCHECKED { result = LocatedValue.new(value: true, location: val[0].location) } type_params: { result = nil } | kLBRACKET type_params0 kRBRACKET { val[1].each {|var| insert_bound_variable(var) } @@ -587,10 +800,14 @@ } alias_member: annotations kALIAS method_name method_name { location = val[1].location + val[3].location + location = location.with_children( + required: { keyword: val[1].location, new_name: val[2].location, old_name: val[3].location }, + optional: { new_kind: nil, old_kind: nil } + ) result = Members::Alias.new( new_name: val[2].value.to_sym, old_name: val[3].value.to_sym, kind: :instance, annotations: val[0], @@ -598,10 +815,17 @@ comment: leading_comment(val[0].first&.location || location) ) } | annotations kALIAS kSELF kDOT method_name kSELF kDOT method_name { location = val[1].location + val[7].location + location = location.with_children( + required: { keyword: val[1].location, new_name: val[4].location, old_name: val[7].location }, + optional: { + new_kind: val[2].location + val[3].location, + old_kind: val[5].location + val[6].location + } + ) result = Members::Alias.new( new_name: val[4].value.to_sym, old_name: val[7].value.to_sym, kind: :singleton, annotations: val[0], @@ -611,37 +835,55 @@ } type_decl: annotations kTYPE type_alias_name kEQ type { location = val[1].location + val[4].location - result = Declarations::Alias.new(name: val[2].value, - type: val[4], - annotations: val[0], - location: location, - comment: leading_comment(val[0].first&.location || location)) + location = location.with_children( + required: { keyword: val[1].location, name: val[2].location, eq: val[3].location } + ) + result = Declarations::Alias.new( + name: val[2].value, + type: val[4], + annotations: val[0], + location: location, + comment: leading_comment(val[0].first&.location || location) + ) } const_decl: class_name kCOLON type { location = val[0].location + val[2].location + location = location.with_children( + required: { name: val[0].location, colon: val[1].location } + ) result = Declarations::Constant.new(name: val[0].value, type: val[2], location: location, comment: leading_comment(location)) } | namespace tUKEYWORD type { location = (val[0] || val[1]).location + val[2].location + + lhs_loc = (val[0] || val[1]).location + val[1].location + name_loc, colon_loc = split_kw_loc(lhs_loc) + location = location.with_children( + required: { name: name_loc, colon: colon_loc } + ) + name = TypeName.new(name: val[1].value, namespace: val[0]&.value || Namespace.empty) result = Declarations::Constant.new(name: name, type: val[2], location: location, comment: leading_comment(location)) } global_decl: tGLOBALIDENT kCOLON type { location = val[0].location + val[2].location + location = location.with_children( + required: { name: val[0].location, colon: val[1].location } + ) result = Declarations::Global.new(name: val[0].value.to_sym, type: val[2], location: location, comment: leading_comment(location)) } @@ -729,15 +971,27 @@ case when name.class? if is_bound_variable?(name.name) result = Types::Variable.new(name: name.name, location: location) else + location = location.with_children( + required: { name: val[0].location }, + optional: { args: nil } + ) result = Types::ClassInstance.new(name: name, args: args, location: location) end when name.alias? + location = location.with_children( + required: { name: val[0].location }, + optional: { args: nil } + ) result = Types::Alias.new(name: name, location: location) when name.interface? + location = location.with_children( + required: { name: val[0].location }, + optional: { args: nil } + ) result = Types::Interface.new(name: name, args: args, location: location) end } | qualified_name kLBRACKET type_list kRBRACKET { name = val[0].value @@ -747,12 +1001,20 @@ case when name.class? if is_bound_variable?(name.name) raise SemanticsError.new("#{name.name} is type variable and cannot be applied", subject: name, location: location) end + location = location.with_children( + required: { name: val[0].location }, + optional: { args: val[1].location + val[3].location } + ) result = Types::ClassInstance.new(name: name, args: args, location: location) when name.interface? + location = location.with_children( + required: { name: val[0].location }, + optional: { args: val[1].location + val[3].location } + ) result = Types::Interface.new(name: name, args: args, location: location) else raise SyntaxError.new(token_str: "kLBRACKET", error_value: val[1]) end } @@ -771,12 +1033,15 @@ @location = val[0].location + val[2].location end result = type } | kSINGLETON kLPAREN class_name kRPAREN { - result = Types::ClassSingleton.new(name: val[2].value, - location: val[0].location + val[3].location) + location = val[0].location + val[3].location + location = location.with_children( + required: { name: val[2].location } + ) + result = Types::ClassSingleton.new(name: val[2].value, location: location) } | kHAT proc_type { type, block = val[1].value result = Types::Proc.new(type: type, block: block, location: val[0].location + val[1].location) } @@ -966,44 +1231,101 @@ result[6] = val[0] } required_positional: type var_name_opt { - result = Types::Function::Param.new(type: val[0], - name: val[1]&.value&.to_sym) + loc = val[0].location + if var_name = val[1] + loc = loc + var_name.location + end + loc = loc.with_children(optional: { name: var_name&.location }) + + result = Types::Function::Param.new( + type: val[0], + name: var_name&.value&.to_sym, + location: loc + ) } optional_positional: kQUESTION type var_name_opt { - result = Types::Function::Param.new(type: val[1], - name: val[2]&.value&.to_sym) + loc = val[0].location + val[1].location + if var_name = val[2] + loc = loc + var_name.location + end + loc = loc.with_children(optional: { name: var_name&.location }) + + result = Types::Function::Param.new( + type: val[1], + name: val[2]&.value&.to_sym, + location: loc + ) } rest_positional: kSTAR type var_name_opt { - result = Types::Function::Param.new(type: val[1], - name: val[2]&.value&.to_sym) + loc = val[0].location + val[1].location + if var_name = val[2] + loc = loc + var_name.location + end + loc = loc.with_children(optional: { name: var_name&.location }) + + result = Types::Function::Param.new( + type: val[1], + name: val[2]&.value&.to_sym, + location: loc + ) } required_keyword: keyword_name type var_name_opt { - param = Types::Function::Param.new(type: val[1], - name: val[2]&.value&.to_sym) + loc = val[0].location + val[1].location + if var_name = val[2] + loc = loc + var_name.location + end + + loc = loc.with_children(optional: { name: var_name&.location }) + + param = Types::Function::Param.new( + type: val[1], + name: val[2]&.value&.to_sym, + location: loc + ) result = { val[0].value => param } } optional_keyword: kQUESTION keyword_name type var_name_opt { - param = Types::Function::Param.new(type: val[2], - name: val[3]&.value&.to_sym) + loc = val[0].location + val[2].location + if var_name = val[3] + loc = loc + var_name.location + end + + loc = loc.with_children(optional: { name: var_name&.location }) + + param = Types::Function::Param.new( + type: val[2], + name: val[3]&.value&.to_sym, + location: loc + ) result = { val[1].value => param } } rest_keyword: kSTAR2 type var_name_opt { - result = Types::Function::Param.new(type: val[1], - name: val[2]&.value&.to_sym) + loc = val[0].location + val[1].location + if var_name = val[2] + loc = loc + var_name.location + end + + loc = loc.with_children(optional: { name: var_name&.location }) + + result = Types::Function::Param.new( + type: val[1], + name: val[2]&.value&.to_sym, + location: loc + ) } var_name_opt: | tLIDENT | tINTERFACEIDENT | tQUOTEDIDENT @@ -1427,9 +1749,19 @@ 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 + +def split_kw_loc(loc) + buf = loc.buffer + start_pos = loc.start_pos + end_pos = loc.end_pos + [ + Location.new(buffer: buf, start_pos: start_pos, end_pos: end_pos - 1), + Location.new(buffer: buf, start_pos: end_pos - 1, end_pos: end_pos) + ] end class SyntaxError < ParsingError attr_reader :token_str, :error_value, :value_stack