requireFile.expand_path('../syntax/tokens',__FILE__)moduleRegexp::SyntaxclassSyntaxError<StandardErrordefinitialize(what)superwhatendendclassUnknownSyntaxNameError<SyntaxErrordefinitialize(name)super"Unknown syntax name '#{name}'"endendclassMissingSyntaxSpecError<SyntaxErrordefinitialize(name)super"Missing syntax specification file for '#{name}'"endendclassNotImplementedError<SyntaxErrordefinitialize(syntax,type,token)super"#{syntax.class.name} does not implement: [#{type}:#{token}]"endendSYNTAX_SPEC_ROOT=File.expand_path('../syntax',__FILE__)# Loads, and instantiates an instance of the syntax specification class for# the given syntax flavor name. The special names 'any' and '*' returns a# instance of Syntax::Any. See below for more details.defself.new(name)returnRegexp::Syntax::Any.newif['*','any'].include?(name.to_s)self.load(name)casename# Ruby 1.8.x (NOTE: 1.8.6 is no longer a supported runtime,# but its regex features are still recognized.)when'ruby/1.8.6';syntax=Regexp::Syntax::Ruby::V186.newwhen'ruby/1.8.7';syntax=Regexp::Syntax::Ruby::V187.new# alias for the latest 1.8 implementationwhen'ruby/1.8';syntax=Regexp::Syntax::Ruby::V18.new# Ruby 1.9.xwhen'ruby/1.9.1';syntax=Regexp::Syntax::Ruby::V191.newwhen'ruby/1.9.2';syntax=Regexp::Syntax::Ruby::V192.newwhen'ruby/1.9.3';syntax=Regexp::Syntax::Ruby::V193.new# alias for the latest 1.9 implementationwhen'ruby/1.9';syntax=Regexp::Syntax::Ruby::V19.new# Ruby 2.0.xwhen'ruby/2.0.0';syntax=Regexp::Syntax::Ruby::V200.new# aliases for the latest 2.0 implementationswhen'ruby/2.0';syntax=Regexp::Syntax::Ruby::V20.new# Ruby 2.1.xwhen'ruby/2.1.0';syntax=Regexp::Syntax::Ruby::V210.newwhen'ruby/2.1.2';syntax=Regexp::Syntax::Ruby::V212.newwhen'ruby/2.1.3';syntax=Regexp::Syntax::Ruby::V213.newwhen'ruby/2.1.4';syntax=Regexp::Syntax::Ruby::V214.newwhen'ruby/2.1.5';syntax=Regexp::Syntax::Ruby::V215.new# aliases for the latest 2.1 implementationswhen'ruby/2.1';syntax=Regexp::Syntax::Ruby::V21.new# Ruby 2.2.xwhen'ruby/2.2.0';syntax=Regexp::Syntax::Ruby::V220.new# aliases for the latest 2.2 implementationswhen'ruby/2.2';syntax=Regexp::Syntax::Ruby::V22.newelseraiseUnknownSyntaxError.new(name)endend# Checks if the named syntax has a specification class file, and requires# it if it does. Downcases names, and adds the .rb extension if omitted.defself.load(name)full="#{SYNTAX_SPEC_ROOT}/#{name.downcase}"full=(full[-1,3]=='.rb')?full:"#{full}.rb"raiseMissingSyntaxSpecError.new(name)unlessFile.exist?(full)requirefullend# A lookup map of supported types and tokens in a given syntaxclassBasedefinitialize@implements={}implementsToken::Literal::Type,Token::Literal::AllimplementsToken::FreeSpace::Type,Token::FreeSpace::Allenddefimplementation@implementsenddefimplements(type,tokens)if@implements[type]@implements[type]=(@implements[type]+tokens).uniqelse@implements[type]=tokensendend# removesdefexcludes(type,tokens)iftokenstokens=[tokens]unlesstokens.is_a?(Array)endif@implements[type]iftokens@implements[type]=@implements[type]-tokens@implements[type]=nilif@implements[type].empty?else@implements[type]=nilendendenddefimplements?(type,token)returntrueif@implements[type]and@implements[type].include?(token)falseendalias:check?:implements?defimplements!(type,token)raiseNotImplementedError.new(self,type,token)unlessimplements?(type,token)endalias:check!:implements!defnormalize(type,token)casetypewhen:groupnormalize_group(type,token)when:backrefnormalize_backref(type,token)else[type,token]endenddefnormalize_group(type,token)casetokenwhen:named_ab,:named_sq[:group,:named]else[type,token]endenddefnormalize_backref(type,token)casetokenwhen:name_ref_ab,:name_ref_sq[:backref,:name_ref]when:name_call_ab,:name_call_sq[:backref,:name_call]when:name_nest_ref_ab,:name_nest_ref_sq[:backref,:name_nest_ref]when:number_ref_ab,:number_ref_sq[:backref,:number_ref]when:number_call_ab,:number_call_sq[:backref,:number_call]when:number_rel_ref_ab,:number_rel_ref_sq[:backref,:number_rel_ref]when:number_rel_call_ab,:number_rel_call_sq[:backref,:number_rel_call]when:number_nest_ref_ab,:number_nest_ref_sq[:backref,:number_nest_ref]else[type,token]endendend# A syntax that always returns true, passing all tokens as implemented. This# is useful during development, testing, and should be useful for some types# of transformations as well.classAny<Basedefinitialize@implements={:*=>[:*]}enddefimplements?(type,token)trueenddefimplements!(type,token)trueendendend