grammar 0.8 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/benchmark/json.benchmark.rb +94 -104
- data/benchmark/json.racc.rb +268 -0
- data/lib/grammar/ruby.rb +76 -38
- data/lib/grammar/ruby2cext.rb +3 -2
- data/lib/grammar/ruby2cext_hack.rb +319 -0
- data/lib/grammar/rubycall.rb +2 -2
- metadata +4 -2
data/benchmark/json.benchmark.rb
CHANGED
@@ -6,25 +6,45 @@ require 'rubygems'
|
|
6
6
|
|
7
7
|
class JSON_Generator
|
8
8
|
attr_accessor(:array, :object)
|
9
|
+
def convert(obj)
|
10
|
+
obj.inspect.gsub(/=>/, ':').gsub(/\bnil\b/, 'null')
|
11
|
+
end
|
9
12
|
def initialize
|
10
13
|
@string1 = '1'
|
14
|
+
@string1s = @string1.inspect
|
11
15
|
@string2 = '2'
|
16
|
+
@string2s = @string2.inspect
|
12
17
|
@array1 = ['abc : 123', {}, false]
|
13
|
-
@array2 = [1.234e-5, {@string2 => nil},
|
18
|
+
@array2 = [1.234e-5, {@string2 => nil}, ""]
|
14
19
|
@object1 = {@string1 => '\\\n\t', @string2 => true}
|
15
20
|
@object2 = {@string2 => -789, @string2 => []}
|
21
|
+
@array1s = @array1.map { |obj| convert(obj) }
|
22
|
+
@array2s = @array2.map { |obj| convert(obj) }
|
23
|
+
@object1s = @object1.map { |k,v| "#{convert(k)}:#{convert(v)}" }
|
24
|
+
@object2s = @object2.map { |k,v| "#{convert(k)}:#{convert(v)}" }
|
16
25
|
end
|
17
26
|
def grow
|
18
27
|
@array1,
|
19
28
|
@array2,
|
20
|
-
@
|
21
|
-
@
|
29
|
+
@object2,
|
30
|
+
@object1 =
|
22
31
|
@array1.reverse << @object2,
|
23
32
|
@array2.reverse.concat(@array1),
|
24
|
-
@
|
25
|
-
@
|
33
|
+
@object2.merge(@object1),
|
34
|
+
@object1.merge!({@string1 => @array2})
|
35
|
+
@array1s,
|
36
|
+
@array2s,
|
37
|
+
@object2s,
|
38
|
+
@object1s =
|
39
|
+
@array1s.reverse << "{#{@object2s.join(', ')}}",
|
40
|
+
@array2s.reverse.concat(@array1s),
|
41
|
+
@object2s.concat(@object1s),
|
42
|
+
@object1s << "#{@string1s}:[#{@array2s.join(', ')}]"
|
26
43
|
@array2
|
27
44
|
end
|
45
|
+
def to_s
|
46
|
+
"[#{@array2s.join(', ')}]"
|
47
|
+
end
|
28
48
|
end
|
29
49
|
|
30
50
|
def filesize(filename)
|
@@ -52,9 +72,6 @@ def benchmark(label='', filename=nil)
|
|
52
72
|
load_path = $LOAD_PATH.clone
|
53
73
|
loaded_features = $LOADED_FEATURES.clone
|
54
74
|
!ARGV[0] or Regexp.new(ARGV[0])=~label or return
|
55
|
-
make = yield
|
56
|
-
limit = (ARGV[1]||1).to_f
|
57
|
-
max_tries = 4
|
58
75
|
unless label.empty?
|
59
76
|
STDERR.print(label)
|
60
77
|
if filename
|
@@ -63,6 +80,9 @@ def benchmark(label='', filename=nil)
|
|
63
80
|
STDERR.print(" -")
|
64
81
|
end
|
65
82
|
end
|
83
|
+
run = yield
|
84
|
+
limit = (ARGV[1]||1).to_f
|
85
|
+
max_tries = 4
|
66
86
|
bandwidth = nil
|
67
87
|
generator = JSON_Generator.new
|
68
88
|
tree0 = nil
|
@@ -70,39 +90,38 @@ def benchmark(label='', filename=nil)
|
|
70
90
|
tree = nil
|
71
91
|
tries = 0
|
72
92
|
done = false
|
93
|
+
t0 = nil
|
94
|
+
n = 1
|
73
95
|
begin
|
74
96
|
GC.start
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
97
|
+
if tries>0
|
98
|
+
tries += 1
|
99
|
+
elsif t0 && t0>limit
|
100
|
+
n *= 2
|
101
|
+
else
|
102
|
+
tms = Benchmark.measure {
|
79
103
|
tree0 = generator.grow
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
s.gsub!(/nil/, 'null')
|
84
|
-
}
|
85
|
-
if !make
|
86
|
-
return if tms.utime+tms.stime>limit
|
87
|
-
next
|
104
|
+
s = generator.to_s
|
105
|
+
}
|
106
|
+
t0 = tms.utime+tms.stime
|
88
107
|
end
|
89
108
|
#puts s
|
90
|
-
run = make[s]
|
91
109
|
GC.start
|
92
110
|
GC.start
|
93
|
-
tms = Benchmark.measure { tree = run[] }
|
111
|
+
tms = Benchmark.measure { n.times { tree = run[s] } }
|
94
112
|
GC.start
|
95
|
-
raise("#{tree.inspect}!=#{tree0.inspect}") if tree!=tree0
|
113
|
+
raise("#{tree.inspect}!=#{tree0.inspect}") if tree && tree!=tree0
|
96
114
|
tree = nil
|
97
115
|
t = tms.utime+tms.stime
|
98
|
-
bandwidth = s.length/t
|
99
|
-
s = nil
|
100
|
-
GC.start
|
116
|
+
bandwidth = (n*s.length)/t
|
101
117
|
if tries.zero?
|
102
118
|
if t>limit
|
103
119
|
tries = 1
|
120
|
+
GC.start
|
104
121
|
else
|
105
|
-
|
122
|
+
s = nil unless t0>limit
|
123
|
+
GC.start
|
124
|
+
next
|
106
125
|
end
|
107
126
|
end
|
108
127
|
if bandwidth>=1e9
|
@@ -122,11 +141,11 @@ def benchmark(label='', filename=nil)
|
|
122
141
|
end until tries>=max_tries
|
123
142
|
STDERR.print("\n")
|
124
143
|
return bandwidth
|
125
|
-
rescue => error
|
126
|
-
|
144
|
+
rescue ScriptError,StandardError => error
|
145
|
+
puts(" #{error}")
|
127
146
|
ensure
|
128
|
-
|
129
|
-
|
147
|
+
begin;Gem.clear_paths;rescue Exception;end
|
148
|
+
begin;Gem.loaded_specs.clear;rescue Exception;end
|
130
149
|
self.class.constants.each { |constant|
|
131
150
|
next if constants[constant]
|
132
151
|
#puts("removing #{constant}")
|
@@ -142,32 +161,47 @@ require 'stringio'
|
|
142
161
|
json_pure = '/var/lib/gems/1.8/gems/json-1.1.2/lib/json/pure/parser.rb'
|
143
162
|
json_ext = '/var/lib/gems/1.8/gems/json-1.1.2/ext/json/ext/parser/parser.rl'
|
144
163
|
|
145
|
-
benchmark('') {
|
164
|
+
benchmark('String#index') {
|
165
|
+
lambda { |s|
|
166
|
+
s.index(?\0)
|
167
|
+
nil
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
benchmark('String#each_byte') {
|
172
|
+
lambda { |s|
|
173
|
+
s.each_byte{}
|
174
|
+
nil
|
175
|
+
}
|
176
|
+
}
|
146
177
|
|
147
|
-
benchmark('
|
178
|
+
benchmark('StringIO#getc') {
|
179
|
+
lambda { |s|
|
180
|
+
i = StringIO.new(s)
|
181
|
+
while i.getc;end
|
182
|
+
nil
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
benchmark('Ragel/C(json/ext)', json_ext) {
|
148
187
|
gem 'json'
|
149
188
|
require 'json/ext'
|
150
189
|
lambda { |s|
|
151
|
-
JSON::Ext::Parser.new(s).
|
190
|
+
JSON::Ext::Parser.new(s).parse
|
152
191
|
}
|
153
192
|
}
|
154
193
|
|
155
194
|
benchmark('Grammar/Ruby2CExt', 'json.grammar.rb') {
|
156
195
|
$LOAD_PATH << '../lib'
|
157
|
-
require '
|
196
|
+
require 'grammar'
|
158
197
|
grammar = Grammar.new.instance_eval(IO.read('json.grammar.rb'))
|
159
198
|
Kernel.module_eval { alias_method(:_warn, :warn) }
|
160
199
|
Kernel.module_eval { def warn(*);end }
|
161
200
|
require 'grammar/ruby2cext'
|
162
201
|
Kernel.module_eval { alias_method(:warn, :_warn) }
|
163
|
-
grammar_ruby2cext = Grammar::Ruby2CExt.compile(grammar)
|
202
|
+
grammar_ruby2cext = Grammar::Ruby2CExt.compile(grammar, :getc)
|
164
203
|
lambda { |s|
|
165
|
-
|
166
|
-
out = []
|
167
|
-
lambda {
|
168
|
-
grammar_ruby2cext[out, i]
|
169
|
-
out[0]
|
170
|
-
}
|
204
|
+
grammar_ruby2cext[out=[], StringIO.new(s)] && out[0]
|
171
205
|
}
|
172
206
|
}
|
173
207
|
|
@@ -175,10 +209,7 @@ benchmark('hand/RE', 'json.re.rb') {
|
|
175
209
|
load 'json.re.rb'
|
176
210
|
re = JSON.new
|
177
211
|
lambda { |s|
|
178
|
-
|
179
|
-
lambda {
|
180
|
-
re.parse(i)
|
181
|
-
}
|
212
|
+
re.parse(StringScanner.new(s))
|
182
213
|
}
|
183
214
|
}
|
184
215
|
|
@@ -186,26 +217,19 @@ benchmark('hand/LL1', 'json.ll1.rb') {
|
|
186
217
|
load 'json.ll1.rb'
|
187
218
|
ll1 = JSON.new
|
188
219
|
lambda { |s|
|
189
|
-
|
190
|
-
lambda {
|
191
|
-
ll1.parse(i)
|
192
|
-
}
|
220
|
+
ll1.parse(StringIO.new(s))
|
193
221
|
}
|
194
222
|
}
|
195
223
|
|
196
224
|
benchmark('Grammar/Ruby', 'json.grammar.rb') {
|
197
225
|
$LOAD_PATH << '../lib'
|
198
|
-
require '
|
226
|
+
require 'grammar'
|
199
227
|
grammar = Grammar.new.instance_eval(IO.read('json.grammar.rb'))
|
200
228
|
require 'grammar/ruby'
|
201
|
-
grammar_ruby = Grammar::Ruby.compile(grammar)
|
229
|
+
grammar_ruby = Grammar::Ruby.compile(grammar, :getc)
|
202
230
|
lambda { |s|
|
203
|
-
|
204
|
-
out
|
205
|
-
lambda {
|
206
|
-
grammar_ruby[out, i]
|
207
|
-
out[0]
|
208
|
-
}
|
231
|
+
grammar_ruby[out=[], StringIO.new(s)] && out[0]
|
232
|
+
out[0]
|
209
233
|
}
|
210
234
|
}
|
211
235
|
|
@@ -222,10 +246,7 @@ benchmark('RACC/ext', 'json.y') {
|
|
222
246
|
}
|
223
247
|
racc = JSON.new
|
224
248
|
lambda { |s|
|
225
|
-
|
226
|
-
lambda {
|
227
|
-
racc.parse(i)
|
228
|
-
}
|
249
|
+
racc.parse(StringScanner.new(s))
|
229
250
|
}
|
230
251
|
}
|
231
252
|
|
@@ -233,7 +254,7 @@ benchmark('json/pure', json_pure) {
|
|
233
254
|
gem 'json'
|
234
255
|
require 'json/pure'
|
235
256
|
lambda { |s|
|
236
|
-
JSON::Pure::Parser.new(s).
|
257
|
+
JSON::Pure::Parser.new(s).parse
|
237
258
|
}
|
238
259
|
}
|
239
260
|
|
@@ -242,19 +263,14 @@ benchmark('Grammar/RubyCall', 'json.grammar.rb') {
|
|
242
263
|
require '../lib/grammar'
|
243
264
|
grammar = Grammar.new.instance_eval(IO.read('json.grammar.rb'))
|
244
265
|
require 'grammar/rubycall'
|
245
|
-
grammar_ruby = Grammar::RubyCall.compile(grammar)
|
266
|
+
grammar_ruby = Grammar::RubyCall.compile(grammar, :getc)
|
246
267
|
lambda { |s|
|
247
|
-
|
248
|
-
out = []
|
249
|
-
lambda {
|
250
|
-
grammar_ruby[out, i]
|
251
|
-
out[0]
|
252
|
-
}
|
268
|
+
grammar_ruby[out=[], StringIO.new(s)] && out[0]
|
253
269
|
}
|
254
270
|
}
|
255
271
|
|
256
272
|
benchmark('Grammar/0.5', 'json.grammar0_5.rb') {
|
257
|
-
gem 'grammar'
|
273
|
+
gem 'grammar', '0.5'
|
258
274
|
require 'grammar'
|
259
275
|
require 'duck'
|
260
276
|
require 'json.grammar0_5'
|
@@ -262,11 +278,7 @@ benchmark('Grammar/0.5', 'json.grammar0_5.rb') {
|
|
262
278
|
require 'cursor/io'
|
263
279
|
grammar0_5 = JSON.new
|
264
280
|
lambda { |s|
|
265
|
-
|
266
|
-
lambda {
|
267
|
-
grammar0_5.scan(i, out=[])
|
268
|
-
out[0]
|
269
|
-
}
|
281
|
+
grammar0_5.scan(Cursor::IO.new(StringIO.new(s)), out=[]) && out[0]
|
270
282
|
}
|
271
283
|
}
|
272
284
|
|
@@ -283,10 +295,7 @@ benchmark('RACC/ruby', 'json.y') {
|
|
283
295
|
}
|
284
296
|
racc = JSON.new
|
285
297
|
lambda { |s|
|
286
|
-
|
287
|
-
lambda {
|
288
|
-
racc.parse(i)
|
289
|
-
}
|
298
|
+
racc.parse(StringScanner.new(s))
|
290
299
|
}
|
291
300
|
}
|
292
301
|
|
@@ -296,9 +305,7 @@ benchmark('Treetop', 'json.treetop') {
|
|
296
305
|
Treetop.load('json.treetop')
|
297
306
|
treetop = JSONParser.new
|
298
307
|
lambda { |s|
|
299
|
-
|
300
|
-
treetop.parse(s).obj
|
301
|
-
}
|
308
|
+
treetop.parse(s).obj
|
302
309
|
}
|
303
310
|
}
|
304
311
|
|
@@ -307,9 +314,7 @@ benchmark('GhostWheel', 'json.ghostwheel') {
|
|
307
314
|
require 'ghost_wheel'
|
308
315
|
ghostwheel = GhostWheel.build_parser(IO.read("json.ghostwheel"))
|
309
316
|
lambda { |s|
|
310
|
-
|
311
|
-
ghostwheel.parse(s)
|
312
|
-
}
|
317
|
+
ghostwheel.parse(s)
|
313
318
|
}
|
314
319
|
}
|
315
320
|
|
@@ -320,12 +325,7 @@ benchmark('Grammar/Ruby0', 'json.grammar.rb') {
|
|
320
325
|
require 'grammar/ruby0'
|
321
326
|
grammar_ruby0 = Grammar::Ruby0.compile(grammar)
|
322
327
|
lambda { |s|
|
323
|
-
|
324
|
-
out = []
|
325
|
-
lambda {
|
326
|
-
grammar_ruby0[out, i]
|
327
|
-
out[0]
|
328
|
-
}
|
328
|
+
grammar_ruby0[out=[], StringIO.new(s).method(:getc)] && out[0]
|
329
329
|
}
|
330
330
|
}
|
331
331
|
|
@@ -337,18 +337,8 @@ benchmark('Peggy', 'json.peggy.rb') {
|
|
337
337
|
peggy = JSON.new
|
338
338
|
lambda { |s|
|
339
339
|
peggy.source_text = s
|
340
|
-
|
341
|
-
|
342
|
-
peggy.to_ruby
|
343
|
-
}
|
344
|
-
}
|
345
|
-
}
|
346
|
-
|
347
|
-
benchmark('json/ext', json_ext) {
|
348
|
-
gem 'json'
|
349
|
-
require 'json/ext'
|
350
|
-
lambda { |s|
|
351
|
-
JSON::Ext::Parser.new(s).method(:parse)
|
340
|
+
peggy.parse?(:value)
|
341
|
+
peggy.to_ruby
|
352
342
|
}
|
353
343
|
}
|
354
344
|
|
@@ -0,0 +1,268 @@
|
|
1
|
+
#
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by racc 1.4.5
|
4
|
+
# from racc grammer file "json.y".
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'racc/parser'
|
8
|
+
|
9
|
+
|
10
|
+
class JSON < Racc::Parser
|
11
|
+
|
12
|
+
module_eval <<'..end json.y modeval..idf8edf52a5d', 'json.y', 26
|
13
|
+
|
14
|
+
def parse(input)
|
15
|
+
@input = input
|
16
|
+
yyparse self, :scan
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def scan
|
22
|
+
input = @input
|
23
|
+
while true
|
24
|
+
if input.scan(/\s+/)
|
25
|
+
elsif input.scan(/"/)
|
26
|
+
s = ""
|
27
|
+
while true
|
28
|
+
if text=input.scan(/[^\\"]+/)
|
29
|
+
s.concat(text)
|
30
|
+
elsif input.scan(/\\/)
|
31
|
+
case (ch=input.getch[0])
|
32
|
+
when ?b ; s << ?\b
|
33
|
+
when ?f ; s << ?\f
|
34
|
+
when ?n ; s << ?\n
|
35
|
+
when ?r ; s << ?\r
|
36
|
+
when ?t ; s << ?\t
|
37
|
+
when ?u
|
38
|
+
text = input.scan(/[0-9a-fA-F]{4}/) or raise("expected hex*4")
|
39
|
+
s << text.to_i(16)
|
40
|
+
else
|
41
|
+
s << ch
|
42
|
+
end
|
43
|
+
else
|
44
|
+
break
|
45
|
+
end
|
46
|
+
end
|
47
|
+
input.scan(/"/) or raise("expected quote")
|
48
|
+
yield :STRING, s
|
49
|
+
elsif text=input.scan(/-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?\s*/)
|
50
|
+
yield :NUMBER, eval(text)
|
51
|
+
elsif text=input.scan(/true/)
|
52
|
+
yield :BOOLEAN, true
|
53
|
+
elsif text=input.scan(/false/)
|
54
|
+
yield :BOOLEAN, false
|
55
|
+
elsif text=input.scan(/null/)
|
56
|
+
yield :BOOLEAN, nil
|
57
|
+
elsif text=input.scan(/./)
|
58
|
+
yield text, text
|
59
|
+
else
|
60
|
+
break
|
61
|
+
end
|
62
|
+
end
|
63
|
+
yield false, '$'
|
64
|
+
end
|
65
|
+
|
66
|
+
..end json.y modeval..idf8edf52a5d
|
67
|
+
|
68
|
+
##### racc 1.4.5 generates ###
|
69
|
+
|
70
|
+
racc_reduce_table = [
|
71
|
+
0, 0, :racc_error,
|
72
|
+
1, 12, :_reduce_none,
|
73
|
+
1, 12, :_reduce_none,
|
74
|
+
1, 12, :_reduce_none,
|
75
|
+
1, 12, :_reduce_none,
|
76
|
+
1, 12, :_reduce_none,
|
77
|
+
3, 13, :_reduce_6,
|
78
|
+
2, 13, :_reduce_7,
|
79
|
+
3, 15, :_reduce_8,
|
80
|
+
5, 15, :_reduce_9,
|
81
|
+
3, 14, :_reduce_10,
|
82
|
+
2, 14, :_reduce_11,
|
83
|
+
1, 16, :_reduce_12,
|
84
|
+
3, 16, :_reduce_13 ]
|
85
|
+
|
86
|
+
racc_reduce_n = 14
|
87
|
+
|
88
|
+
racc_shift_n = 27
|
89
|
+
|
90
|
+
racc_action_table = [
|
91
|
+
3, 4, 6, 7, 18, 23, 19, 8, 15, 3,
|
92
|
+
4, 6, 7, 20, 16, 21, 8, 3, 4, 6,
|
93
|
+
7, 9, 25, 17, 8, 3, 4, 6, 7, nil,
|
94
|
+
nil, nil, 8, 3, 4, 6, 7, 10, nil, nil,
|
95
|
+
8, 12 ]
|
96
|
+
|
97
|
+
racc_action_check = [
|
98
|
+
8, 8, 8, 8, 11, 19, 11, 8, 8, 17,
|
99
|
+
17, 17, 17, 14, 9, 14, 17, 20, 20, 20,
|
100
|
+
20, 1, 23, 10, 20, 0, 0, 0, 0, nil,
|
101
|
+
nil, nil, 0, 25, 25, 25, 25, 7, nil, nil,
|
102
|
+
25, 7 ]
|
103
|
+
|
104
|
+
racc_action_pointer = [
|
105
|
+
23, 21, nil, nil, nil, nil, nil, 35, -2, 14,
|
106
|
+
16, -2, nil, nil, 5, nil, nil, 7, nil, 3,
|
107
|
+
15, nil, nil, 15, nil, 31, nil ]
|
108
|
+
|
109
|
+
racc_action_default = [
|
110
|
+
-14, -14, -2, -1, -4, -3, -5, -14, -14, -14,
|
111
|
+
-14, -14, -7, -12, -14, -11, 27, -14, -6, -14,
|
112
|
+
-14, -10, -8, -14, -13, -14, -9 ]
|
113
|
+
|
114
|
+
racc_goto_table = [
|
115
|
+
1, 11, 14, nil, nil, nil, nil, nil, 13, nil,
|
116
|
+
nil, nil, nil, nil, nil, nil, nil, 22, nil, nil,
|
117
|
+
24, nil, nil, nil, nil, 26 ]
|
118
|
+
|
119
|
+
racc_goto_check = [
|
120
|
+
1, 4, 5, nil, nil, nil, nil, nil, 1, nil,
|
121
|
+
nil, nil, nil, nil, nil, nil, nil, 1, nil, nil,
|
122
|
+
1, nil, nil, nil, nil, 1 ]
|
123
|
+
|
124
|
+
racc_goto_pointer = [
|
125
|
+
nil, 0, nil, nil, -6, -6 ]
|
126
|
+
|
127
|
+
racc_goto_default = [
|
128
|
+
nil, nil, 2, 5, nil, nil ]
|
129
|
+
|
130
|
+
racc_token_table = {
|
131
|
+
false => 0,
|
132
|
+
Object.new => 1,
|
133
|
+
:STRING => 2,
|
134
|
+
:BOOLEAN => 3,
|
135
|
+
:NUMBER => 4,
|
136
|
+
"{" => 5,
|
137
|
+
"}" => 6,
|
138
|
+
":" => 7,
|
139
|
+
"," => 8,
|
140
|
+
"[" => 9,
|
141
|
+
"]" => 10 }
|
142
|
+
|
143
|
+
racc_use_result_var = false
|
144
|
+
|
145
|
+
racc_nt_base = 11
|
146
|
+
|
147
|
+
Racc_arg = [
|
148
|
+
racc_action_table,
|
149
|
+
racc_action_check,
|
150
|
+
racc_action_default,
|
151
|
+
racc_action_pointer,
|
152
|
+
racc_goto_table,
|
153
|
+
racc_goto_check,
|
154
|
+
racc_goto_default,
|
155
|
+
racc_goto_pointer,
|
156
|
+
racc_nt_base,
|
157
|
+
racc_reduce_table,
|
158
|
+
racc_token_table,
|
159
|
+
racc_shift_n,
|
160
|
+
racc_reduce_n,
|
161
|
+
racc_use_result_var ]
|
162
|
+
|
163
|
+
Racc_token_to_s_table = [
|
164
|
+
'$end',
|
165
|
+
'error',
|
166
|
+
'STRING',
|
167
|
+
'BOOLEAN',
|
168
|
+
'NUMBER',
|
169
|
+
'"{"',
|
170
|
+
'"}"',
|
171
|
+
'":"',
|
172
|
+
'","',
|
173
|
+
'"["',
|
174
|
+
'"]"',
|
175
|
+
'$start',
|
176
|
+
'value',
|
177
|
+
'object',
|
178
|
+
'array',
|
179
|
+
'members',
|
180
|
+
'elements']
|
181
|
+
|
182
|
+
Racc_debug_parser = false
|
183
|
+
|
184
|
+
##### racc system variables end #####
|
185
|
+
|
186
|
+
# reduce 0 omitted
|
187
|
+
|
188
|
+
# reduce 1 omitted
|
189
|
+
|
190
|
+
# reduce 2 omitted
|
191
|
+
|
192
|
+
# reduce 3 omitted
|
193
|
+
|
194
|
+
# reduce 4 omitted
|
195
|
+
|
196
|
+
# reduce 5 omitted
|
197
|
+
|
198
|
+
module_eval <<'.,.,', 'json.y', 10
|
199
|
+
def _reduce_6( val, _values)
|
200
|
+
val[1]
|
201
|
+
end
|
202
|
+
.,.,
|
203
|
+
|
204
|
+
module_eval <<'.,.,', 'json.y', 11
|
205
|
+
def _reduce_7( val, _values)
|
206
|
+
{}
|
207
|
+
end
|
208
|
+
.,.,
|
209
|
+
|
210
|
+
module_eval <<'.,.,', 'json.y', 13
|
211
|
+
def _reduce_8( val, _values)
|
212
|
+
{val[0] => val[2]}
|
213
|
+
end
|
214
|
+
.,.,
|
215
|
+
|
216
|
+
module_eval <<'.,.,', 'json.y', 14
|
217
|
+
def _reduce_9( val, _values)
|
218
|
+
val[0][val[2]] = val[4]; val[0]
|
219
|
+
end
|
220
|
+
.,.,
|
221
|
+
|
222
|
+
module_eval <<'.,.,', 'json.y', 16
|
223
|
+
def _reduce_10( val, _values)
|
224
|
+
val[1]
|
225
|
+
end
|
226
|
+
.,.,
|
227
|
+
|
228
|
+
module_eval <<'.,.,', 'json.y', 17
|
229
|
+
def _reduce_11( val, _values)
|
230
|
+
[]
|
231
|
+
end
|
232
|
+
.,.,
|
233
|
+
|
234
|
+
module_eval <<'.,.,', 'json.y', 19
|
235
|
+
def _reduce_12( val, _values)
|
236
|
+
val
|
237
|
+
end
|
238
|
+
.,.,
|
239
|
+
|
240
|
+
module_eval <<'.,.,', 'json.y', 20
|
241
|
+
def _reduce_13( val, _values)
|
242
|
+
val[0] << val[2]
|
243
|
+
end
|
244
|
+
.,.,
|
245
|
+
|
246
|
+
def _reduce_none( val, _values)
|
247
|
+
val[0]
|
248
|
+
end
|
249
|
+
|
250
|
+
end # class JSON
|
251
|
+
|
252
|
+
|
253
|
+
if $0 == __FILE__
|
254
|
+
src = <<EOS
|
255
|
+
{
|
256
|
+
"name" : null,
|
257
|
+
"id" : 12.3
|
258
|
+
}
|
259
|
+
EOS
|
260
|
+
require 'strscan'
|
261
|
+
puts 'Parsing (String):'
|
262
|
+
print src
|
263
|
+
puts
|
264
|
+
puts 'Result (Ruby Object):'
|
265
|
+
p JSON_RACC.new.parse(StringScanner.new(src))
|
266
|
+
end
|
267
|
+
|
268
|
+
|
data/lib/grammar/ruby.rb
CHANGED
@@ -6,8 +6,8 @@ class Ruby
|
|
6
6
|
# compile a grammar to a parser. The parser can be called with
|
7
7
|
# an input (#[] to get next element) and an output (#<< appends
|
8
8
|
# to it).
|
9
|
-
def self.compile(gram)
|
10
|
-
code = new.dump(gram)
|
9
|
+
def self.compile(gram, input_method=:[])
|
10
|
+
code = new(input_method).dump(gram)
|
11
11
|
#p(code)
|
12
12
|
#code.lined
|
13
13
|
eval(code.to_s).new
|
@@ -71,15 +71,19 @@ class Ruby
|
|
71
71
|
@output << item
|
72
72
|
end
|
73
73
|
|
74
|
-
def initialize
|
74
|
+
def initialize(input_method=:[])
|
75
75
|
@followed = 0
|
76
76
|
@consumed = 0
|
77
77
|
@output0 = Code::Primary.new("o")
|
78
78
|
@output = @output0
|
79
|
+
@output_init = nil
|
79
80
|
@input0 = Code::Primary.new("i")
|
80
81
|
@input = @input0
|
82
|
+
@input_method = input_method
|
81
83
|
@lookahead0 = Code::Primary.new("la")
|
82
84
|
@lookahead = @lookahead0
|
85
|
+
@lookahead_get = Code::Self.at(Code[0])
|
86
|
+
@lookahead_set = Code::Self[Code[0]]
|
83
87
|
@fail0 = Code::Primary.new("f")
|
84
88
|
@fail = @fail0
|
85
89
|
@failure_hard = lambda { |i, la, *expected|
|
@@ -99,7 +103,7 @@ class Ruby
|
|
99
103
|
}
|
100
104
|
@method_definitions = []
|
101
105
|
@methods = {}
|
102
|
-
@consume =
|
106
|
+
@consume = true
|
103
107
|
@void = nil
|
104
108
|
@scope = nil
|
105
109
|
end
|
@@ -110,14 +114,6 @@ class Ruby
|
|
110
114
|
@assignments << var._assign(code)
|
111
115
|
end
|
112
116
|
|
113
|
-
def generate_consume
|
114
|
-
@consume = Code::SharedSteps.new(
|
115
|
-
(@output ? [@output << @lookahead] : []) <<
|
116
|
-
@lookahead._assign(@input[]) <<
|
117
|
-
Code::True
|
118
|
-
)
|
119
|
-
end
|
120
|
-
|
121
117
|
class CodeProxy
|
122
118
|
include Enumerable
|
123
119
|
def initialize(code)
|
@@ -167,24 +163,25 @@ class Ruby
|
|
167
163
|
@scope = "call"
|
168
164
|
top = gram[self]
|
169
165
|
@scope = scope
|
170
|
-
CodeProxy.new(Code[Class].new { ||
|
166
|
+
CodeProxy.new(Code[Class].new(Code[Array]) { ||
|
171
167
|
steps = []
|
172
168
|
@assignments.each { |assignment|
|
173
169
|
steps << assignment
|
174
170
|
}
|
171
|
+
steps << Code::Implicit.super(Code[1])
|
175
172
|
steps = [Code::Steps.new(steps)._def(:initialize)] unless
|
176
173
|
steps.empty?
|
177
174
|
@method_definitions.each { |definition|
|
178
175
|
steps << definition
|
179
176
|
}
|
180
|
-
steps << top.
|
177
|
+
steps << top._and {
|
181
178
|
Code::Self.block_given?._and{
|
182
179
|
Code::Implicit.yield(@lookahead)
|
183
|
-
}
|
184
|
-
|
180
|
+
}._step(Code::True)
|
181
|
+
}._def(:call,
|
185
182
|
@output,
|
186
183
|
@input,
|
187
|
-
@lookahead._assign(@input
|
184
|
+
@lookahead._assign(@input.method_missing(@input_method)),
|
188
185
|
@fail._assign(Code::Self.lambda { |i, la, *exp|
|
189
186
|
exp = exp[0]
|
190
187
|
Code::Implicit.raise(
|
@@ -213,9 +210,23 @@ class Ruby
|
|
213
210
|
end
|
214
211
|
end
|
215
212
|
def consume(matching, expected=nil)
|
216
|
-
|
213
|
+
if @consume
|
214
|
+
matching = matching._and {
|
215
|
+
consume = @lookahead._assign(
|
216
|
+
@input.method_missing(@input_method)
|
217
|
+
)
|
218
|
+
if @output
|
219
|
+
consume = ((@output_init ? @output._assign(@output_init) :
|
220
|
+
@output) << @lookahead).
|
221
|
+
_step(consume)
|
222
|
+
end
|
223
|
+
consume._step(Code::True)
|
224
|
+
}
|
225
|
+
end
|
226
|
+
matching._or{failure(expected)}
|
217
227
|
ensure
|
218
228
|
if @consume
|
229
|
+
@output_init = nil
|
219
230
|
@failure = @failure_hard
|
220
231
|
@consumed += 1
|
221
232
|
end
|
@@ -261,14 +272,33 @@ class Ruby
|
|
261
272
|
def alternation(gram1) # :yield: engine
|
262
273
|
failure = @failure
|
263
274
|
@failure = nil
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
275
|
+
if output_init = @output_init
|
276
|
+
begin
|
277
|
+
gram1[self]._and {
|
278
|
+
@output_init ? @output._assign(@output_init) : Code::True
|
279
|
+
}
|
280
|
+
ensure
|
281
|
+
failure1 = @failure
|
282
|
+
output_init1 = @output_init
|
283
|
+
end._or{
|
284
|
+
@failure = failure
|
285
|
+
@output_init = output_init
|
286
|
+
code = yield(self)
|
287
|
+
if !output_init1 and @output_init
|
288
|
+
code = @output._assign(@output_init)._step(code)
|
289
|
+
end
|
290
|
+
code
|
291
|
+
}
|
292
|
+
else
|
293
|
+
begin
|
294
|
+
gram1[self]
|
295
|
+
ensure
|
296
|
+
failure1 = @failure
|
297
|
+
end._or{
|
298
|
+
@failure = failure
|
299
|
+
yield(self)
|
300
|
+
}
|
301
|
+
end
|
272
302
|
ensure
|
273
303
|
@failure = failure1 if failure1
|
274
304
|
end
|
@@ -382,10 +412,12 @@ class Ruby
|
|
382
412
|
@fail = @fail0
|
383
413
|
@failure = nil
|
384
414
|
@expected = []
|
385
|
-
|
415
|
+
@consume = true
|
386
416
|
code = inner ? recurse(inner, true, &outer) : outer[self]
|
387
417
|
@method_definitions[i] =
|
388
|
-
code.
|
418
|
+
code._and {
|
419
|
+
@lookahead_set._assign(@lookahead)._step(Code::True)
|
420
|
+
}._def(
|
389
421
|
name,
|
390
422
|
@output,
|
391
423
|
@input,
|
@@ -412,9 +444,8 @@ class Ruby
|
|
412
444
|
}.new
|
413
445
|
))
|
414
446
|
call = Code::Self.method_missing(name, output, @input,
|
415
|
-
@lookahead, @fail) {
|
416
|
-
|
417
|
-
@lookahead._assign(la)
|
447
|
+
@lookahead, @fail)._and {
|
448
|
+
@lookahead._assign(@lookahead_get)._step(Code::True)
|
418
449
|
}
|
419
450
|
if expected.empty?
|
420
451
|
Code::Always.new(call)
|
@@ -496,17 +527,24 @@ class Ruby
|
|
496
527
|
Code::Local.new { |buf|
|
497
528
|
begin
|
498
529
|
@output = buf
|
499
|
-
@consume =
|
500
|
-
|
530
|
+
@consume = true
|
531
|
+
output_init = self[buf0,true]
|
532
|
+
if @failure
|
533
|
+
@output._assign(output_init)._step(gram[self])
|
534
|
+
else
|
535
|
+
@output_init = output_init
|
501
536
|
gram[self]
|
502
|
-
|
537
|
+
end
|
503
538
|
ensure
|
504
539
|
@followed -= 1 if block_given?
|
505
540
|
@output = output
|
506
541
|
@consume = consume
|
507
542
|
end._and {
|
508
543
|
!block_given? ? Code::True :
|
509
|
-
|
544
|
+
(@output_init ? (@output._assign(@output_init)) : Code::True).
|
545
|
+
_step(Code::Always.new(
|
546
|
+
block.arity==1 ? yield(buf) : yield(buf, self)
|
547
|
+
))
|
510
548
|
}
|
511
549
|
}
|
512
550
|
end
|
@@ -518,7 +556,7 @@ class Ruby
|
|
518
556
|
@followed += 1 if block_given?
|
519
557
|
begin
|
520
558
|
@output = nil
|
521
|
-
@consume =
|
559
|
+
@consume = true
|
522
560
|
gram[self]
|
523
561
|
ensure
|
524
562
|
@followed -= 1 if block_given?
|
@@ -547,7 +585,7 @@ class Ruby
|
|
547
585
|
buf.slice!(Code[0], buf.size),
|
548
586
|
begin
|
549
587
|
@output = buf
|
550
|
-
@consume =
|
588
|
+
@consume = true
|
551
589
|
@expected = []
|
552
590
|
tokenizer[self]
|
553
591
|
ensure
|
@@ -561,7 +599,7 @@ class Ruby
|
|
561
599
|
begin
|
562
600
|
@input = input1
|
563
601
|
@lookahead = lookahead1
|
564
|
-
@consume =
|
602
|
+
@consume = true
|
565
603
|
@expected = []
|
566
604
|
parser[self]
|
567
605
|
ensure
|
data/lib/grammar/ruby2cext.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
|
2
2
|
require 'grammar/ruby'
|
3
3
|
require 'rubygems'
|
4
|
+
gem 'ruby2cext'
|
4
5
|
require 'ruby2cext/eval2c'
|
5
6
|
|
6
7
|
class Grammar
|
7
8
|
class Ruby2CExt < Ruby
|
8
9
|
|
9
|
-
def self.compile(gram)
|
10
|
-
code = new.dump(gram)
|
10
|
+
def self.compile(gram, input_method=:[])
|
11
|
+
code = new(input_method).dump(gram)
|
11
12
|
#p(code)
|
12
13
|
#code.lined
|
13
14
|
Ruby2CExtension::Eval2C.new.compile_to_proc(code.to_s).call.new
|
@@ -0,0 +1,319 @@
|
|
1
|
+
|
2
|
+
require 'grammar/ruby'
|
3
|
+
require 'rubygems'
|
4
|
+
gem 'ruby2cext'
|
5
|
+
require 'ruby2cext/compiler'
|
6
|
+
require 'digest/sha1'
|
7
|
+
|
8
|
+
class Grammar
|
9
|
+
class Ruby2CExt < Ruby
|
10
|
+
|
11
|
+
def self.compile(gram, input_method=:[])
|
12
|
+
code = new(input_method).dump(gram)
|
13
|
+
ruby_code = code.to_s
|
14
|
+
#puts(code)
|
15
|
+
path = File.join(File.expand_path(
|
16
|
+
ENV["HOME"] || ENV["USERPROFILE"] || ENV["HOMEPATH"] || "."),
|
17
|
+
".ruby2cext")
|
18
|
+
prefix = 'grammar'
|
19
|
+
name = "#{prefix}_#{Digest::SHA1.hexdigest(ruby_code)}"
|
20
|
+
gvar_name = "$__#{name}__"
|
21
|
+
compiler = Ruby2CExtension::Compiler.new(name)
|
22
|
+
compiler.add_plugins({:optimizations => :all})
|
23
|
+
compiler.add_rb_file("#{gvar_name} = #{ruby_code}", name)
|
24
|
+
c_code = compiler.to_c_code
|
25
|
+
|
26
|
+
ws = /(?:\s|\/\*.*?\*\/)/m
|
27
|
+
sym2name = []
|
28
|
+
c_code.scan(
|
29
|
+
/^\s*sym\s*\[\s*(\d+)\s*\]\s*\=\s*rb_intern\s*\(\s*\"([^\"]*)\"\s*\)/
|
30
|
+
) { |i,ruby|
|
31
|
+
sym2name[i.to_i] = ruby;
|
32
|
+
}
|
33
|
+
|
34
|
+
#c_code.gsub!(/\b
|
35
|
+
# switch\s*\(TYPE\s*\(argv\[0\]\)\)\s*\{\s*
|
36
|
+
# case\s+T_FIXNUM:\s*
|
37
|
+
# (res\s*=.*)\s*
|
38
|
+
# break;\s*
|
39
|
+
# default:\s*
|
40
|
+
# res\s*=.*\s*
|
41
|
+
# \}
|
42
|
+
#/x, '\1')
|
43
|
+
|
44
|
+
#c_code.gsub!(/\b
|
45
|
+
# if\s*\(\!RTEST\s*\(Qtrue\)\)\s*
|
46
|
+
# break;
|
47
|
+
#/x, ';')
|
48
|
+
#c_code.gsub!(/^\b(VALUE )?while_res = Qnil;/, ';')
|
49
|
+
#c_code.gsub!(/\bres = while_res;/, ';')
|
50
|
+
|
51
|
+
##n = 0
|
52
|
+
##c_code.scan(/VALUE argv\[(\d+)\]/) { |i|
|
53
|
+
## i = i[0].to_i
|
54
|
+
## n = i if i>n
|
55
|
+
##}
|
56
|
+
##c_code.gsub!(/^\s*VALUE argv\[\d+\]\;\n/, '')
|
57
|
+
##c_code.gsub!(/\bVALUE (recv\s*\=)/, '\1')
|
58
|
+
##c_code.gsub!(/^(\s*)(VALUE res;\n)/,
|
59
|
+
## "\\1\\2\\1VALUE recv;\nVALUE argv[#{n}];\n")
|
60
|
+
ruby2c = Hash.new { |h,k|
|
61
|
+
lambda { |header, assign, call, footer, *argv|
|
62
|
+
call.gsub!(/\brecv\b/, 'self')
|
63
|
+
"#{header}#{assign}#{call}#{footer}"
|
64
|
+
}
|
65
|
+
}
|
66
|
+
ruby2c['at'] = lambda { |header, assign, call, footer, *argv|
|
67
|
+
"res = RARRAY(self)->ptr[NUM2LONG(#{argv[0]})];"
|
68
|
+
}
|
69
|
+
ruby2c['[]='] = lambda { |header, assign, call, footer, *argv|
|
70
|
+
"res = RARRAY(self)->ptr[NUM2LONG(#{argv[0]})] = #{argv[1]};"
|
71
|
+
}
|
72
|
+
c_code.scan(
|
73
|
+
/^\s*rb_define_method\s*\(s_class\,\s*\"([^\"]*)\"\,\s*(\w+)\,\s*\-1\)/
|
74
|
+
) { |ruby,c|
|
75
|
+
ruby2c[ruby] = lambda { |header, assign, call, footer, *argv|
|
76
|
+
"#{header}#{assign}res = #{c}(argc, argv, self);#{footer}"
|
77
|
+
}
|
78
|
+
}
|
79
|
+
c_code.gsub!(/
|
80
|
+
(\{\s*)
|
81
|
+
VALUE\s+recv\s*\=\s*self\s*\;\s*
|
82
|
+
(
|
83
|
+
const\s+int\s+argc\s*\=\s*\d+\s*\;\s*
|
84
|
+
VALUE\s+argv\s*\[\s*\d+\s*\]\s*\;\s*
|
85
|
+
(?:(?>\/\*.*?\*\/)\s*argv\s*\[\s*\d+\s*\]\s*\=\s*(?>[^\;]+\;)\s*)*
|
86
|
+
)
|
87
|
+
(
|
88
|
+
(?:res\s*\=\s*)?rb_funcall2\s*\(\s*
|
89
|
+
recv\s*\,\s*
|
90
|
+
sym\s*\[\s*(\d+)\s*\]\s*(?>\/\*.*?\*\/)\s*\,\s*
|
91
|
+
argc\s*\,\s*
|
92
|
+
argv\s*\)\s*\;
|
93
|
+
(?:\s*res\s*=\s*argv\s*\[\s*argc\s*\-\s*1\s*\]\s*\;)?
|
94
|
+
)
|
95
|
+
(\s*\})
|
96
|
+
/xm) { |match|
|
97
|
+
header = $1
|
98
|
+
recv = $2
|
99
|
+
assign = $2
|
100
|
+
call = $3
|
101
|
+
symnum = $4.to_i
|
102
|
+
footer = $5
|
103
|
+
ruby = sym2name[symnum]
|
104
|
+
c = ruby2c[ruby]
|
105
|
+
argv = []
|
106
|
+
assign.scan(/argv#{ws}*\[#{ws}*(\d+)#{ws}*\]#{ws}*\=#{ws}*([^\;]+)/) {
|
107
|
+
|i,arg|
|
108
|
+
argv[i.to_i] = arg
|
109
|
+
}
|
110
|
+
c[header, assign, call, footer, *argv]
|
111
|
+
}
|
112
|
+
|
113
|
+
c_code.gsub!(/(?=\bstatic\s+BUILTINOPT_FP\s+builtinopt_method_lookup)/) {
|
114
|
+
%q{
|
115
|
+
#include <stdarg.h>
|
116
|
+
typedef struct {
|
117
|
+
BUILTINOPT_FP fp;
|
118
|
+
void* data;
|
119
|
+
} ruby_method;
|
120
|
+
static VALUE normal_call0(VALUE recv, ruby_method* m) {
|
121
|
+
return rb_funcall3(recv, (ID)(m->data), 0, 0);
|
122
|
+
}
|
123
|
+
static VALUE remember_call0(VALUE recv, ruby_method* m) {
|
124
|
+
VALUE klass = CLASS_OF(recv);
|
125
|
+
NODE* body;
|
126
|
+
while (!st_lookup(RCLASS(klass)->m_tbl, (ID)(m->data),
|
127
|
+
(st_data_t *)&body))
|
128
|
+
{
|
129
|
+
klass = RCLASS(klass)->super;
|
130
|
+
if (!klass) {
|
131
|
+
m->fp = &normal_call0;
|
132
|
+
return rb_funcall3(recv, (ID)(m->data), 0, 0);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
body = body->nd_body;
|
136
|
+
if (nd_type(body)==NODE_FBODY) body = body->nd_head;
|
137
|
+
if (nd_type(body)==NODE_CFUNC && body->nd_argc==0) {
|
138
|
+
m->fp = body->nd_cfnc;
|
139
|
+
return (*(m->fp))(recv, m);
|
140
|
+
} else {
|
141
|
+
m->fp = &normal_call0;
|
142
|
+
return rb_funcall3(recv, (ID)(m->data), 0, 0);
|
143
|
+
}
|
144
|
+
}
|
145
|
+
static ruby_method next_input;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
input_sym_num = nil
|
150
|
+
c_code.gsub!(/\b
|
151
|
+
rb_funcall3\s*\(\s*
|
152
|
+
lvar\s*\[\s*1\s*\]\s*,\s*
|
153
|
+
sym\s*\[\s*(\d+)\s*\]\s*(?>\/\*.*?\*\/)\s*,\s*
|
154
|
+
0\s*,\s*
|
155
|
+
0\s*\)
|
156
|
+
/xm) { |match|
|
157
|
+
input_sym_num = $1.to_i unless input_sym_num
|
158
|
+
(input_sym_num!=$1.to_i) ? match :
|
159
|
+
"(*next_input.fp)(lvar[1], &next_input)"
|
160
|
+
}
|
161
|
+
if input_sym_num
|
162
|
+
#c_code.gsub!(/(\bVALUE\s+lvar\s*\[\s*\d+\s*\]\s*\;)(\s*)/) {
|
163
|
+
# "#{$1}#{$2}ruby_method next_input;#{$2}"
|
164
|
+
#}
|
165
|
+
c_code.gsub!(/\bif\s*\(\s*meth_argc\s*>\s*2\s*\)/) { |match|
|
166
|
+
#c_code.gsub!(/\blvar\s*\[\s*1\s*\]\s*\=/) { |match|
|
167
|
+
"next_input.fp = &remember_call0; " +
|
168
|
+
"next_input.data = (void*)sym[#{input_sym_num}]; " +
|
169
|
+
match
|
170
|
+
}
|
171
|
+
end
|
172
|
+
|
173
|
+
builtinopt_method = {}
|
174
|
+
c_code.scan(/
|
175
|
+
\bbuiltinopt_method_tbl\s*\[\s*(\d+)\s*\]\s*\=\s*
|
176
|
+
builtinopt_method_lookup\s*\(\s*
|
177
|
+
(\w+)\s*\,\s*
|
178
|
+
(\w+)\s*\,\s*
|
179
|
+
sym\s*\[\s*(\d+)\s*\]\s*(?>\/\*.*?\*\/)\s*\,\s*
|
180
|
+
(-?\d+)\s*\)\s*\;
|
181
|
+
/xm) { |i,klass,origin,sym,arity|
|
182
|
+
builtinopt_method[[klass,sym2name[sym.to_i]]] = [i.to_i,arity.to_i]
|
183
|
+
}
|
184
|
+
|
185
|
+
#begin
|
186
|
+
# lvars = []
|
187
|
+
# done = true
|
188
|
+
# c_code.gsub!(/
|
189
|
+
# \blvar\s*\[\s*(\d+)\s*\]\s*\=\s*(\S\w*)
|
190
|
+
# |
|
191
|
+
# \{\s*
|
192
|
+
# VALUE\s+recv\s*\=\s*
|
193
|
+
# ((?:\(\s*)?lvar\s*\[\s*(\d+)\s*\]
|
194
|
+
# (?:\s*\=\s*(\S\w*)[^;]*?\))?)\s*\;\s*
|
195
|
+
# VALUE\s+argv\s*\[\s*1\s*\]\s*\;\s*
|
196
|
+
# (?>\/\*.*?\*\/)\s*
|
197
|
+
# (
|
198
|
+
# (?>\/\*.*?\*\/)\s*
|
199
|
+
# \{[^}]*\}\s*
|
200
|
+
# )?
|
201
|
+
# argv\s*\[\s*0\s*\]\s*\=\s*([^;]*?)\s*\;\s*
|
202
|
+
# res\s*\=\s*builtinopt(\w+)__1\s*\(\s*
|
203
|
+
# recv\s*\,\s*
|
204
|
+
# argv\s*
|
205
|
+
# \)\s*\;\s*
|
206
|
+
# \}
|
207
|
+
# /xm) { |match|
|
208
|
+
# if $1
|
209
|
+
# lvars[$1.to_i] = $2
|
210
|
+
# match
|
211
|
+
# else
|
212
|
+
# recv = $4.to_i
|
213
|
+
# lvars[recv] = $5 if $5
|
214
|
+
# klass = case lvars[recv]
|
215
|
+
# when "rb_ary_new"
|
216
|
+
# "rb_cArray"
|
217
|
+
# when "rb_str_new3"
|
218
|
+
# "rb_cString"
|
219
|
+
# else
|
220
|
+
# nil
|
221
|
+
# end
|
222
|
+
# recv = $3
|
223
|
+
# arg0 = $6||""
|
224
|
+
# arg = $7
|
225
|
+
# meth = case $8
|
226
|
+
# when "op_lshift"
|
227
|
+
# "<<"
|
228
|
+
# when /meth_(.*)/
|
229
|
+
# $1
|
230
|
+
# end
|
231
|
+
# builtin,arity = builtinopt_method[[klass, meth]]
|
232
|
+
# if builtin && arity==-1
|
233
|
+
# done = false
|
234
|
+
# arg0 +
|
235
|
+
# "{ " \
|
236
|
+
# "VALUE argv[1]; " \
|
237
|
+
# "argv[0] = #{arg}; " \
|
238
|
+
# "res = (*(builtinopt_method_tbl[#{builtin}]))(1, #{recv}, argv);" \
|
239
|
+
# "}"
|
240
|
+
# elsif builtin && arity==1
|
241
|
+
# done = false
|
242
|
+
# arg0 +
|
243
|
+
# "res = (*(builtinopt_method_tbl[#{builtin}]))(#{recv}, #{arg});"
|
244
|
+
# else
|
245
|
+
# match
|
246
|
+
# end
|
247
|
+
# end
|
248
|
+
# }
|
249
|
+
#end until done
|
250
|
+
#c_code.gsub!(/
|
251
|
+
# (\blvar\s*\[\s*(\d+)\s*\]\s*\=\s*)(
|
252
|
+
# builtinopt(\w+)__0\s*\(\s*
|
253
|
+
# lvar\s*\[\s*(\d+)\s*\]\s*
|
254
|
+
# \)
|
255
|
+
# |
|
256
|
+
# \S\w*
|
257
|
+
# )
|
258
|
+
#/xm) { |match|
|
259
|
+
# if !$4
|
260
|
+
# lvars[$2.to_i] = $3
|
261
|
+
# match
|
262
|
+
# else
|
263
|
+
# recv = $5.to_i
|
264
|
+
# klass = case lvars[recv]
|
265
|
+
# when "rb_ary_new"
|
266
|
+
# "rb_cArray"
|
267
|
+
# when "rb_str_new3"
|
268
|
+
# "rb_cString"
|
269
|
+
# else
|
270
|
+
# nil
|
271
|
+
# end
|
272
|
+
# header = $1
|
273
|
+
# recv = "lvar[#{recv}]"
|
274
|
+
# meth = case $4
|
275
|
+
# when "op_lshift"
|
276
|
+
# "<<"
|
277
|
+
# when /meth_(.*)/
|
278
|
+
# $1
|
279
|
+
# end
|
280
|
+
# builtin,arity = builtinopt_method[[klass, meth]]
|
281
|
+
# if builtin && arity==-1
|
282
|
+
# done = false
|
283
|
+
# header +
|
284
|
+
# "(*(builtinopt_method_tbl[#{builtin}]))(0, #{recv}, 0)"
|
285
|
+
# elsif builtin && arity==0
|
286
|
+
# done = false
|
287
|
+
# header +
|
288
|
+
# "(*(builtinopt_method_tbl[#{builtin}]))(#{recv})"
|
289
|
+
# else
|
290
|
+
# match
|
291
|
+
# end
|
292
|
+
# end
|
293
|
+
#}
|
294
|
+
|
295
|
+
c_filename = File.join(path, "#{name}.c")
|
296
|
+
File.open(c_filename, "w") { |f| f.puts(c_code) }
|
297
|
+
#system("indent -fc1 -st #{c_filename}")
|
298
|
+
#p ::Config::CONFIG
|
299
|
+
|
300
|
+
dl_filename = File.join(path,
|
301
|
+
"#{name}.#{Ruby2CExtension::Compiler::DLEXT}")
|
302
|
+
cflags = ::Config::CONFIG['CFLAGS']
|
303
|
+
#::Config::CONFIG['CFLAGS'] = cflags.gsub(/-g /,'') + ' -O3'
|
304
|
+
begin
|
305
|
+
Ruby2CExtension::Compiler.compile_c_file_to_dllib(c_filename)
|
306
|
+
ensure
|
307
|
+
::Config::CONFIG['CFLAGS'] = cflags
|
308
|
+
end == dl_filename or
|
309
|
+
raise(Ruby2CExtension::Ruby2CExtError::Bug,
|
310
|
+
"unexpected return value from compile_c_file_to_dllib")
|
311
|
+
|
312
|
+
require(dl_filename)
|
313
|
+
eval(gvar_name).new
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
|
data/lib/grammar/rubycall.rb
CHANGED
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: grammar
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version:
|
7
|
-
date: 2008-09-
|
6
|
+
version: 0.8.1
|
7
|
+
date: 2008-09-17 00:00:00 -05:00
|
8
8
|
summary: BNF-like grammar specified directly in ruby
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -34,6 +34,7 @@ files:
|
|
34
34
|
- lib/grammar/ruby0.rb
|
35
35
|
- lib/grammar/ruby.rb
|
36
36
|
- lib/grammar/rubycall.rb
|
37
|
+
- lib/grammar/ruby2cext_hack.rb
|
37
38
|
- lib/grammar/ruby/code.rb
|
38
39
|
- test/molecules.rb
|
39
40
|
- test/atoms.rb
|
@@ -46,6 +47,7 @@ files:
|
|
46
47
|
- test/test_demo.rb
|
47
48
|
- test/basic.rb
|
48
49
|
- benchmark/json.benchmark.rb
|
50
|
+
- benchmark/json.racc.rb
|
49
51
|
- benchmark/json.grammar.rb
|
50
52
|
- benchmark/json.grammar0_5.rb
|
51
53
|
- benchmark/json.ll1.rb
|