def parse(src, location:)
def parse(src, location:)
case src
when keyword_subject_type("var", VAR_NAME)
Regexp.last_match.yield_self do |match|
match or raise
name = match[:name] or raise
AST::Annotation::VarType.new(name: name.to_sym,
type: parse_type(match, location: location),
location: location)
end
when keyword_subject_type("method", METHOD_NAME)
Regexp.last_match.yield_self do |match|
match or raise
name = match[:name] or raise
type = match[:type] or raise
method_type = factory.method_type(RBS::Parser.parse_method_type(type) || raise)
AST::Annotation::MethodType.new(name: name.to_sym,
type: method_type,
location: location)
end
when keyword_subject_type("const", CONST_NAME)
Regexp.last_match.yield_self do |match|
match or raise
name = match[:name] or raise
type = parse_type(match, location: location)
AST::Annotation::ConstType.new(name: RBS::TypeName.parse(name), type: type, location: location)
end
when keyword_subject_type("ivar", IVAR_NAME)
Regexp.last_match.yield_self do |match|
match or raise
name = match[:name] or raise
type = parse_type(match, location: location)
AST::Annotation::IvarType.new(name: name.to_sym,
type: type,
location: location)
end
when keyword_and_type("return")
Regexp.last_match.yield_self do |match|
match or raise
type = parse_type(match, location: location)
AST::Annotation::ReturnType.new(type: type, location: location)
end
when keyword_and_type("block")
Regexp.last_match.yield_self do |match|
match or raise
type = parse_type(match, location: location)
AST::Annotation::BlockType.new(type: type, location: location)
end
when keyword_and_type("self")
Regexp.last_match.yield_self do |match|
match or raise
type = parse_type(match, location: location)
AST::Annotation::SelfType.new(type: type, location: location)
end
when keyword_and_type("instance")
Regexp.last_match.yield_self do |match|
match or raise
type = parse_type(match, location: location)
AST::Annotation::InstanceType.new(type: type, location: location)
end
when keyword_and_type("module")
Regexp.last_match.yield_self do |match|
match or raise
type = parse_type(match, location: location)
AST::Annotation::ModuleType.new(type: type, location: location)
end
when keyword_and_type("break")
Regexp.last_match.yield_self do |match|
match or raise
type = parse_type(match, location: location)
AST::Annotation::BreakType.new(type: type, location: location)
end
when /@dynamic\s+(?<names>(#{DYNAMIC_NAME}\s*,\s*)*#{DYNAMIC_NAME})/
Regexp.last_match.yield_self do |match|
match or raise
names = (match[:names] || raise).split(/\s*,\s*/)
AST::Annotation::Dynamic.new(
names: names.map {|name|
case
when name.delete_prefix!("self.")
AST::Annotation::Dynamic::Name.new(name: name.to_sym, kind: :module)
when name.delete_prefix!("self?.")
AST::Annotation::Dynamic::Name.new(name: name.to_sym, kind: :module_instance)
else
AST::Annotation::Dynamic::Name.new(name: name.to_sym, kind: :instance)
end
},
location: location
)
end
when /@implements\s+(?<name>#{CONST_NAME})#{TYPE_PARAMS}$/
Regexp.last_match.yield_self do |match|
match or raise
type_name = RBS::TypeName.parse(match[:name] || raise)
params = match[:params]&.yield_self {|params| params.split(/,/).map {|param| param.strip.to_sym } } || []
name = AST::Annotation::Implements::Module.new(name: type_name, args: params)
AST::Annotation::Implements.new(name: name, location: location)
end
end
rescue RBS::ParsingError => exn
raise SyntaxError.new(source: src, location: location, exn: exn)
end