1#!/usr/bin/ruby 2 3 4require 'erb' 5require 'antlr3' 6 7module ANTLR3 8module Template 9module 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 55end 56 57module RewriteBuilder 58 include Builder 59 60 def self.included( klass ) 61 super 62 Class === klass and klass.extend( Builder::ClassMethods ) 63 end 64 65private 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 85end 86 87 88autoload :GroupFile, 'antlr3/template/group-file' 89 90class 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 168private 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 209end 210 211class 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 271private 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 284end 285 286Parameter = Struct.new( :name, :default ) 287class Parameter 288 def to_s 289 default ? "#{ name } = #{ default }" : "#{ name }" 290 end 291end 292 293class 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 331end 332end 333end 334