grammar 0.8 → 0.8.1
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.
- 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
|