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