rubber-generate 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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