antlr3 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/java/antlr-full-3.2.1.jar +0 -0
- data/lib/antlr3.rb +2 -0
- data/lib/antlr3/main.rb +3 -5
- data/lib/antlr3/modes/ast-builder.rb +1 -22
- data/lib/antlr3/streams/rewrite.rb +3 -3
- data/lib/antlr3/task.rb +12 -1
- data/lib/antlr3/template.rb +319 -0
- data/lib/antlr3/template/group-lexer.rb +992 -0
- data/lib/antlr3/template/group-parser.rb +627 -0
- data/lib/antlr3/template/parameter.rb +56 -0
- data/lib/antlr3/test/grammar.rb +9 -11
- data/lib/antlr3/tree.rb +30 -0
- data/lib/antlr3/version.rb +2 -2
- data/templates/Ruby.stg +9 -10
- data/templates/ST.stg +128 -0
- data/test/functional/ast-output/auto-ast.rb +1 -1
- data/test/functional/ast-output/hetero-nodes.rb +2 -1
- data/test/functional/template-output/template-output.rb +404 -0
- data/test/unit/sample-input/template-group +38 -0
- data/test/unit/test-template.rb +248 -0
- metadata +12 -2
    
        data/java/antlr-full-3.2.1.jar
    CHANGED
    
    | Binary file | 
    
        data/lib/antlr3.rb
    CHANGED
    
    | @@ -161,6 +161,8 @@ module ANTLR3 | |
| 161 161 | 
             
              autoload :DOT, 'antlr3/dot'
         | 
| 162 162 | 
             
              autoload :InteractiveStringStream, 'antlr3/streams/interactive'
         | 
| 163 163 |  | 
| 164 | 
            +
              autoload :Template, 'antlr3/template'
         | 
| 165 | 
            +
              
         | 
| 164 166 | 
             
              $LOAD_PATH.include?(library_path) or $LOAD_PATH.unshift(library_path)
         | 
| 165 167 |  | 
| 166 168 | 
             
            end  # module ANTLR3
         | 
    
        data/lib/antlr3/main.rb
    CHANGED
    
    | @@ -2,7 +2,6 @@ | |
| 2 2 | 
             
            # encoding: utf-8
         | 
| 3 3 |  | 
| 4 4 | 
             
            =begin LICENSE
         | 
| 5 | 
            -
             | 
| 6 5 | 
             
            [The "BSD licence"]
         | 
| 7 6 | 
             
            Copyright (c) 2009 Kyle Yetter
         | 
| 8 7 | 
             
            All rights reserved.
         | 
| @@ -171,7 +170,8 @@ class Main | |
| 171 170 | 
             
                end
         | 
| 172 171 | 
             
              end
         | 
| 173 172 |  | 
| 174 | 
            -
             | 
| 173 | 
            +
            private
         | 
| 174 | 
            +
              
         | 
| 175 175 | 
             
              def execute_interactive
         | 
| 176 176 | 
             
                @output.puts( Util.tidy(<<-END) )
         | 
| 177 177 | 
             
                | ===================================================================
         | 
| @@ -379,7 +379,6 @@ class LexerMain < Main | |
| 379 379 |  | 
| 380 380 | 
             
            end
         | 
| 381 381 |  | 
| 382 | 
            -
             | 
| 383 382 | 
             
            =begin rdoc ANTLR3::Main::ParserMain
         | 
| 384 383 |  | 
| 385 384 | 
             
            A class which implements a handy test script which is executed whenever an ANTLR
         | 
| @@ -425,7 +424,7 @@ class ParserMain < Main | |
| 425 424 | 
             
              end
         | 
| 426 425 |  | 
| 427 426 | 
             
              def setup
         | 
| 428 | 
            -
                unless @lexer_class ||= fetch_class(@lexer_class_name)
         | 
| 427 | 
            +
                unless @lexer_class ||= fetch_class( @lexer_class_name )
         | 
| 429 428 | 
             
                  if @lexer_class_name
         | 
| 430 429 | 
             
                    fail("unable to locate the lexer class ``#@lexer_class_name''")
         | 
| 431 430 | 
             
                  else
         | 
| @@ -468,7 +467,6 @@ class ParserMain < Main | |
| 468 467 |  | 
| 469 468 | 
             
            end
         | 
| 470 469 |  | 
| 471 | 
            -
             | 
| 472 470 | 
             
            =begin rdoc ANTLR3::Main::WalkerMain
         | 
| 473 471 |  | 
| 474 472 | 
             
            A class which implements a handy test script which is executed whenever an ANTLR
         | 
| @@ -24,38 +24,17 @@ module ASTBuilder | |
| 24 24 | 
             
              shared_attribute( :adaptor )
         | 
| 25 25 |  | 
| 26 26 | 
             
            private
         | 
| 27 | 
            -
             | 
| 27 | 
            +
              
         | 
| 28 28 | 
             
              def subtree_stream(desc, element = nil)
         | 
| 29 29 | 
             
                AST::RewriteRuleSubtreeStream.new( @adaptor, desc, element )
         | 
| 30 | 
            -
                #if element.instance_of?( Array )
         | 
| 31 | 
            -
                #  AST::RewriteRuleSubtreeStream.new( @adaptor, desc, *element )
         | 
| 32 | 
            -
                #elsif element
         | 
| 33 | 
            -
                #  AST::RewriteRuleSubtreeStream.new( @adaptor, desc, element )
         | 
| 34 | 
            -
                #else
         | 
| 35 | 
            -
                #  AST::RewriteRuleSubtreeStream.new( @adaptor, desc )
         | 
| 36 | 
            -
                #end
         | 
| 37 30 | 
             
              end
         | 
| 38 31 |  | 
| 39 32 | 
             
              def token_stream(desc, element = nil)
         | 
| 40 33 | 
             
                AST::RewriteRuleTokenStream.new( @adaptor, desc, element )
         | 
| 41 | 
            -
                #if element.instance_of?( Array )
         | 
| 42 | 
            -
                #  AST::RewriteRuleTokenStream.new( @adaptor, desc, *element )
         | 
| 43 | 
            -
                #elsif element
         | 
| 44 | 
            -
                #  AST::RewriteRuleTokenStream.new( @adaptor, desc, element )
         | 
| 45 | 
            -
                #else
         | 
| 46 | 
            -
                #  AST::RewriteRuleTokenStream.new( @adaptor, desc )
         | 
| 47 | 
            -
                #end
         | 
| 48 34 | 
             
              end
         | 
| 49 35 |  | 
| 50 36 | 
             
              def node_stream(desc, element = nil)
         | 
| 51 37 | 
             
                AST::RewriteRuleNodeStream.new( @adaptor, desc, element )
         | 
| 52 | 
            -
                #if element.instance_of?( Array )
         | 
| 53 | 
            -
                #  AST::RewriteRuleNodeStream.new( @adaptor, desc, *element )
         | 
| 54 | 
            -
                #elsif element
         | 
| 55 | 
            -
                #  AST::RewriteRuleNodeStream.new( @adaptor, desc, element )
         | 
| 56 | 
            -
                #else
         | 
| 57 | 
            -
                #  AST::RewriteRuleNodeStream.new( @adaptor, desc )
         | 
| 58 | 
            -
                #end
         | 
| 59 38 | 
             
              end
         | 
| 60 39 | 
             
            end
         | 
| 61 40 | 
             
            end
         | 
| @@ -99,9 +99,9 @@ class InsertBefore < RewriteOperation | |
| 99 99 | 
             
              alias index= location=
         | 
| 100 100 |  | 
| 101 101 | 
             
              def execute(buffer)
         | 
| 102 | 
            -
                buffer << text
         | 
| 102 | 
            +
                buffer << text.to_s
         | 
| 103 103 | 
             
                token = stream[location]
         | 
| 104 | 
            -
                buffer << token.text if token
         | 
| 104 | 
            +
                buffer << token.text.to_s if token
         | 
| 105 105 | 
             
                return location + 1
         | 
| 106 106 | 
             
              end
         | 
| 107 107 | 
             
            end
         | 
| @@ -132,7 +132,7 @@ class Replace < RewriteOperation | |
| 132 132 | 
             
              end
         | 
| 133 133 |  | 
| 134 134 | 
             
              def execute(buffer)
         | 
| 135 | 
            -
                buffer << text unless text.nil?
         | 
| 135 | 
            +
                buffer << text.to_s unless text.nil?
         | 
| 136 136 | 
             
                return(location.end + 1)
         | 
| 137 137 | 
             
              end
         | 
| 138 138 |  | 
    
        data/lib/antlr3/task.rb
    CHANGED
    
    | @@ -49,6 +49,7 @@ class CompileTask < Rake::TaskLib | |
| 49 49 | 
             
                @grammar_sets = []
         | 
| 50 50 | 
             
                @name = options.fetch( :name, 'antlr-grammars' )
         | 
| 51 51 | 
             
                @options = options
         | 
| 52 | 
            +
                @namespace = Rake.application.current_scope
         | 
| 52 53 | 
             
                grammar_files.empty? or grammar_set( grammar_files )
         | 
| 53 54 | 
             
              end
         | 
| 54 55 |  | 
| @@ -69,6 +70,16 @@ class CompileTask < Rake::TaskLib | |
| 69 70 | 
             
                return( set )
         | 
| 70 71 | 
             
              end
         | 
| 71 72 |  | 
| 73 | 
            +
              def compile_task
         | 
| 74 | 
            +
                full_name = ( @namespace + [ @name, 'compile' ] ).join(':')
         | 
| 75 | 
            +
                Rake::Task[ full_name ]
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
              
         | 
| 78 | 
            +
              def clobber_task
         | 
| 79 | 
            +
                full_name = ( @namespace + [ @name, 'clobber' ] ).join(':')
         | 
| 80 | 
            +
                Rake::Task[ full_name ]
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
              
         | 
| 72 83 | 
             
              def define
         | 
| 73 84 | 
             
                namespace( @name ) do
         | 
| 74 85 | 
             
                  desc( "trash all ANTLR-generated source code")
         | 
| @@ -108,7 +119,7 @@ class CompileTask::GrammarSet | |
| 108 119 | 
             
                @grammars = grammar_files.map do | file |
         | 
| 109 120 | 
             
                  GrammarFile.new( self, file )
         | 
| 110 121 | 
             
                end
         | 
| 111 | 
            -
                @output_directory =  | 
| 122 | 
            +
                @output_directory = '.'
         | 
| 112 123 | 
             
                dir = options[ :output_directory ] and @output_directory = dir.to_s
         | 
| 113 124 |  | 
| 114 125 | 
             
                @antlr_jar = options.fetch( :antlr_jar, ANTLR3.antlr_jar )
         | 
| @@ -0,0 +1,319 @@ | |
| 1 | 
            +
            #!/usr/bin/ruby
         | 
| 2 | 
            +
            # encoding: utf-8
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'erb'
         | 
| 5 | 
            +
            require 'antlr3'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module ANTLR3
         | 
| 8 | 
            +
            module Template
         | 
| 9 | 
            +
            module Builder
         | 
| 10 | 
            +
              extend ClassMacros
         | 
| 11 | 
            +
              
         | 
| 12 | 
            +
              module ClassMethods
         | 
| 13 | 
            +
                attr_writer :template_library
         | 
| 14 | 
            +
                
         | 
| 15 | 
            +
                def template_library
         | 
| 16 | 
            +
                  @template_library ||= ANTLR3::Template::Group.new
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
                
         | 
| 19 | 
            +
                def return_scope_members
         | 
| 20 | 
            +
                  super.push( :template )
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
                
         | 
| 23 | 
            +
                def define_template( name, source, &block )
         | 
| 24 | 
            +
                  template_library.define_template( name, source, &block )
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
              
         | 
| 28 | 
            +
              def self.included( klass )
         | 
| 29 | 
            +
                super
         | 
| 30 | 
            +
                Class === klass and klass.extend( ClassMethods )
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
              
         | 
| 33 | 
            +
              def initialize( input, options = {} )
         | 
| 34 | 
            +
                templates = @templates || options.fetch( :templates ) do
         | 
| 35 | 
            +
                  self.class.template_library or ANTLR3::Template::Group.new
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
                super( input, options )
         | 
| 38 | 
            +
                self.templates = templates
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
              
         | 
| 41 | 
            +
              shared_attribute( :templates )
         | 
| 42 | 
            +
              
         | 
| 43 | 
            +
              def create_template( source, values = {} )
         | 
| 44 | 
            +
                @templates.new( source, values )
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
              
         | 
| 47 | 
            +
              def fetch_template( name, values = {} )
         | 
| 48 | 
            +
                @templates.fetch( name, values )
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
            end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            module RewriteBuilder
         | 
| 53 | 
            +
              include Builder
         | 
| 54 | 
            +
              
         | 
| 55 | 
            +
              def self.included( klass )
         | 
| 56 | 
            +
                super
         | 
| 57 | 
            +
                Class === klass and klass.extend( Builder::ClassMethods )
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
              
         | 
| 60 | 
            +
            private
         | 
| 61 | 
            +
              
         | 
| 62 | 
            +
              def cast_input( input, options )
         | 
| 63 | 
            +
                case input
         | 
| 64 | 
            +
                when TokenSource then TokenRewriteStream.new( input, options )
         | 
| 65 | 
            +
                when IO, String
         | 
| 66 | 
            +
                  if lexer_class = self.class.associated_lexer
         | 
| 67 | 
            +
                    TokenRewriteStream.new( lexer_class.new( input, options ), options )
         | 
| 68 | 
            +
                  else
         | 
| 69 | 
            +
                    raise ArgumentError, Util.tidy( <<-END, true )
         | 
| 70 | 
            +
                    | unable to automatically convert input #{ input.inspect }
         | 
| 71 | 
            +
                    | to a ANTLR3::TokenStream object as #{ self.class }
         | 
| 72 | 
            +
                    | does not appear to have an associated lexer class
         | 
| 73 | 
            +
                    END
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                else
         | 
| 76 | 
            +
                  super
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
              
         | 
| 80 | 
            +
            end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            class Group < Module
         | 
| 83 | 
            +
              autoload :Lexer, 'antlr3/template/group-lexer'
         | 
| 84 | 
            +
              autoload :Parser, 'antlr3/template/group-parser'
         | 
| 85 | 
            +
              
         | 
| 86 | 
            +
              def self.parse( source, options = {} )
         | 
| 87 | 
            +
                namespace = options.fetch( :namespace, ::Object )
         | 
| 88 | 
            +
                lexer  = Lexer.new( source, options )
         | 
| 89 | 
            +
                parser = Parser.new( lexer, options )
         | 
| 90 | 
            +
                return( parser.group( namespace ) )
         | 
| 91 | 
            +
              end
         | 
| 92 | 
            +
              
         | 
| 93 | 
            +
              def self.load( group_file, options = {} )
         | 
| 94 | 
            +
                namespace = options.fetch( :namespace, ::Object )
         | 
| 95 | 
            +
                input = ANTLR3::FileStream.new( group_file, options )
         | 
| 96 | 
            +
                lexer = Lexer.new( input, options )
         | 
| 97 | 
            +
                parser = Parser.new( lexer, options )
         | 
| 98 | 
            +
                return( parser.group( namespace ) )
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
              
         | 
| 101 | 
            +
              def self.new( &block )
         | 
| 102 | 
            +
                super do
         | 
| 103 | 
            +
                  const_set( :TEMPLATES, {} )
         | 
| 104 | 
            +
                  block_given? and module_eval( &block )
         | 
| 105 | 
            +
                end
         | 
| 106 | 
            +
              end
         | 
| 107 | 
            +
              
         | 
| 108 | 
            +
              def new( source, values = {} )
         | 
| 109 | 
            +
                erb = ERB.new( source, nil, '%' )
         | 
| 110 | 
            +
                template = Context.new( values )
         | 
| 111 | 
            +
                template.extend( self )
         | 
| 112 | 
            +
                sclass = class << template; self; end
         | 
| 113 | 
            +
                erb.def_method( sclass, 'to_s' )
         | 
| 114 | 
            +
                return( template )
         | 
| 115 | 
            +
              end
         | 
| 116 | 
            +
              
         | 
| 117 | 
            +
              def fetch( name, values = {} )
         | 
| 118 | 
            +
                self::TEMPLATES.fetch( name.to_s ).new( values )
         | 
| 119 | 
            +
              end
         | 
| 120 | 
            +
              
         | 
| 121 | 
            +
              def templates
         | 
| 122 | 
            +
                self::TEMPLATES
         | 
| 123 | 
            +
              end
         | 
| 124 | 
            +
              
         | 
| 125 | 
            +
              def template_defined?( name )
         | 
| 126 | 
            +
                self::TEMPLATES.has_key?( name.to_s )
         | 
| 127 | 
            +
              end
         | 
| 128 | 
            +
              
         | 
| 129 | 
            +
              def define_template( name, source, parameters = nil, &block )
         | 
| 130 | 
            +
                name = name.to_s.dup.freeze
         | 
| 131 | 
            +
                Context.define( self, name, parameters ) do | tclass |
         | 
| 132 | 
            +
                  self::TEMPLATES[ name ] = tclass
         | 
| 133 | 
            +
                  ERB.new( source, nil, '%' ).def_method( tclass, 'to_s' )
         | 
| 134 | 
            +
                  
         | 
| 135 | 
            +
                  define_template_methods( tclass )
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
                return( self )
         | 
| 138 | 
            +
              end
         | 
| 139 | 
            +
              
         | 
| 140 | 
            +
              def alias_template( new_name, old_name )
         | 
| 141 | 
            +
                new_name, old_name = new_name.to_s.dup.freeze, old_name.to_s
         | 
| 142 | 
            +
                context = self::TEMPLATES.fetch( old_name.to_s ) do
         | 
| 143 | 
            +
                  raise( NameError,
         | 
| 144 | 
            +
                    "undefined template `%s' for template group %p" % [ old_name, self ]
         | 
| 145 | 
            +
                  )
         | 
| 146 | 
            +
                end
         | 
| 147 | 
            +
                context.define_alias( new_name ) do | tclass |
         | 
| 148 | 
            +
                  self::TEMPLATES[ new_name ] = tclass
         | 
| 149 | 
            +
                  define_template_methods( tclass )
         | 
| 150 | 
            +
                end
         | 
| 151 | 
            +
                return( self )
         | 
| 152 | 
            +
              end
         | 
| 153 | 
            +
              
         | 
| 154 | 
            +
            private
         | 
| 155 | 
            +
              
         | 
| 156 | 
            +
              def define_template_methods( context )
         | 
| 157 | 
            +
                name = context.name
         | 
| 158 | 
            +
                if params = context.parameters
         | 
| 159 | 
            +
                  init = params.names.map do | param |
         | 
| 160 | 
            +
                    "___[ #{ param.inspect } ] = #{ param }"
         | 
| 161 | 
            +
                  end.join( "\n" )
         | 
| 162 | 
            +
                  
         | 
| 163 | 
            +
                  module_eval( <<-END )
         | 
| 164 | 
            +
                    module_function
         | 
| 165 | 
            +
                    
         | 
| 166 | 
            +
                    def #{ name }( #{ params } )
         | 
| 167 | 
            +
                      TEMPLATES[ #{ name.inspect } ].new do | ___ |
         | 
| 168 | 
            +
                        #{ init }
         | 
| 169 | 
            +
                      end
         | 
| 170 | 
            +
                    end
         | 
| 171 | 
            +
                    
         | 
| 172 | 
            +
                    def #{ name }!( #{ params } )
         | 
| 173 | 
            +
                      TEMPLATES[ #{ name.inspect } ].new do | ___ |
         | 
| 174 | 
            +
                        #{ init }
         | 
| 175 | 
            +
                      end.to_s
         | 
| 176 | 
            +
                    end
         | 
| 177 | 
            +
                  END
         | 
| 178 | 
            +
                  
         | 
| 179 | 
            +
                else
         | 
| 180 | 
            +
                  
         | 
| 181 | 
            +
                  module_eval( <<-END )
         | 
| 182 | 
            +
                    module_function
         | 
| 183 | 
            +
                    
         | 
| 184 | 
            +
                    def #{ name }( values = {} )
         | 
| 185 | 
            +
                      TEMPLATES[ #{ name.inspect } ].new( values )
         | 
| 186 | 
            +
                    end
         | 
| 187 | 
            +
                    
         | 
| 188 | 
            +
                    def #{ name }!( values = {} )
         | 
| 189 | 
            +
                      TEMPLATES[ #{ name.inspect } ].new( values ).to_s
         | 
| 190 | 
            +
                    end
         | 
| 191 | 
            +
                  END
         | 
| 192 | 
            +
                  
         | 
| 193 | 
            +
                end
         | 
| 194 | 
            +
              end
         | 
| 195 | 
            +
            end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
            class Context
         | 
| 198 | 
            +
              VARIABLE_FORM = /^(@)?[a-z_\x80-\xff][\w\x80-\xff]*$/
         | 
| 199 | 
            +
              SETTER_FORM = /^([a-z_\x80-\xff][\w\x80-\xff]*)=$/
         | 
| 200 | 
            +
              ATTR_FORM = /^[a-z_\x80-\xff][\w\x80-\xff]*$/
         | 
| 201 | 
            +
              
         | 
| 202 | 
            +
              class << self
         | 
| 203 | 
            +
                attr_accessor :group, :name, :parameters
         | 
| 204 | 
            +
                protected :group=, :name=
         | 
| 205 | 
            +
                
         | 
| 206 | 
            +
                def define_alias( name )
         | 
| 207 | 
            +
                  new = clone
         | 
| 208 | 
            +
                  new.name = name
         | 
| 209 | 
            +
                  new.group = @group
         | 
| 210 | 
            +
                  block_given? and yield( new )
         | 
| 211 | 
            +
                  return( new )
         | 
| 212 | 
            +
                end
         | 
| 213 | 
            +
                
         | 
| 214 | 
            +
                def define( group, name, parameters )
         | 
| 215 | 
            +
                  Class.new( self ) do
         | 
| 216 | 
            +
                    include( group )
         | 
| 217 | 
            +
                    
         | 
| 218 | 
            +
                    @group = group
         | 
| 219 | 
            +
                    @name  = name
         | 
| 220 | 
            +
                    @parameters = parameters
         | 
| 221 | 
            +
                    
         | 
| 222 | 
            +
                    block_given? and yield( self )
         | 
| 223 | 
            +
                  end
         | 
| 224 | 
            +
                end
         | 
| 225 | 
            +
              end
         | 
| 226 | 
            +
              
         | 
| 227 | 
            +
              def method_missing( method, *args )
         | 
| 228 | 
            +
                case name = method.to_s
         | 
| 229 | 
            +
                when SETTER_FORM then return( self[ $1 ] = *args )
         | 
| 230 | 
            +
                when ATTR_FORM
         | 
| 231 | 
            +
                  args.empty? and has_ivar?( name ) and return( self[ name ] )
         | 
| 232 | 
            +
                end
         | 
| 233 | 
            +
                super
         | 
| 234 | 
            +
              end
         | 
| 235 | 
            +
              
         | 
| 236 | 
            +
              def []=( name, value )
         | 
| 237 | 
            +
                instance_variable_set( make_ivar( name ), value )
         | 
| 238 | 
            +
              end
         | 
| 239 | 
            +
              
         | 
| 240 | 
            +
              def []( name )
         | 
| 241 | 
            +
                name = make_ivar( name )
         | 
| 242 | 
            +
                instance_variable_defined?( name ) ? instance_variable_get( name ) : nil
         | 
| 243 | 
            +
              end
         | 
| 244 | 
            +
              
         | 
| 245 | 
            +
              def <<( variable_map )
         | 
| 246 | 
            +
                variable_map.each_pair do | name, value |
         | 
| 247 | 
            +
                  self[ name ] = value
         | 
| 248 | 
            +
                end
         | 
| 249 | 
            +
                return( self )
         | 
| 250 | 
            +
              end
         | 
| 251 | 
            +
              
         | 
| 252 | 
            +
              def initialize( variable_map = nil )
         | 
| 253 | 
            +
                variable_map and self << variable_map
         | 
| 254 | 
            +
                block_given? and yield( self )
         | 
| 255 | 
            +
              end
         | 
| 256 | 
            +
              
         | 
| 257 | 
            +
            private
         | 
| 258 | 
            +
              
         | 
| 259 | 
            +
              def has_ivar?( name )
         | 
| 260 | 
            +
                instance_variable_defined?( make_ivar( name ) )
         | 
| 261 | 
            +
              end
         | 
| 262 | 
            +
              
         | 
| 263 | 
            +
              def make_ivar( name )
         | 
| 264 | 
            +
                name = name.to_s
         | 
| 265 | 
            +
                VARIABLE_FORM =~ name or
         | 
| 266 | 
            +
                  raise ArgumentError, "cannot convert %p to an instance variable name" % name
         | 
| 267 | 
            +
                $1 ? name : "@#{ name }"
         | 
| 268 | 
            +
              end
         | 
| 269 | 
            +
              
         | 
| 270 | 
            +
            end
         | 
| 271 | 
            +
             | 
| 272 | 
            +
            Parameter = Struct.new( :name, :default )
         | 
| 273 | 
            +
            class Parameter
         | 
| 274 | 
            +
              def to_s
         | 
| 275 | 
            +
                default ? "#{ name } = #{ default }" : "#{ name }"
         | 
| 276 | 
            +
              end
         | 
| 277 | 
            +
            end
         | 
| 278 | 
            +
             | 
| 279 | 
            +
            class ParameterList < ::Array
         | 
| 280 | 
            +
              attr_accessor :splat, :block
         | 
| 281 | 
            +
              
         | 
| 282 | 
            +
              def self.default
         | 
| 283 | 
            +
                new.add( :values ) do | p |
         | 
| 284 | 
            +
                  p.default = '{}'
         | 
| 285 | 
            +
                end
         | 
| 286 | 
            +
              end
         | 
| 287 | 
            +
              
         | 
| 288 | 
            +
              def names
         | 
| 289 | 
            +
                names = map { | param | param.name.to_s }
         | 
| 290 | 
            +
                @splat and names << @splat.to_s
         | 
| 291 | 
            +
                @block and names << @block.to_s
         | 
| 292 | 
            +
                return( names )
         | 
| 293 | 
            +
              end
         | 
| 294 | 
            +
              
         | 
| 295 | 
            +
              def add( name, options = nil )
         | 
| 296 | 
            +
                param =
         | 
| 297 | 
            +
                  case name
         | 
| 298 | 
            +
                  when Parameter then name
         | 
| 299 | 
            +
                  else Parameter.new( name.to_s )
         | 
| 300 | 
            +
                  end
         | 
| 301 | 
            +
                if options
         | 
| 302 | 
            +
                  default = options[ :default ] and param.default = default
         | 
| 303 | 
            +
                  param.splat = options.fetch( :splat, false )
         | 
| 304 | 
            +
                  param.block = options.fetch( :block, false )
         | 
| 305 | 
            +
                end
         | 
| 306 | 
            +
                block_given? and yield( param )
         | 
| 307 | 
            +
                push( param )
         | 
| 308 | 
            +
                return( self )
         | 
| 309 | 
            +
              end
         | 
| 310 | 
            +
              
         | 
| 311 | 
            +
              def to_s
         | 
| 312 | 
            +
                signature = join( ', ' )
         | 
| 313 | 
            +
                @splat and signature << ", *" << @splat.to_s
         | 
| 314 | 
            +
                @block and signature << ", &" << @block.to_s
         | 
| 315 | 
            +
                return( signature )
         | 
| 316 | 
            +
              end
         | 
| 317 | 
            +
            end
         | 
| 318 | 
            +
            end
         | 
| 319 | 
            +
            end
         |