redparse 0.8.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -0
- data/COPYING.LGPL +503 -158
- data/History.txt +192 -0
- data/Makefile +9 -0
- data/README.txt +72 -39
- data/bin/redparse +108 -14
- data/lib/miniredparse.rb +1543 -0
- data/lib/redparse.rb +971 -105
- data/lib/redparse/ReduceWithsFor_RedParse_1_8.rb +17412 -0
- data/lib/redparse/ReduceWithsFor_RedParse_1_9.rb +17633 -0
- data/lib/redparse/babynodes.rb +17 -0
- data/lib/redparse/babyparser.rb +17 -0
- data/lib/redparse/cache.rb +290 -6
- data/lib/redparse/compile.rb +6 -97
- data/lib/redparse/decisiontree.rb +1 -1
- data/lib/redparse/float_accurate_to_s.rb +30 -6
- data/lib/redparse/generate.rb +18 -0
- data/lib/redparse/node.rb +415 -124
- data/lib/redparse/parse_tree_server.rb +20 -2
- data/lib/redparse/problemfiles.rb +1 -1
- data/lib/redparse/pthelper.rb +17 -31
- data/lib/redparse/reg_more_sugar.rb +1 -1
- data/lib/redparse/replacing/parse_tree.rb +30 -0
- data/lib/redparse/replacing/ripper.rb +20 -0
- data/lib/redparse/replacing/ruby_parser.rb +28 -0
- data/lib/redparse/ripper.rb +393 -0
- data/lib/redparse/ripper_sexp.rb +153 -0
- data/lib/redparse/stackableclasses.rb +113 -0
- data/lib/redparse/version.rb +18 -1
- data/redparse.gemspec +29 -9
- data/rplt.txt +31 -0
- data/test/data/hd_with_blank_string.rb +3 -0
- data/test/data/pt_known_output.rb +13273 -0
- data/test/data/wp.pp +0 -0
- data/test/generate_parse_tree_server_rc.rb +17 -0
- data/test/rp-locatetest.rb +2 -2
- data/test/test_1.9.rb +338 -35
- data/test/test_all.rb +22 -3
- data/test/test_part.rb +32 -0
- data/test/test_redparse.rb +396 -74
- data/test/test_xform_tree.rb +18 -0
- data/test/unparse_1.9_exceptions.txt +85 -0
- data/test/unparse_1.9_exceptions.txt.old +81 -0
- metadata +71 -46
- data/Rakefile +0 -35
data/lib/redparse/babynodes.rb
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
=begin
|
2
|
+
redparse - a ruby parser written in ruby
|
3
|
+
Copyright (C) 2008,2009, 2012, 2016 Caleb Clausen
|
4
|
+
|
5
|
+
This program is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU Lesser General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
This program is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU Lesser General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU Lesser General Public License
|
16
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
1
18
|
require 'pp'
|
2
19
|
require 'rubygems'
|
3
20
|
require 'rubylexer'
|
data/lib/redparse/babyparser.rb
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
=begin
|
2
|
+
redparse - a ruby parser written in ruby
|
3
|
+
Copyright (C) 2012, 2016 Caleb Clausen
|
4
|
+
|
5
|
+
This program is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU Lesser General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
This program is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU Lesser General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU Lesser General Public License
|
16
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
1
18
|
require 'pp'
|
2
19
|
require 'rubygems'
|
3
20
|
require 'rubylexer'
|
data/lib/redparse/cache.rb
CHANGED
@@ -1,7 +1,38 @@
|
|
1
|
+
=begin
|
2
|
+
redparse - a ruby parser written in ruby
|
3
|
+
Copyright (C) 2012, 2016 Caleb Clausen
|
4
|
+
|
5
|
+
This program is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU Lesser General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
This program is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU Lesser General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU Lesser General Public License
|
16
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
1
18
|
require 'digest/sha2'
|
19
|
+
require 'fileutils'
|
20
|
+
begin
|
21
|
+
require 'etc'
|
22
|
+
rescue LoadError #ignore it
|
23
|
+
end
|
2
24
|
class RedParse
|
3
25
|
class Cache
|
4
|
-
def initialize
|
26
|
+
def initialize(is_file,name,*params)
|
27
|
+
divider=params.index(:/)
|
28
|
+
@input_id=params[0...divider]
|
29
|
+
@output_id=params[divider+1..-1]
|
30
|
+
@rubyversion=@input_id.pop
|
31
|
+
@name=name
|
32
|
+
@is_file=is_file
|
33
|
+
end
|
34
|
+
|
35
|
+
def old_initialize *params
|
5
36
|
@callersfile=Digest::SHA2.hexdigest params.join(',')
|
6
37
|
@homedir=find_home+"/.redparse/"
|
7
38
|
Dir.mkdir @homedir unless File.exist? @homedir
|
@@ -13,6 +44,8 @@ class RedParse
|
|
13
44
|
File.open(@homedir+"/parserdigest","wb"){|fd| fd.puts actual_digest } #update saved digest
|
14
45
|
end
|
15
46
|
retire_old_entries
|
47
|
+
rescue Errno::EACCES
|
48
|
+
#do nothing
|
16
49
|
end
|
17
50
|
|
18
51
|
def cachedir
|
@@ -76,7 +109,16 @@ class RedParse
|
|
76
109
|
# it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
|
77
110
|
# least on Win32).
|
78
111
|
#(originally stolen from rubygems)
|
79
|
-
|
112
|
+
#before trying env variables, try getpwuid, since the environment
|
113
|
+
#might have been cleansed (eg by a cgi server) or altered (eg by
|
114
|
+
#rubygems tests).
|
115
|
+
def Cache.find_home
|
116
|
+
begin
|
117
|
+
return Etc.getpwuid.dir
|
118
|
+
rescue Exception
|
119
|
+
#do nothing
|
120
|
+
end
|
121
|
+
|
80
122
|
['HOME', 'USERPROFILE'].each do |homekey|
|
81
123
|
return ENV[homekey] if ENV[homekey]
|
82
124
|
end
|
@@ -95,6 +137,7 @@ class RedParse
|
|
95
137
|
end
|
96
138
|
end
|
97
139
|
end
|
140
|
+
def find_home; Cache.find_home end
|
98
141
|
private :find_home, :entry_files, :redparse_rb_hexdigest, :retire_old_entries, :max_size, :hexdigest_of_file
|
99
142
|
|
100
143
|
def hash_of_input input
|
@@ -105,7 +148,7 @@ class RedParse
|
|
105
148
|
end
|
106
149
|
end
|
107
150
|
|
108
|
-
def
|
151
|
+
def old_get input
|
109
152
|
hash=hash_of_input input
|
110
153
|
cachefile=cachedir+hash
|
111
154
|
if File.exist? cachefile
|
@@ -138,17 +181,17 @@ class RedParse
|
|
138
181
|
end
|
139
182
|
return result
|
140
183
|
end
|
141
|
-
rescue EOFError
|
184
|
+
rescue EOFError,Errno::EACCES
|
142
185
|
return nil
|
143
186
|
end
|
144
187
|
|
145
|
-
def
|
188
|
+
def old_put input,result
|
146
189
|
hash=hash_of_input input
|
147
190
|
File.open(cachedir+hash, "wb"){|fd|
|
148
191
|
begin
|
149
192
|
Thread.current["Marshal.ignore_sclass"]=true
|
150
193
|
Marshal.dump(result,fd)
|
151
|
-
rescue TypeError
|
194
|
+
rescue TypeError #dump failed
|
152
195
|
File.unlink cachedir+hash
|
153
196
|
begin
|
154
197
|
require 'ron'
|
@@ -168,5 +211,246 @@ class RedParse
|
|
168
211
|
warn "cache write failed for:\n#{result.inspect}"
|
169
212
|
File.unlink cachedir+hash
|
170
213
|
end
|
214
|
+
|
215
|
+
def get input,output_type="parsed"
|
216
|
+
output_type=@rubyversion.to_s+output_type
|
217
|
+
if @is_file
|
218
|
+
Cache.read_for_file(input,@name,@input_id,output_type,@output_id)
|
219
|
+
else
|
220
|
+
Cache.read_for_str(input,@input_id,output_type,@output_id)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def put input,result,output_type="parsed"
|
225
|
+
output_type=@rubyversion.to_s+output_type
|
226
|
+
if @is_file
|
227
|
+
Cache.write_for_file(input,@name,@input_id,output_type,@output_id,result)
|
228
|
+
else
|
229
|
+
Cache.write_for_str(input,@input_id,output_type,@output_id,result)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
CACHEDIRNAME="obj"
|
235
|
+
GLOBALCACHEDIRNAME=".ruby-"+CACHEDIRNAME
|
236
|
+
|
237
|
+
def Cache.get input,name,input_id,output_type,outputter_id
|
238
|
+
if String===input
|
239
|
+
read_for_str(input,input_id,output_type,outputter_id)
|
240
|
+
else
|
241
|
+
read_for_file(input,name,input_id,output_type,outputter_id)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def Cache.put input,name,input_id,output_type,outputter_id,result
|
246
|
+
if String===input
|
247
|
+
write_for_str(input,input_id,output_type,outputter_id,result)
|
248
|
+
else
|
249
|
+
write_for_file(input,name,input_id,output_type,outputter_id,result)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def Cache.read input,name,input_id,output_type,outputter_id
|
254
|
+
result=get input,name,input_id,output_type,outputter_id
|
255
|
+
return result if result
|
256
|
+
|
257
|
+
result=yield
|
258
|
+
put input,name,input_id,output_type,outputter_id,result
|
259
|
+
end
|
260
|
+
|
261
|
+
def Cache.cachename_for_file(name,output_type)
|
262
|
+
cache_fn=File.join(File.dirname(name),CACHEDIRNAME,File.basename(name))+"."+output_type
|
263
|
+
dir=File.dirname(cache_fn)
|
264
|
+
begin
|
265
|
+
Dir.mkdir dir unless File.exists?(dir)
|
266
|
+
raise unless File.writable?(dir)
|
267
|
+
rescue Exception #chosen dir is not writeable
|
268
|
+
cache_fn=File.join(find_home,GLOBALCACHEDIRNAME,name)+"."+output_type
|
269
|
+
FileUtils.mkdir_p( File.dirname( cache_fn ) )
|
270
|
+
end
|
271
|
+
return cache_fn
|
272
|
+
end
|
273
|
+
|
274
|
+
def Cache.cachename_for_str(str,options,output_type)
|
275
|
+
options=options.to_a.sort_by{|k,v| k}.map{|k,v| k+'='+v} if Hash===options
|
276
|
+
options=options.join(',') unless String===options
|
277
|
+
#options.gsub!('%n','%%n'); options.gsub!("\n",'%n')
|
278
|
+
#fail if /\n/===options
|
279
|
+
#str=options+"\n"+str
|
280
|
+
options=Digest::SHA2.hexdigest(options) if options.size>100
|
281
|
+
digest=Digest::SHA2.hexdigest(str)
|
282
|
+
cache_fn=File.join(find_home, GLOBALCACHEDIRNAME,"-e",options,digest)+"."+output_type
|
283
|
+
FileUtils.mkdir_p( File.dirname( cache_fn ) )
|
284
|
+
return cache_fn
|
285
|
+
end
|
286
|
+
|
287
|
+
HEADER_REX=/\A\n\#encoded\ with\ (ascii|Ron|Marshal)\n
|
288
|
+
\#(.*)\n
|
289
|
+
\#([0-9A-Fa-f]+)\n
|
290
|
+
\#([0-9A-Fa-f]+)\n
|
291
|
+
\#\s{0,9}([0-9]{1,9})\s{0,9}\n\z
|
292
|
+
/x
|
293
|
+
|
294
|
+
#encoder, options, inputhash, outputterhash, size
|
295
|
+
def Cache.read_trailer(f)
|
296
|
+
f.seek(-(9*3+2+1),IO::SEEK_END)
|
297
|
+
size=f.read[/\n\# *([0-9]+) *\n\z/,1].to_i
|
298
|
+
return if size.zero?
|
299
|
+
f.seek(-size,IO::SEEK_END)
|
300
|
+
buf=f.read
|
301
|
+
return unless result=buf.match(HEADER_REX)
|
302
|
+
result=result.to_a
|
303
|
+
result.shift
|
304
|
+
return result
|
305
|
+
end
|
306
|
+
|
307
|
+
def Cache.attempt_read(cache_fn,inputdigest,options,output_identity,want_file=false)
|
308
|
+
return if !File.exist? cache_fn
|
309
|
+
|
310
|
+
#warn "...reading from cache file #{cache_fn}"
|
311
|
+
#warn "...options=#{options.inspect}"
|
312
|
+
|
313
|
+
outid=Digest::SHA2.hexdigest output_identity.join(',')
|
314
|
+
|
315
|
+
cache_f=File.open(cache_fn,"rb")
|
316
|
+
pos=cache_f.pos
|
317
|
+
options=options.to_s
|
318
|
+
|
319
|
+
encoder,saved_options,saved_inputdigest,saved_outid=read_trailer cache_f
|
320
|
+
error=case
|
321
|
+
when !encoder; "trailer not found"
|
322
|
+
when saved_inputdigest!=inputdigest; "input changed"
|
323
|
+
when saved_outid!=outid; "outputter changed"
|
324
|
+
when saved_options!=options; "options changed from #{saved_options.inspect} to #{options.inspect}"
|
325
|
+
end
|
326
|
+
if error
|
327
|
+
#warn "...cache read failed because #{error}"
|
328
|
+
cache_f.close
|
329
|
+
cache_f=nil
|
330
|
+
return
|
331
|
+
end
|
332
|
+
|
333
|
+
case encoder
|
334
|
+
when 'ascii'
|
335
|
+
return cache_f if want_file
|
336
|
+
return cache_f.read
|
337
|
+
when 'Ron'
|
338
|
+
begin
|
339
|
+
require 'ron'
|
340
|
+
return Ron.load( cache_f.read )
|
341
|
+
rescue Exception=>e
|
342
|
+
warn "#{e.class}: #{e}"
|
343
|
+
warn "cache ron read failed for:#{cache_fn}"
|
344
|
+
return nil
|
345
|
+
end
|
346
|
+
when 'Marshal'
|
347
|
+
cache_f.pos=pos
|
348
|
+
begin
|
349
|
+
return Marshal.load( cache_f )
|
350
|
+
rescue Exception=>e
|
351
|
+
warn "#{e.class}: #{e}"
|
352
|
+
warn "cache read failed for:#{cache_fn}"
|
353
|
+
return nil
|
354
|
+
end
|
355
|
+
else
|
356
|
+
warn "unrecognized RedParse::Cache encoder type: #{encoder}"
|
357
|
+
return nil
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
def Cache.attempt_write(cache_fn,inputdigest,options,output_identity,result)
|
362
|
+
#STDERR.write "...writing to cache file #{cache_fn}... "
|
363
|
+
|
364
|
+
if result.respond_to? :sysread
|
365
|
+
path=result.path
|
366
|
+
begin
|
367
|
+
FileUtils.move(path,cache_fn)
|
368
|
+
rescue Exception
|
369
|
+
FileUtils.copy(path,cache_fn)
|
370
|
+
end
|
371
|
+
encoder= "ascii"
|
372
|
+
#STDERR.puts 'file'
|
373
|
+
cache_f=File.open(cache_fn,"a")
|
374
|
+
else
|
375
|
+
cache_f=File.open(cache_fn,"wb")
|
376
|
+
|
377
|
+
if String===result
|
378
|
+
cache_f.write result
|
379
|
+
encoder= "ascii"
|
380
|
+
#STDERR.puts 'ascii'
|
381
|
+
else begin
|
382
|
+
Thread.current["Marshal.ignore_sclass"]=true
|
383
|
+
Marshal.dump(result,cache_f)
|
384
|
+
encoder= "Marshal"
|
385
|
+
#STDERR.puts 'Marshal'
|
386
|
+
rescue TypeError #dump failed
|
387
|
+
#STDERR.write "Marshal failed => "
|
388
|
+
cache_f.close
|
389
|
+
cache_f=File.open(cache_fn,"wb")
|
390
|
+
begin
|
391
|
+
require 'ron'
|
392
|
+
cache_f.write Ron.dump(result)
|
393
|
+
encoder='Ron'
|
394
|
+
#STDERR.puts "Ron"
|
395
|
+
rescue Exception
|
396
|
+
#STDERR.puts "Ron failed"
|
397
|
+
File.unlink(cache_fn)
|
398
|
+
return
|
399
|
+
end
|
400
|
+
ensure
|
401
|
+
Thread.current["Marshal.ignore_sclass"]=nil
|
402
|
+
end end
|
403
|
+
end
|
404
|
+
|
405
|
+
outid=Digest::SHA2.hexdigest output_identity.join(',')
|
406
|
+
trailer= "\n#encoded with #{encoder}\n##{options}\n##{inputdigest}\n##{outid}\n"
|
407
|
+
sz=trailer.size+2
|
408
|
+
szsz=sz.to_s.size
|
409
|
+
sz+=szsz
|
410
|
+
sz+=1 unless szsz==sz.to_s.size
|
411
|
+
trailer<< "##{sz}\n"
|
412
|
+
fail 'bad trailer size' unless trailer[/^\#([0-9]+)\n\Z/,1].to_i==trailer.size
|
413
|
+
cache_f.write trailer
|
414
|
+
|
415
|
+
return result
|
416
|
+
ensure
|
417
|
+
cache_f.close if cache_f
|
418
|
+
#STDERR.puts("...options=#{options.inspect}")
|
419
|
+
end
|
420
|
+
|
421
|
+
def Cache.read_for_file(input,name,options,output_type,output_identity,&if_missing)
|
422
|
+
name=File.expand_path(name)
|
423
|
+
inputdigest=Digest::SHA2.file(name).hexdigest
|
424
|
+
cache_fn=cachename_for_file name,output_type
|
425
|
+
result=attempt_read(cache_fn,inputdigest,options,output_identity,:want_file)
|
426
|
+
return result if result
|
427
|
+
|
428
|
+
if if_missing and result=if_missing.call
|
429
|
+
write_for_file(input,name,options,output_type,output_identity,result)
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
def Cache.write_for_file(input,name,options,output_type,output_identity,result)
|
434
|
+
name=File.expand_path(name)
|
435
|
+
inputdigest=Digest::SHA2.file(name).hexdigest
|
436
|
+
cache_fn=cachename_for_file name,output_type
|
437
|
+
attempt_write(cache_fn,inputdigest,options,output_identity,result)
|
438
|
+
end
|
439
|
+
|
440
|
+
def Cache.read_for_str(input,options,output_type,output_identity,&if_missing)
|
441
|
+
inputdigest=Digest::SHA2.hexdigest(input)
|
442
|
+
cache_fn= cachename_for_str input,options,output_type
|
443
|
+
result=attempt_read(cache_fn,inputdigest,options,output_identity)
|
444
|
+
return result if result
|
445
|
+
|
446
|
+
if if_missing and result=if_missing.call
|
447
|
+
write_for_str(input,options,output_type,output_identity,result)
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
def Cache.write_for_str(input,options,output_type,output_identity,result)
|
452
|
+
inputdigest=Digest::SHA2.hexdigest(input)
|
453
|
+
cache_fn= cachename_for_str input,options,output_type
|
454
|
+
attempt_write(cache_fn,inputdigest,options,output_identity,result)
|
171
455
|
end
|
172
456
|
end
|
data/lib/redparse/compile.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
=begin
|
2
2
|
redparse - a ruby parser written in ruby
|
3
|
-
Copyright (C) 2008,2009 Caleb Clausen
|
3
|
+
Copyright (C) 2008,2009, 2012, 2016 Caleb Clausen
|
4
4
|
|
5
5
|
This program is free software: you can redistribute it and/or modify
|
6
6
|
it under the terms of the GNU Lesser General Public License as published by
|
@@ -35,6 +35,7 @@ require "redparse/node"
|
|
35
35
|
require "redparse/reg_more_sugar"
|
36
36
|
require "redparse/generate"
|
37
37
|
require "redparse/cache"
|
38
|
+
require "redparse/stackableclasses"
|
38
39
|
|
39
40
|
class RedParse
|
40
41
|
|
@@ -143,101 +144,8 @@ if defined? END_ATTACK
|
|
143
144
|
|
144
145
|
end
|
145
146
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
#just the left side (the stack/lookahead matchers)
|
150
|
-
def LEFT
|
151
|
-
@rules.map{|r| r.left.subregs }.flatten
|
152
|
-
end
|
153
|
-
|
154
|
-
#remove lookahead and lookback decoration
|
155
|
-
def LEFT_NO_LOOKING
|
156
|
-
l=LEFT()
|
157
|
-
l.map!{|m|
|
158
|
-
case m #
|
159
|
-
when Reg::LookAhead,Reg::LookBack; m.subregs[0]
|
160
|
-
when Proc; []
|
161
|
-
else m #
|
162
|
-
end #
|
163
|
-
}
|
164
|
-
l
|
165
|
-
end
|
166
|
-
|
167
|
-
#all classes mentioned in rules, on left and right sides
|
168
|
-
def STACKABLE_CLASSES #
|
169
|
-
return @sc_result unless @sc_result.nil?
|
170
|
-
@sc_result=false
|
171
|
-
l=LEFT_NO_LOOKING()
|
172
|
-
l=l.map{|lm| sc_juice lm}.flatten.compact
|
173
|
-
r= @rules.map{|rr| rr.right }.grep(Class) #classes in productions
|
174
|
-
result=l+r
|
175
|
-
@sc_result=result.grep(Class).uniq
|
176
|
-
fail if @sc_result.empty?
|
177
|
-
return @sc_result
|
178
|
-
end
|
147
|
+
include RedParse::StackableClasses
|
179
148
|
|
180
|
-
def juice(m)
|
181
|
-
case m #
|
182
|
-
when Class;
|
183
|
-
return [m] unless @subclasses_of
|
184
|
-
result=[m] # and subclasses too
|
185
|
-
i=0
|
186
|
-
while item=result[i]
|
187
|
-
#p item
|
188
|
-
result.concat @subclasses_of[item]
|
189
|
-
i += 1
|
190
|
-
end
|
191
|
-
result
|
192
|
-
when String,Regexp; juice(RedParse.KW(m))
|
193
|
-
when Reg::And; m.subregs.map{|x| juice(x).flatten.compact}.inject{|sum,rr| sum&rr}
|
194
|
-
when Reg::Or; m.subregs.map( &method(:juice) )
|
195
|
-
when Reg::Not;
|
196
|
-
m=m.subregs[0]
|
197
|
-
if Class===m or (Reg::Or===m and
|
198
|
-
m.subregs.inject{|sum,x| sum && (Class===x) })
|
199
|
-
j=juice(m)
|
200
|
-
STACKABLE_CLASSES()-j.flatten.compact rescue j
|
201
|
-
else
|
202
|
-
STACKABLE_CLASSES()
|
203
|
-
end
|
204
|
-
else STACKABLE_CLASSES()
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def sc_juice(m)
|
209
|
-
case m #
|
210
|
-
when Class; [m]
|
211
|
-
when String,Regexp; juice(RedParse.KW(m))
|
212
|
-
# when String,Regexp; [KeywordToken]
|
213
|
-
when Reg::And; m.subregs.map{|x| sc_juice(x)}.compact.map{|x| x.flatten.compact}.inject{|sum,rr| sum&rr }
|
214
|
-
when Reg::Or; m.subregs.map( &method(:sc_juice) )
|
215
|
-
when Reg::Not; sc_juice(m.subregs[0])
|
216
|
-
when Reg::LookAhead, Reg::LookBack; sc_juice(m.subregs[0])
|
217
|
-
else []
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
def LOOKAHEAD_CLASSES rule
|
222
|
-
last=rule.left.subregs.last
|
223
|
-
return STACKABLE_CLASSES() unless Reg::LookAhead===last
|
224
|
-
la= last.subregs[0]
|
225
|
-
return juice(la).flatten.compact
|
226
|
-
end
|
227
|
-
#
|
228
|
-
def TOS_CLASSES rule
|
229
|
-
i=-1
|
230
|
-
mats=rule.left.subregs
|
231
|
-
m=mats[i]
|
232
|
-
m=mats[i-=1] if Reg::LookAhead===m || Proc===m
|
233
|
-
result=[]
|
234
|
-
while Reg::Repeat===m and m.times.min.zero?
|
235
|
-
result<<juice(m.subregs[0])
|
236
|
-
m=mats[i-=1]
|
237
|
-
end
|
238
|
-
return (result+juice(m)).flatten.compact
|
239
|
-
end
|
240
|
-
|
241
149
|
def [](i)
|
242
150
|
@rules[i]
|
243
151
|
end
|
@@ -1386,9 +1294,10 @@ end
|
|
1386
1294
|
|
1387
1295
|
states=all_states
|
1388
1296
|
# @rules=expanded_RULES
|
1389
|
-
@inputs=nil #Marshal no like it
|
1390
1297
|
|
1298
|
+
false && \
|
1391
1299
|
begin
|
1300
|
+
@inputs=nil #Marshal no like it
|
1392
1301
|
p :dumping
|
1393
1302
|
Marshal.dump(self,f=open("cached_parse_tables.drb","wb"))
|
1394
1303
|
p :dump_done!
|
@@ -1399,7 +1308,7 @@ end
|
|
1399
1308
|
@inputs=enumerate_exemplars
|
1400
1309
|
end
|
1401
1310
|
end
|
1402
|
-
f.close
|
1311
|
+
f.close if f
|
1403
1312
|
|
1404
1313
|
#look for unused dotted rules and actions
|
1405
1314
|
#also states with drs past the end
|