rubber-generate 0.0.5

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.
@@ -0,0 +1,63 @@
1
+ require 'rubber/codegen/class'
2
+
3
+ module Rubber
4
+
5
+ class C_Struct < C_Class
6
+ define_members :name, :args, :parent
7
+ attr_reader :child_names
8
+ def init
9
+ @functions = []
10
+ @classes = []
11
+ @methods = []
12
+ end
13
+ def declare(io)
14
+ io.puts "static VALUE #{cname};"
15
+ end
16
+ include RegisterChildren
17
+ def default_cname
18
+ "struct"+name
19
+ end
20
+ def doc_rd(io)
21
+ depth = (fullname.gsub(/[^:]/,'').size >> 1)
22
+ io.puts "=#{'=' * depth} enum #{fullname}"
23
+ end
24
+ def get_root(); is_root? ? self : parent.get_root; end; def is_root?()
25
+ not parent.respond_to?(:fullname)
26
+ end
27
+ def fullname()
28
+ if parent and parent.respond_to?(:fullname)
29
+ "#{parent.fullname}::#{name}"
30
+ else
31
+ name
32
+ end
33
+ end
34
+ def same_prefix(arr)
35
+ for i in arr
36
+ return false if arr.first.first != i.first
37
+ end
38
+ return true
39
+ end
40
+ def strip_prefixes(arr)
41
+ splits = arr.collect { |i| i.strip.split(/_/) }
42
+ while (same_prefix(splits))
43
+ splits.each { |i| i.shift }
44
+ end
45
+ splits.collect!{|i| i.join('_') }
46
+ splits
47
+ end
48
+ def get_root(); is_root? ? self : parent.get_root; end;
49
+ def is_root?()
50
+ not parent.respond_to?(:fullname)
51
+ end
52
+ def register(io, already_defined=false)
53
+ io.puts " #{cname} = rb_struct_define(#{name.inspect}, #{args.map{|m|m[0]==?" && m || m.inspect}.join(', ')}, NULL);"
54
+ if parent
55
+ io.puts " rb_define_const(#{parent.cname}, #{name.inspect}, #{cname});"
56
+ else
57
+ #io.puts " rb_define_const(#{parent.cname}, #{name.inspect}, #{cname});"
58
+ end
59
+ register_children(io)
60
+ end
61
+ end
62
+
63
+ end # Rubber
@@ -0,0 +1,95 @@
1
+
2
+ module Rubber
3
+ def generate_extconf(scanner, io)
4
+ if true
5
+ io.puts "require 'mkmf'"
6
+ io.puts "require 'mkmf-gnome2'" if scanner.pkgs
7
+ #io.puts "$defs ||= []"
8
+
9
+ if scanner.inc_dirs
10
+ io.puts "$CFLAGS += "+scanner.inc_dirs.collect { |i| " '-I#{i}'"}.join().inspect
11
+ end
12
+ if scanner.lib_dirs
13
+ io.puts "$LDFLAGS += "+scanner.lib_dirs.collect { |i| " '-L#{i}'"}.join().inspect
14
+ end
15
+ if scanner.defs
16
+ io.puts "$CFLAGS += "+scanner.defs.collect { |i| " '-D#{i}'"}.join().inspect
17
+ end
18
+ scanner.pkgs.each { |pkg| io.puts "PKGConfig.have_package(#{pkg.inspect}) or exit(-1)" } if scanner.pkgs
19
+
20
+ if scanner.incs
21
+ scanner.incs.each { |i| io.puts "have_header(#{i.inspect}) or exit(-1)"}
22
+ end
23
+ if scanner.libs
24
+ scanner.libs.each { |i| io.puts "have_library(#{i.inspect}) or exit(-1)\n$LIBS += \" -l#{i}\""}
25
+ end
26
+ io.write <<-EOB
27
+
28
+ STDOUT.print("checking for new allocation framework... ") # for ruby-1.7
29
+ if Object.respond_to? :allocate
30
+ STDOUT.print "yes\n"
31
+ $defs << "-DHAVE_OBJECT_ALLOCATE"
32
+ else
33
+ STDOUT.print "no\n"
34
+ end
35
+
36
+ top = File.expand_path(File.dirname(__FILE__) + '/..') # XXX
37
+ $CFLAGS += " " + ['glib/src'].map{|d|
38
+ "-I" + File.join(top, d)
39
+ }.join(" ")
40
+
41
+ have_func("rb_define_alloc_func") # for ruby-1.8
42
+
43
+ #set_output_lib('libruby-#{scanner.ext}.a')
44
+ if /cygwin|mingw/ =~ RUBY_PLATFORM
45
+ top = "../.."
46
+ [
47
+ ["glib/src", "ruby-glib2"],
48
+ ].each{|d,l|
49
+ $LDFLAGS << sprintf(" -L%s/%s", top, d)
50
+ $libs << sprintf(" -l%s", l)
51
+ }
52
+ end
53
+ begin
54
+ srcdir = File.expand_path(File.dirname($0))
55
+
56
+ begin
57
+
58
+ obj_ext = "."+$OBJEXT
59
+
60
+ $libs = $libs.split(/\s/).uniq.join(' ')
61
+ $source_files = Dir.glob(sprintf("%s/*.c", srcdir)).map{|fname|
62
+ fname[0, srcdir.length+1] = ''
63
+ fname
64
+ }
65
+ $objs = $source_files.collect do |item|
66
+ item.gsub(/\.c$/, obj_ext)
67
+ end
68
+
69
+ #
70
+ # create Makefile
71
+ #
72
+ $defs << "-DRUBY_#{scanner.ext.upcase}_COMPILATION"
73
+ # $CFLAGS << $defs.join(' ')
74
+ create_makefile(#{scanner.ext.inspect}, srcdir)
75
+ raise Interrupt if not FileTest.exist? "Makefile"
76
+
77
+ File.open("Makefile", "a") do |mfile|
78
+ $source_files.each do |e|
79
+ mfile.print sprintf("%s: %s\n", e.gsub(/\.c$/, obj_ext), e)
80
+ end
81
+ end
82
+ ensure
83
+ #Dir.chdir ".."
84
+ end
85
+
86
+ #create_top_makefile()
87
+ rescue Interrupt
88
+ print " [error] " + $!.to_s + "\n"
89
+ end
90
+
91
+ EOB
92
+ end
93
+ end
94
+ module_function :generate_extconf
95
+ end
@@ -0,0 +1,419 @@
1
+ require 'rubber/struct'
2
+ module Rubber
3
+ class ScanState
4
+ define_members(:in_code, :in_class, :in_func, :braces)
5
+ end
6
+
7
+ class Options
8
+ attr_accessor :gtk, :glib, :gnu
9
+ alias :gtk? :gtk
10
+ alias :glib? :glib
11
+ def []=(name,val)
12
+ instance_variable_set("@"+name,val)
13
+ end
14
+ def [](name)
15
+ instance_variable_get("@"+name)
16
+ end
17
+ end
18
+
19
+ class CRScanner
20
+ attr_reader :file, :functions, :nested_functions, :classes, :calls, :allocs, :stack, :ext, :pkgs, :incs, :doc, :raw, :libs, :defs, :pre_init_code, :post_init_code, :inc_dirs, :lib_dirs
21
+ attr_reader :options
22
+ def initialize(file)
23
+ @file = file
24
+ @ext = File::basename(file).gsub(/\..*$/, '')
25
+ @nested_functions = {}
26
+ @functions = {}
27
+ @modules = {}
28
+ @classes = {}
29
+ @calls = []
30
+ @allocs = []
31
+ @options = Options.new
32
+ # Default settings
33
+ @options.glib= true
34
+ @options.gtk= true
35
+ @options.gnu= false
36
+ end
37
+ def scan_args()
38
+ args = []
39
+ return args unless @str.peep(1) == '('
40
+ brackets = 1
41
+ arg = ''
42
+ @str.get_byte # Get first bracket
43
+ until @str.peep(1) == ')' and brackets == 1
44
+ brackets += 1 if @str.peep(1) == '('
45
+ brackets -= 1 if @str.peep(1) == ')'
46
+ if brackets == 1 and @str.peep(1) == ','
47
+ @str.pos = @str.pos + 1
48
+ arg.strip!
49
+ args.push arg unless arg.empty?
50
+ arg = ''
51
+ else
52
+ arg += @str.get_byte
53
+ end
54
+ end
55
+ @str.get_byte # Get last bracket
56
+ arg.strip!
57
+ args.push arg unless arg.empty?
58
+ args
59
+ end
60
+ def stack()
61
+ #p @stack
62
+ @stack
63
+ end
64
+ attr_accessor :state
65
+ def scan(fp)
66
+ _scan(fp)
67
+ rescue Exception
68
+ off,ind = 0,0
69
+ for line in @lines
70
+ off += line.size
71
+ break if off > @str.pos
72
+ ind += 1
73
+ end
74
+ p @state, @str, ind
75
+ raise
76
+ end
77
+ def _scan(fp)
78
+ @lines = IO.readlines(@file)
79
+ @str = StringScanner.new(@lines.join)
80
+ tokens = []
81
+ @state = ScanState.new(0,0,false,0)
82
+ @stack = [C_RootModule.new]
83
+ func = nil
84
+ until @str.empty?
85
+ ######## Doc
86
+ if @str.skip(/=begin([ \t][^\n]*)?\n/) # skip =begin/=end blocks
87
+ lines = @str.scan_until(/\n=end([ \t].*)?/).split("\n")
88
+ lines.pop
89
+ if state.in_func
90
+ (func.doc ||= "") << lines.join("\n")
91
+ elsif @class and not @class.kind_of?(C_RootModule)
92
+ (@class.doc ||= "") << lines.join("\n")
93
+ else
94
+ (@doc ||= "") << lines.join("\n")
95
+ end
96
+
97
+ ######## Config
98
+
99
+ elsif @str.skip(/%\{/) # Scan raw
100
+ raw = @str.scan_until(/%\}/)
101
+ raw[-2..-1] = ""
102
+ (@raw ||= "") << raw
103
+ elsif @str.skip(/%pre_init\{/) # Scan raw
104
+ raw = @str.scan_until(/%\}/)
105
+ raw[-2..-1] = ""
106
+ (@pre_init_code ||= "") << raw
107
+ elsif @str.skip(/%post_init\{/) # Scan raw
108
+ raw = @str.scan_until(/%\}/)
109
+ raw[-2..-1] = ""
110
+ (@post_init_code ||= "") << raw
111
+ elsif @str.skip(/\s+/) # skip
112
+ func.text += " " if state.in_func
113
+ elsif @str.skip(/%name */) # Extension name
114
+ @ext = @str.scan(/[a-zA-Z0-9]+/)
115
+ elsif @str.skip(/%pkg-config\s*([-a-z.0-9+]+)/) # pkg-config library
116
+ @pkgs ||= []
117
+ @pkgs << @str[1]
118
+ elsif @str.skip(/%include_dir\s+(.+)\n/) # Include dirs
119
+ @inc_dirs ||= []
120
+ @inc_dirs << @str[1].strip
121
+ elsif @str.skip(/%lib_dir\s+(.+)\n/) # Library dir
122
+ @lib_dirs ||= []
123
+ @lib_dirs << @str[1].strip
124
+ elsif @str.skip(/%include\s+(.+)\n/) # Include file
125
+ @incs ||= []
126
+ @incs << @str[1].strip
127
+ elsif @str.skip(/%option +([a-z]+)=(yes|no)\n/) # Option
128
+ case @str[1]
129
+ when 'glib','gtk','gnu'
130
+ @options[@str[1]] = (@str[2] == 'yes')
131
+ else
132
+ raise "Unknown option #{@str[1]}"
133
+ end
134
+ elsif @str.skip(/%lib\s+(.+)\n/) # Skip single-line comment
135
+ @libs ||= []
136
+ @libs << @str[1].strip
137
+ elsif @str.skip(/%define\s+(.+)\n/) # Skip single-line comment
138
+ @defs ||= []
139
+ @defs << @str[1].strip
140
+ elsif @str.skip(/%equiv[a-z]*\s+([^=\n]+)=([^=\n]+)\n/) # Skip single-line comment
141
+ $equivalents[@str[1].gsub(/ /,'').strip] = @str[2].gsub(/ /,'').strip
142
+ elsif @str.skip(/%map\s+([^->]+?)\>([^:]+):([^@\n]+) *@? *(.*)\n/) # Skip single-line comment
143
+ from, to, code = *[@str[1], @str[2], @str[3]].collect { |i| i.strip }
144
+ free_code = @str[4]
145
+ from.gsub!(/ /,'')
146
+ to.gsub!(/ /,'')
147
+ puts "Mapping #{from} -> #{to}"
148
+ ($custom_maps[from] ||= {})[to] = code
149
+ $custom_frees[to] = free_code
150
+ elsif state.in_class > 0 and state.in_func == false and @str.skip(/%flag\s+([a-z0-9_A-Z]+)/)
151
+ flag = ("flag_"+@str[1]+"=").intern
152
+ if stack.last.respond_to?(flag)
153
+ stack.last.__send__(flag, true)
154
+ else
155
+ raise "%flags directive cannot be used here (#{stack.last.class} doesn't respond to #{flag})"
156
+ end
157
+ elsif state.in_class > 0 and state.in_func == false and @str.skip(/%feature\s+([a-z0-9_A-Z]+)/)
158
+ flag = ("feature_"+@str[1]).intern
159
+ @str.skip(/\s+/)
160
+ args = []
161
+ if @str.skip(/\(/)
162
+ args = @str.scan_until(/\)/)[0..-2].split(/, */).map { |i| i.strip }
163
+ end
164
+ @str.skip(/;/)
165
+ if stack.last.respond_to?(flag)
166
+ stack.last.__send__(flag, *args)
167
+ else
168
+ raise "%feature '#{@str[1]}' directive cannot be used here (#{stack.last.class} doesn't support it)"
169
+ end
170
+ elsif @str.skip(/%/) # Skip single-line comment
171
+ @str.skip_until(/\n/)
172
+
173
+
174
+ ####### Comments
175
+
176
+ elsif state.in_func == false and @str.skip(/#.*/) # Comment
177
+
178
+ elsif state.in_func == false and @str.skip(/\/\/.*/) # Comment
179
+
180
+ elsif state.in_func == false and @str.skip(/\/\*(.|\n)*\*\//) # Multi-line Comment
181
+
182
+
183
+
184
+ ####### Code
185
+
186
+ elsif txt = @str.scan(/['"]/) #' Skip quoted string
187
+ txt += @str.scan_until(/(^|[^\\])#{txt}/) # Skip until unescaped quote
188
+ func.text += txt if state.in_func
189
+ elsif state.in_func == false and @str.skip(/module(?= )/x) # Module defn
190
+ @str.skip(/\s+/)
191
+ name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
192
+ @classes[name] = C_Module.new(name, [], [], [])
193
+ @classes[name].parent = stack.last
194
+ stack.last.classes.push(@classes[name])
195
+ stack.push(@class = @classes[name])
196
+ puts "module "+ @class.fullname + "-#{@class.name}"
197
+ state.in_class += 1
198
+ elsif state.in_func == false and @str.skip(/class(?= )/x) # Class defn
199
+ @str.skip(/\s+/)
200
+ name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
201
+ superclass = nil
202
+ @str.skip(/\s*/)
203
+ if @str.skip(/</)
204
+ @str.skip(/\s*/)
205
+ superclass = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
206
+ end
207
+ @classes[name] = C_Class.new(name, superclass, [], [], [])
208
+ @classes[name].parent = stack.last
209
+ stack.last.classes.push(@classes[name])
210
+ stack.push(@class = @classes[name])
211
+ puts "class "+ @class.fullname
212
+ state.in_class += 1
213
+
214
+ elsif state.in_func == false and @str.skip(/struct(?= )/x) # Ruby Struct
215
+ @str.skip(/\s+/)
216
+ name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
217
+ @str.skip(/\s+/)
218
+ if @str.skip(/\(/)
219
+ args = @str.scan_until(/\)/)[0..-2].split(/, */).collect { |i| i.strip }
220
+ end
221
+ # NB. struct Name(arg0...argN)
222
+ if @str.skip(/\s*;/)
223
+ stack.last.classes.push(C_Struct.new(name, args, stack.last))
224
+ else
225
+ @classes[name] = C_Struct.new(name, args, stack.last)
226
+ stack.last.classes.push(@classes[name])
227
+ stack.push(@class = @classes[name])
228
+ puts "struct "+ @class.fullname
229
+ state.in_class += 1
230
+ end
231
+ elsif state.in_func == false and @str.skip(/gcpool(?= )/x) # GC Pool
232
+ @str.skip(/\s+/)
233
+ name = @str.scan(/[a-z_0-9A-Z]*/)
234
+ puts "GCPool #{name}"
235
+ stack.first.classes.push(C_GCRefPool.new(name))
236
+
237
+ elsif state.in_func == false and @str.skip(/(enum)(?= )/x) # C Enum as module wrapper
238
+ what = @str[1]
239
+ @str.skip(/\s+/)
240
+ name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
241
+ @str.skip(/\s+/)
242
+ if @str.skip(/\(/)
243
+ args = @str.scan_until(/\)/)[0..-2].split(/, */).collect { |i| i.strip }
244
+ end
245
+ if what == "flags"
246
+ stack.last.classes.push(C_Flags.new(name, args, stack.last))
247
+ else
248
+ stack.last.classes.push(C_Enum.new(name, args, stack.last))
249
+ end
250
+
251
+ elsif state.in_func == false and @str.skip(/(genum|gflags)(?= )/x) # C GEnum as module wrapper
252
+ what = @str[1]
253
+ @str.skip(/\s+/)
254
+ name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
255
+ @str.skip(/\s+/)
256
+ g_type = @str.scan(/[A-Z][_0-9A-Z]*/)
257
+ @str.skip(/\s+/)
258
+ prefix = @str.scan(/[A-Z][_0-9A-Z]*/)
259
+ @str.skip(/\s*;/)
260
+ if what == "gflags"
261
+ stack.last.classes.push(C_GFlags.new(name, g_type, prefix, stack.last))
262
+ else
263
+ stack.last.classes.push(C_GEnum.new(name, g_type, prefix, stack.last))
264
+ end
265
+
266
+ elsif state.in_func == false and @str.skip(/(gobject|ginterface|gboxed)(?= )/x) # Class defn
267
+ type=@str[1]
268
+ @str.skip(/\s+/)
269
+ name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
270
+ superclass = nil
271
+ @str.skip(/\s*/)
272
+ if @str.skip(/\</)
273
+ @str.skip(/\s*/)
274
+ gtype = @str.scan(/[A-Z_]+/)
275
+ end
276
+ @str.skip(/\s*/)
277
+ if @str.skip(/:/)
278
+ @str.skip(/\s*/)
279
+ gparent_class = @str.scan(/[A-Z_:a-z0-9]+/)
280
+ end
281
+ case type
282
+ when "gobject"
283
+ @classes[name] = C_GObject.new(name, gtype, [], [], [])
284
+ when "ginterface"
285
+ @classes[name] = C_GInterface.new(name, gtype, [], [], [])
286
+ when "gboxed"
287
+ @classes[name] = C_GBoxed.new(name, gtype, [], [], [])
288
+ else
289
+ raise "#{name} is not a GObject or GInterface..."
290
+ end
291
+ @classes[name].gparent_class = gparent_class
292
+ @classes[name].parent = stack.last
293
+ stack.last.classes.push(@classes[name])
294
+ stack.push(@class = @classes[name])
295
+ puts "class "+ @class.fullname
296
+ state.in_class += 1
297
+ elsif @str.scan(/@type\s+([A-Za-z_0-9]+)/)
298
+ type = @str[1]
299
+ prev = stack.last
300
+ if prev.is_a?(C_GObject)
301
+ # p c_type, self
302
+ puts "Converting #{type}* to & from VALUE"
303
+ prev.c_type_name = type
304
+ ($custom_maps[type+'*'] ||= {})["VALUE"] = "GOBJ2RVAL(%%)"
305
+ ($custom_maps["VALUE"] ||= {})[type+'*'] = "RVAL2GOBJ(%%)"
306
+ elsif prev.is_a?(C_GBoxed)
307
+ prev.c_type_name = type
308
+
309
+ ($custom_maps[type+'*'] ||= {})["VALUE"] = "BOXED2RVAL(%%, #{prev.superclass})"
310
+ ($custom_maps["VALUE"] ||= {})[type+'*'] = "RVAL2BOXED(%%, #{prev.superclass})"
311
+ else
312
+ # Invalid type directive
313
+ end
314
+ elsif @str.skip(/end(?=\s)/x)
315
+ last = stack.pop
316
+ puts "#{last.class} - #{last.name}"
317
+ case last
318
+ when C_Module, C_Class, C_Enum, C_Flags, C_Struct, C_GObject, C_GInterface, C_GBoxed
319
+ state.in_class -= 1
320
+ @class = stack.last
321
+ when C_Function
322
+ state.in_func = false
323
+ else
324
+ STDERR.puts "Remaining code: #{@str.rest}"
325
+ STDERR.puts "Defined Classes: #{@classes.keys.join(', ')}"
326
+ p stack
327
+ raise "Invalid stack entry #{last.class}"
328
+ end
329
+ elsif @str.skip(/alias\s+:([A-Za-z0-9_]*[\[\]]{0,2}[?!=]?)\s+:([A-Za-z0-9_]*[\[\]]{0,2}[?!=]?)/) # Alias
330
+ @class.add_alias(@str[1], @str[2]) if @class.respond_to?(:add_alias)
331
+ elsif @str.skip(/(pre|post)_func\s+do/)
332
+ where = @str[1]
333
+ str = @str.scan_until(/\bend/)#[0,-4]
334
+ unless str
335
+ raise "Invalid #{where}_func definition: #{@str.peek(200).inspect}"
336
+ end
337
+ str = str[0..-4].strip
338
+ except = only = nil
339
+ @str.skip(/\s*/)
340
+ if @str.skip(/,\s*:(only|except)\s*=\>\s*(\[[^\]]+\])/)
341
+ if @str[1] == 'only'
342
+ only = eval(@str[2]).map{|i|i.to_s}
343
+ else
344
+ except = eval(@str[2]).map{|i|i.to_s}
345
+ end
346
+ end
347
+ if where == 'pre'
348
+ @class.pre_func = str
349
+ @class.pre_only = only if only
350
+ @class.pre_except = except if except
351
+ else
352
+ @class.post_func = str
353
+ @class.post_only = only if only
354
+ @class.post_except = except if except
355
+ end
356
+ elsif @str.skip(/pre_func\s+(.*)/) # Pre func code
357
+ @class.pre_func= @str[1] if @class.respond_to?(:pre_func)
358
+ elsif @str.skip(/post_func\s+(.*)/) # Post func code
359
+ @class.post_func= @str[1] if @class.respond_to?(:post_func)
360
+ elsif @str.skip(/def(?=\s+)/x) # Function defn
361
+ @str.skip(/\s+/)
362
+ if @str.scan(/([a-zA-Z_* ]+):/)
363
+ returntype = @str[1]
364
+ else
365
+ returntype = 'VALUE'
366
+ end
367
+ prename = ''
368
+ prename = @str.scan(/self\./)
369
+ name = @str.scan(/[a-z_0-9A-Z.]+[?!=]?/)
370
+ unless name
371
+ name = @str.scan(/[-\[\]<>~=+|&]{1,3}/)
372
+ end
373
+ name = prename.to_s + (oname=name)
374
+ #p [prename, oname, name]
375
+ @str.skip(/\s*/)
376
+ args = scan_args().collect { |i| C_Param.new(i) }
377
+ func = @functions[name] = C_Function.new(name, args, '')
378
+ func.returntype = returntype
379
+ func.parent = @class
380
+ stack.last.functions.push(func)
381
+ puts "def "+ func.fullname
382
+ stack.push(func)
383
+ state.in_func = true
384
+
385
+ elsif state.in_func == false and @str.skip(/(string|integer|float|double|int)(?= )/x) # C String as module wrapper
386
+ type= @str[1]
387
+ @str.skip(/\s+/)
388
+ name = @str.scan(/[A-Z][a-z_0-9A-Z]*/)
389
+ @str.skip(/\s*=\s*/)
390
+ if @str.skip(/"/) #"
391
+ string = '"' + @str.scan_until(/[^\\]?"/) #"
392
+ elsif t = @str.scan(/([A-Z][a-z_0-9A-Z]*)/)
393
+ string = @str[1]
394
+ elsif type =~ /^(flo|dou|int)/ and t = @str.scan(/([0-9]+(\.[0-9]+)?(e[0-9]+)?)/)
395
+ string = @str[1]
396
+ end
397
+ klass = nil
398
+ case type
399
+ when /^str/
400
+ klass = C_String
401
+ when /^int/
402
+ klass = C_Integer
403
+ when /^(flo|dou)/
404
+ klass = C_Float
405
+ end
406
+ stack.last.classes.push(klass.new(name, string, stack.last)) if klass
407
+
408
+ elsif txt = @str.get_byte # Spare chars
409
+ if state.in_func
410
+ func.text += txt
411
+ else
412
+ puts '"' << txt << '"'
413
+ end
414
+ end
415
+ end
416
+ end
417
+ end
418
+
419
+ end # m Rubber