Home | History | Annotate | Download | only in antlr3
      1 #!/usr/bin/ruby
      2 
      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 load_templates( group_file )
     24       @template_library = 
     25         ANTLR3::Template::Group.load( group_file )
     26     end
     27     
     28     def define_template( name, source, &block )
     29       template_library.define_template( name, source, &block )
     30     end
     31   end
     32   
     33   def self.included( klass )
     34     super
     35     Class === klass and klass.extend( ClassMethods )
     36   end
     37   
     38   def initialize( input, options = {} )
     39     templates = @templates || options.fetch( :templates ) do
     40       self.class.template_library or ANTLR3::Template::Group.new
     41     end
     42     super( input, options )
     43     self.templates = templates
     44   end
     45   
     46   shared_attribute( :templates )
     47   
     48   def create_template( source, values = {} )
     49     @templates.new( source, values )
     50   end
     51   
     52   def fetch_template( name, values = {} )
     53     @templates.fetch( name, values )
     54   end
     55 end
     56 
     57 module RewriteBuilder
     58   include Builder
     59   
     60   def self.included( klass )
     61     super
     62     Class === klass and klass.extend( Builder::ClassMethods )
     63   end
     64   
     65 private
     66   
     67   def cast_input( input, options )
     68     case input
     69     when TokenSource then TokenRewriteStream.new( input, options )
     70     when IO, String
     71       if lexer_class = self.class.associated_lexer
     72         TokenRewriteStream.new( lexer_class.new( input, options ), options )
     73       else
     74         raise ArgumentError, Util.tidy( <<-END, true )
     75         | unable to automatically convert input #{ input.inspect }
     76         | to a ANTLR3::TokenStream object as #{ self.class }
     77         | does not appear to have an associated lexer class
     78         END
     79       end
     80     else
     81       super
     82     end
     83   end
     84   
     85 end
     86 
     87 
     88 autoload :GroupFile, 'antlr3/template/group-file'
     89 
     90 class Group < Module
     91   autoload :Lexer, 'antlr3/template/group-file'
     92   autoload :Parser, 'antlr3/template/group-file'
     93   
     94   def self.parse( source, options = {} )
     95     namespace = options.fetch( :namespace, ::Object )
     96     lexer  = Lexer.new( source, options )
     97     parser = Parser.new( lexer, options )
     98     return( parser.group( namespace ) )
     99   end
    100   
    101   def self.load( group_file, options = {} )
    102     unless( File.file?( group_file ) )
    103       dir = $LOAD_PATH.find do | d |
    104         File.file?( File.join( dir, group_file ) )
    105       end or raise( LoadError, "no such template group file to load %s" % group_file )
    106       group_file = File.join( dir, group_file )
    107     end
    108     namespace = options.fetch( :namespace, ::Object )
    109     input = ANTLR3::FileStream.new( group_file, options )
    110     lexer = Lexer.new( input, options )
    111     parser = Parser.new( lexer, options )
    112     return( parser.group( namespace ) )
    113   end
    114   
    115   def self.new( &block )
    116     super do
    117       const_set( :TEMPLATES, {} )
    118       block_given? and module_eval( &block )
    119     end
    120   end
    121   
    122   def new( source, values = {} )
    123     erb = ERB.new( source, nil, '%' )
    124     template = Context.new( values )
    125     template.extend( self )
    126     sclass = class << template; self; end
    127     erb.def_method( sclass, 'to_s' )
    128     return( template )
    129   end
    130   
    131   def fetch( name, values = {} )
    132     self::TEMPLATES.fetch( name.to_s ).new( values )
    133   end
    134   
    135   def templates
    136     self::TEMPLATES
    137   end
    138   
    139   def template_defined?( name )
    140     self::TEMPLATES.has_key?( name.to_s )
    141   end
    142   
    143   def define_template( name, source, parameters = nil, &block )
    144     name = name.to_s.dup.freeze
    145     Context.define( self, name, parameters ) do | tclass |
    146       self::TEMPLATES[ name ] = tclass
    147       ERB.new( source, nil, '%' ).def_method( tclass, 'to_s' )
    148       
    149       define_template_methods( tclass )
    150     end
    151     return( self )
    152   end
    153   
    154   def alias_template( new_name, old_name )
    155     new_name, old_name = new_name.to_s.dup.freeze, old_name.to_s
    156     context = self::TEMPLATES.fetch( old_name.to_s ) do
    157       raise( NameError,
    158         "undefined template `%s' for template group %p" % [ old_name, self ]
    159       )
    160     end
    161     context.define_alias( new_name ) do | tclass |
    162       self::TEMPLATES[ new_name ] = tclass
    163       define_template_methods( tclass )
    164     end
    165     return( self )
    166   end
    167   
    168 private
    169   
    170   def define_template_methods( context )
    171     name = context.name
    172     if params = context.parameters
    173       init = params.names.map do | param |
    174         "___[ #{ param.inspect } ] = #{ param }"
    175       end.join( "\n" )
    176       
    177       module_eval( <<-END )
    178         module_function
    179         
    180         def #{ name }( #{ params } )
    181           TEMPLATES[ #{ name.inspect } ].new do | ___ |
    182             #{ init }
    183           end
    184         end
    185         
    186         def #{ name }!( #{ params } )
    187           TEMPLATES[ #{ name.inspect } ].new do | ___ |
    188             #{ init }
    189           end.to_s
    190         end
    191       END
    192       
    193     else
    194       
    195       module_eval( <<-END )
    196         module_function
    197         
    198         def #{ name }( values = {} )
    199           TEMPLATES[ #{ name.inspect } ].new( values )
    200         end
    201         
    202         def #{ name }!( values = {} )
    203           TEMPLATES[ #{ name.inspect } ].new( values ).to_s
    204         end
    205       END
    206       
    207     end
    208   end
    209 end
    210 
    211 class Context
    212   VARIABLE_FORM = /^(@)?[a-z_\x80-\xff][\w\x80-\xff]*$/
    213   SETTER_FORM = /^([a-z_\x80-\xff][\w\x80-\xff]*)=$/
    214   ATTR_FORM = /^[a-z_\x80-\xff][\w\x80-\xff]*$/
    215   
    216   class << self
    217     attr_accessor :group, :name, :parameters
    218     protected :group=, :name=
    219     
    220     def define_alias( name )
    221       new = clone
    222       new.name = name
    223       new.group = @group
    224       block_given? and yield( new )
    225       return( new )
    226     end
    227     
    228     def define( group, name, parameters )
    229       Class.new( self ) do
    230         include( group )
    231         
    232         @group = group
    233         @name  = name
    234         @parameters = parameters
    235         
    236         block_given? and yield( self )
    237       end
    238     end
    239   end
    240   
    241   def method_missing( method, *args )
    242     case name = method.to_s
    243     when SETTER_FORM then return( self[ $1 ] = args.first )
    244     when ATTR_FORM
    245       args.empty? and has_ivar?( name ) and return( self[ name ] )
    246     end
    247     super
    248   end
    249   
    250   def []=( name, value )
    251     instance_variable_set( make_ivar( name ), value )
    252   end
    253   
    254   def []( name )
    255     name = make_ivar( name )
    256     instance_variable_defined?( name ) ? instance_variable_get( name ) : nil
    257   end
    258   
    259   def <<( variable_map )
    260     variable_map.each_pair do | name, value |
    261       self[ name ] = value
    262     end
    263     return( self )
    264   end
    265   
    266   def initialize( variable_map = nil )
    267     variable_map and self << variable_map
    268     block_given? and yield( self )
    269   end
    270   
    271 private
    272   
    273   def has_ivar?( name )
    274     instance_variable_defined?( make_ivar( name ) )
    275   end
    276   
    277   def make_ivar( name )
    278     name = name.to_s
    279     VARIABLE_FORM =~ name or
    280       raise ArgumentError, "cannot convert %p to an instance variable name" % name
    281     $1 ? name : "@#{ name }"
    282   end
    283   
    284 end
    285 
    286 Parameter = Struct.new( :name, :default )
    287 class Parameter
    288   def to_s
    289     default ? "#{ name } = #{ default }" : "#{ name }"
    290   end
    291 end
    292 
    293 class ParameterList < ::Array
    294   attr_accessor :splat, :block
    295   
    296   def self.default
    297     new.add( :values ) do | p |
    298       p.default = '{}'
    299     end
    300   end
    301   
    302   def names
    303     names = map { | param | param.name.to_s }
    304     @splat and names << @splat.to_s
    305     @block and names << @block.to_s
    306     return( names )
    307   end
    308   
    309   def add( name, options = nil )
    310     param =
    311       case name
    312       when Parameter then name
    313       else Parameter.new( name.to_s )
    314       end
    315     if options
    316       default = options[ :default ] and param.default = default
    317       param.splat = options.fetch( :splat, false )
    318       param.block = options.fetch( :block, false )
    319     end
    320     block_given? and yield( param )
    321     push( param )
    322     return( self )
    323   end
    324   
    325   def to_s
    326     signature = join( ', ' )
    327     @splat and signature << ", *" << @splat.to_s
    328     @block and signature << ", &" << @block.to_s
    329     return( signature )
    330   end
    331 end
    332 end
    333 end
    334