redparse 0.8.3 → 0.8.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +63 -4
- data/Makefile +43 -0
- data/README.txt +101 -166
- data/Rakefile +1 -1
- data/bin/redparse +49 -21
- data/lib/redparse.rb +88 -1654
- data/lib/redparse/cache.rb +172 -0
- data/lib/redparse/compile.rb +1648 -0
- data/lib/redparse/float_accurate_to_s.rb +162 -0
- data/lib/redparse/generate.rb +6 -2
- data/lib/redparse/node.rb +677 -397
- data/lib/redparse/parse_tree_server.rb +129 -0
- data/lib/redparse/pthelper.rb +43 -0
- data/lib/redparse/reg_more_sugar.rb +5 -5
- data/lib/redparse/version.rb +1 -1
- data/redparse.gemspec +43 -0
- data/test/data/skkdictools.rb +3 -0
- data/test/generate_parse_tree_server_rc.rb +43 -0
- data/test/rp-locatetest.rb +41 -1
- data/test/test_1.9.rb +114 -0
- data/test/test_all.rb +3 -0
- data/test/test_redparse.rb +283 -124
- data/test/test_xform_tree.rb +66 -0
- metadata +57 -56
@@ -0,0 +1,162 @@
|
|
1
|
+
class Float
|
2
|
+
SIZE=[1.1].pack("d").size
|
3
|
+
BITSIZE=SIZE*8
|
4
|
+
BASE10_DIGITS=(2**BITSIZE-1).to_s.size
|
5
|
+
def accurate_to_s
|
6
|
+
return "#{'-' if self<0}Infinity" if infinite?
|
7
|
+
return "NaN" if nan?
|
8
|
+
return "0.0e0" if zero?
|
9
|
+
|
10
|
+
as_str=sprintf("%.#{BASE10_DIGITS+2}e",self)
|
11
|
+
|
12
|
+
#decompose self into sign, mantissa, and exponent (in string form)
|
13
|
+
all,sign,first,digits,exp=*as_str.match(/^([+-]?)(\d)\.(\d+)e(.*)$/)
|
14
|
+
digits=first<<digits
|
15
|
+
exp=exp.to_i+1
|
16
|
+
lead=sign<<"0."
|
17
|
+
return digits=digits if as_str.to_f.zero? #hopeless
|
18
|
+
|
19
|
+
#recompose back to a float
|
20
|
+
result=[lead,digits,"e",exp].join
|
21
|
+
result_f=result.to_f
|
22
|
+
delta=result_f - self
|
23
|
+
return digits=digits if delta.zero? #if representation is exact, return here
|
24
|
+
|
25
|
+
#figure out which direction to go to get toward the right answer
|
26
|
+
if delta<0
|
27
|
+
incr=1
|
28
|
+
else #delta>0
|
29
|
+
incr=-1
|
30
|
+
end
|
31
|
+
|
32
|
+
#keep adding increasing increments to mantissa
|
33
|
+
#until we get to a value on the other side of the correct answer
|
34
|
+
while true
|
35
|
+
while true
|
36
|
+
try_digits=digits.to_i.+(incr).to_s
|
37
|
+
if try_digits.size>digits.size
|
38
|
+
exp+=1
|
39
|
+
digits="0"+digits
|
40
|
+
end
|
41
|
+
fail if try_digits[0]==?- #can't happen... I think?
|
42
|
+
trying=[lead,try_digits,"e",exp].join
|
43
|
+
trying_f=trying.to_f
|
44
|
+
break unless trying_f.zero?
|
45
|
+
digits[-1,1]='' #workaround 1.8 bug
|
46
|
+
end
|
47
|
+
return digits=try_digits if trying_f==self
|
48
|
+
break if self.between?(*[trying_f,result_f].sort) #(trying_f-self)*delta<0
|
49
|
+
incr*=2
|
50
|
+
end
|
51
|
+
|
52
|
+
#we now have lower and upper bounds on the correct answer
|
53
|
+
lower,upper=*[digits.to_i, digits.to_i.+(incr)].sort
|
54
|
+
|
55
|
+
#maybe one of the bounds is already the correct answer?
|
56
|
+
result=[lead,lower,"e",exp].join
|
57
|
+
return digits=lower if result.to_f==self
|
58
|
+
result=[lead,upper,"e",exp].join
|
59
|
+
return digits=upper if result.to_f==self
|
60
|
+
|
61
|
+
#binary search between lower and upper bounds til we find a correct answer
|
62
|
+
digits=nil
|
63
|
+
while true
|
64
|
+
return as_str if upper-lower <= 1 #hopeless
|
65
|
+
mid=(lower+upper)/2
|
66
|
+
mid_s=[lead,mid,"e",exp].join
|
67
|
+
mid_f=mid_s.to_f
|
68
|
+
return digits=mid if mid_f==self
|
69
|
+
if mid_f<self
|
70
|
+
lower=mid
|
71
|
+
else #mid_f>self
|
72
|
+
upper=mid
|
73
|
+
end
|
74
|
+
end
|
75
|
+
ensure
|
76
|
+
|
77
|
+
#try to drop unneeded trailing digits
|
78
|
+
if digits
|
79
|
+
digits=digits.to_s
|
80
|
+
begin
|
81
|
+
last=digits.slice!( -1 )
|
82
|
+
result=[lead,digits,"e",exp].join.to_f
|
83
|
+
end while result==self or result.zero? && digits.size.nonzero?
|
84
|
+
roundup=(digits.to_i+1).to_s
|
85
|
+
if roundup.size>digits.size
|
86
|
+
exp+=1
|
87
|
+
digits="0"+digits
|
88
|
+
end
|
89
|
+
roundup.slice!( /0+\Z/ )
|
90
|
+
roundup=[lead,roundup,"e",exp].join
|
91
|
+
return roundup if roundup.to_f==self
|
92
|
+
return [lead,digits<<last,"e",exp].join
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
=begin not quite accurate, tho
|
98
|
+
class String
|
99
|
+
def accurate_to_f
|
100
|
+
all,sign,int,frac,exp=*self.match(/\A([+-])?([0-9_]+)(?:\.([0-9_]+))?(?:[eE]([+-]?[0-9_]+))?/)
|
101
|
+
exp=exp.to_i||0
|
102
|
+
exp-=frac.size
|
103
|
+
mantissa=sign<<int<<frac
|
104
|
+
mantissa=mantissa.to_f
|
105
|
+
scale=10.0**exp
|
106
|
+
return mantissa*scale
|
107
|
+
end
|
108
|
+
end
|
109
|
+
=end
|
110
|
+
|
111
|
+
eval DATA.read if __FILE__==$0
|
112
|
+
__END__
|
113
|
+
|
114
|
+
require 'test/unit'
|
115
|
+
|
116
|
+
class FloatRoundTripTest<Test::Unit::TestCase
|
117
|
+
def float_round_trip f
|
118
|
+
str=f.accurate_to_s
|
119
|
+
if str=="Infinity"
|
120
|
+
return 1.0/0
|
121
|
+
elsif str=="-Infinity"
|
122
|
+
return -1.0/0
|
123
|
+
elsif str=="NaN"
|
124
|
+
return 0.0/0.0
|
125
|
+
else
|
126
|
+
str.to_f
|
127
|
+
end
|
128
|
+
end
|
129
|
+
alias frt float_round_trip
|
130
|
+
|
131
|
+
def rand_float
|
132
|
+
base=rand
|
133
|
+
range=Float::MIN_10_EXP..Float::MAX_10_EXP
|
134
|
+
extent=range.last-range.first
|
135
|
+
offset=rand(extent+1)
|
136
|
+
exp=range.first+offset
|
137
|
+
base*=10**exp
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_frt
|
141
|
+
data=[0.399891415240566, 0.198188037200931, 0.90302699802093,
|
142
|
+
7.48121345153454520016e-01, 4.11408313999083175005e-02,
|
143
|
+
2.68070684698467065488e-02, 3.85029229764812574999e-01,
|
144
|
+
"\327\237vY\343n\342?".unpack("d")[0],
|
145
|
+
1.0/0, -1.0/0, 0.0/0.0,
|
146
|
+
"\333\211>4\253Atu".unpack("d")[0],
|
147
|
+
"\2461\220\253\214\267e\021".unpack("d")[0],
|
148
|
+
"\r\032N\f'\336\243\003".unpack("d")[0],
|
149
|
+
"B[\226\001\2175f\021".unpack("d")[0],
|
150
|
+
"%\217\336\362\326\272\026\001".unpack("d")[0],
|
151
|
+
"\312\342\344\206\237\024\"\003".unpack("d")[0],
|
152
|
+
]
|
153
|
+
1_000_000.times{|i|
|
154
|
+
f=data.shift||rand_float
|
155
|
+
p sprintf("%.#{Float::BASE10_DIGITS}e",f)
|
156
|
+
p [f].pack"d"
|
157
|
+
p f.accurate_to_s
|
158
|
+
f2=frt f
|
159
|
+
warn "failed with i=#{i} f=#{f}, #{[f].pack("d").inspect}; f2=#{f2}, #{[f2].pack("d").inspect}" unless [f].pack("d")==[f2].pack("d")
|
160
|
+
}
|
161
|
+
end
|
162
|
+
end
|
data/lib/redparse/generate.rb
CHANGED
@@ -205,6 +205,10 @@ def repl(rule,m)
|
|
205
205
|
when Class
|
206
206
|
%[static VALUE repl_#{rule.name}=rb_const_lookup(rb_const_lookup(kNIL,"RedParse"),"#{repl.name});\n]
|
207
207
|
when StackMonkey
|
208
|
+
huh
|
209
|
+
else
|
210
|
+
huh
|
211
|
+
end
|
208
212
|
end
|
209
213
|
|
210
214
|
def reduce(rule,m)
|
@@ -235,7 +239,7 @@ def reduce(rule,m)
|
|
235
239
|
SEMANTIC_STACK_SET(yyredval); /* Copy ($$) onto semantic stack.*/
|
236
240
|
goto nonterminal_#{str2cname repl.name}; /* Compute transition on produced node type.*/
|
237
241
|
]
|
238
|
-
end
|
242
|
+
#end
|
239
243
|
|
240
244
|
rescue Exception=>e
|
241
245
|
backtrace.unshift("exception in reduce of rule #{rule.name} #{e.class}:#{e}").join("\n")
|
@@ -352,7 +356,7 @@ end
|
|
352
356
|
}
|
353
357
|
STRMAP_REX=/#{STRMAPPINGS.keys.map{|x| Regexp.quote x}.join "|"}/
|
354
358
|
def self.str2cname str
|
355
|
-
str.gsub(STRMAP_REX){|
|
359
|
+
str.gsub(STRMAP_REX){|str2| STRMAPPINGS[str2] } \
|
356
360
|
.gsub(/(?!#{LETTER_DIGIT}).|[X]/o){|ch|
|
357
361
|
"X"+ esc=CHARMAPPINGS[ch[0]] ? esc : ch[0].to_s(16)
|
358
362
|
}
|
data/lib/redparse/node.rb
CHANGED
@@ -27,13 +27,12 @@ require 'tempfile'
|
|
27
27
|
require 'pp'
|
28
28
|
require "rubylexer"
|
29
29
|
require "reg"
|
30
|
-
|
30
|
+
require "redparse/float_accurate_to_s"
|
31
31
|
|
32
32
|
|
33
33
|
|
34
34
|
|
35
35
|
class RedParse
|
36
|
-
# module Nodes
|
37
36
|
#import token classes from rubylexer
|
38
37
|
RubyLexer::constants.each{|k|
|
39
38
|
t=RubyLexer::const_get(k)
|
@@ -41,12 +40,14 @@ class RedParse
|
|
41
40
|
}
|
42
41
|
|
43
42
|
module FlattenedIvars
|
43
|
+
EXCLUDED_IVARS=%w[@data @offset @startline @endline]
|
44
|
+
EXCLUDED_IVARS.push(*EXCLUDED_IVARS.map{|iv| iv.to_sym })
|
44
45
|
def flattened_ivars
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
ivars=instance_variables
|
47
|
+
ivars-=EXCLUDED_IVARS
|
48
|
+
ivars.sort!
|
49
|
+
result=ivars+ivars.map{|iv|
|
50
|
+
instance_variable_get(iv)
|
50
51
|
}
|
51
52
|
return result
|
52
53
|
end
|
@@ -148,7 +149,7 @@ class RedParse
|
|
148
149
|
def identity_name
|
149
150
|
k=self.class
|
150
151
|
list=[k.name]
|
151
|
-
list.concat k.boolean_identity_params.map{|(bip
|
152
|
+
list.concat k.boolean_identity_params.map{|(bip,*)| bip if send(bip) }.compact
|
152
153
|
list.concat k.identity_params.map{|(ip,variations)|
|
153
154
|
val=send(ip)
|
154
155
|
variations.include? val or fail "identity_param #{k}##{ip} unexpected value #{val.inspect}"
|
@@ -230,7 +231,7 @@ class RedParse
|
|
230
231
|
|
231
232
|
def infix
|
232
233
|
@infix if defined? @infix
|
233
|
-
end unless
|
234
|
+
end unless allocate.respond_to? :infix
|
234
235
|
end
|
235
236
|
|
236
237
|
class OperatorToken
|
@@ -242,25 +243,18 @@ class RedParse
|
|
242
243
|
]+RubyLexer::OPORBEGINWORDLIST+%w<; lhs, rhs, rescue3>
|
243
244
|
#identity_param :unary, true,false,nil
|
244
245
|
#identity_param :tag, :lhs,:rhs,:param,:call,:array,:block,:nested,nil
|
245
|
-
|
246
|
-
#this should be in rubylexer
|
247
|
-
def as
|
248
|
-
if tag and ident[/^[,*&]$/]
|
249
|
-
tag.to_s+ident
|
250
|
-
end
|
251
|
-
end
|
252
246
|
end
|
253
247
|
|
254
248
|
class NumberToken
|
255
249
|
alias to_lisp to_s
|
256
|
-
def negative; /\A-/ === ident end unless
|
250
|
+
def negative; /\A-/ === ident end unless allocate.respond_to? :negative
|
257
251
|
|
258
252
|
identity_param :negative, true,false
|
259
253
|
end
|
260
254
|
|
261
255
|
class MethNameToken
|
262
256
|
alias to_lisp to_s
|
263
|
-
def has_equals; /#{LETTER_DIGIT}=$/o===ident end unless
|
257
|
+
def has_equals; /#{LETTER_DIGIT}=$/o===ident end unless allocate.respond_to? :has_equals
|
264
258
|
|
265
259
|
identity_param :has_equals, true,false
|
266
260
|
end
|
@@ -367,6 +361,8 @@ class RedParse
|
|
367
361
|
case val
|
368
362
|
when Symbol
|
369
363
|
val=CallNode[nil,val.to_s]
|
364
|
+
when Integer,Float
|
365
|
+
val=LiteralNode[val]
|
370
366
|
end
|
371
367
|
super( *args<<val )
|
372
368
|
end
|
@@ -387,14 +383,8 @@ class RedParse
|
|
387
383
|
@endline||=0
|
388
384
|
end
|
389
385
|
|
390
|
-
def
|
391
|
-
|
392
|
-
result.each_with_index{|x,i|
|
393
|
-
if i&1==0 and x!="@data"
|
394
|
-
result[i,2]=[]
|
395
|
-
end
|
396
|
-
}
|
397
|
-
result
|
386
|
+
def self.create(*args)
|
387
|
+
new(*args)
|
398
388
|
end
|
399
389
|
|
400
390
|
def ==(other)
|
@@ -416,6 +406,8 @@ class RedParse
|
|
416
406
|
case val
|
417
407
|
when Symbol
|
418
408
|
val=CallNode[nil,val.to_s]
|
409
|
+
when Integer,Float
|
410
|
+
val=LiteralNode[val]
|
419
411
|
end
|
420
412
|
super( *args<<val )
|
421
413
|
end
|
@@ -464,18 +456,84 @@ class RedParse
|
|
464
456
|
return result
|
465
457
|
end
|
466
458
|
|
467
|
-
def inspect
|
468
|
-
ivarnames=instance_variables-
|
459
|
+
def inspect label=nil,indent=0
|
460
|
+
ivarnames=instance_variables-FlattenedIvars::EXCLUDED_IVARS
|
461
|
+
ivarnodes=[]
|
462
|
+
ivars=ivarnames.map{|ivarname|
|
463
|
+
ivar=instance_variable_get(ivarname)
|
464
|
+
if Node===ivar
|
465
|
+
ivarnodes.push [ivarname,ivar]
|
466
|
+
nil
|
467
|
+
else
|
468
|
+
ivarname[1..-1]+"="+ivar.inspect if ivar
|
469
|
+
end
|
470
|
+
}.compact.join(' ')
|
471
|
+
|
472
|
+
|
473
|
+
pos=@startline.to_s
|
474
|
+
pos<<"..#@endline" if @endline!=@startline
|
475
|
+
pos<<"@#@offset"
|
476
|
+
classname=self.class.name
|
477
|
+
classname.sub!(/^(?:RedParse::)?(.*?)(?:Node)?$/){$1}
|
478
|
+
result= [' '*indent,"+",(label+': ' if label),classname," pos=",pos," ",ivars,"\n"]
|
479
|
+
indent+=2
|
480
|
+
|
481
|
+
namelist=self.class.namelist
|
482
|
+
if namelist and !namelist.empty?
|
483
|
+
namelist.each{|name|
|
484
|
+
val=send name rescue "{{ERROR INSPECTING ATTR #{name}}}"
|
485
|
+
case val
|
486
|
+
when Node; result<< val.inspect(name,indent)
|
487
|
+
when ListInNode
|
488
|
+
result.push ' '*indent,"#{name}:\n",*val.map{|v|
|
489
|
+
v.inspect(nil,indent+2) rescue ' '*(indent+2)+"-#{v.inspect}\n"
|
490
|
+
}
|
491
|
+
when nil;
|
492
|
+
else ivars<< " #{name}=#{val.inspect}"
|
493
|
+
end
|
494
|
+
}
|
495
|
+
else
|
496
|
+
each{|val|
|
497
|
+
case val
|
498
|
+
when Node; result<< val.inspect(nil,indent)
|
499
|
+
else result<< ' '*indent+"-#{val.inspect}\n"
|
500
|
+
end
|
501
|
+
}
|
502
|
+
end
|
503
|
+
|
504
|
+
ivarnodes.each{|(name,val)|
|
505
|
+
result<< val.inspect(name,indent)
|
506
|
+
}
|
507
|
+
|
508
|
+
return result.join
|
509
|
+
end
|
510
|
+
|
511
|
+
def evalable_inspect
|
512
|
+
ivarnames=instance_variables-["@data", :@data]
|
469
513
|
ivars=ivarnames.map{|ivarname|
|
470
|
-
|
514
|
+
val=instance_variable_get(ivarname)
|
515
|
+
if val.respond_to?(:evalable_inspect)
|
516
|
+
val=val.evalable_inspect
|
517
|
+
else
|
518
|
+
val=val.inspect
|
519
|
+
end
|
520
|
+
":"+ivarname+"=>"+val
|
471
521
|
}.join(', ')
|
472
|
-
|
522
|
+
|
523
|
+
bare="["+map{|val|
|
524
|
+
if val.respond_to?(:evalable_inspect)
|
525
|
+
val=val.evalable_inspect
|
526
|
+
else
|
527
|
+
val=val.inspect
|
528
|
+
end
|
529
|
+
}.join(", ")+"]"
|
530
|
+
|
473
531
|
bare.gsub!(/\]\Z/, ", {"+ivars+"}]") unless ivarnames.empty?
|
474
532
|
return self.class.name+bare
|
475
533
|
end
|
476
|
-
|
534
|
+
|
477
535
|
def pretty_print(q)
|
478
|
-
ivarnames=instance_variables-["@data"]
|
536
|
+
ivarnames=instance_variables-["@data", :@data]
|
479
537
|
ivars={}
|
480
538
|
ivarnames.each{|ivarname|
|
481
539
|
ivars[ivarname.to_sym]=instance_variable_get(ivarname)
|
@@ -493,29 +551,32 @@ class RedParse
|
|
493
551
|
def self.param_names(*names)
|
494
552
|
accessors=[]
|
495
553
|
namelist=[]
|
496
|
-
|
554
|
+
@namelist=[]
|
497
555
|
names.each{|name|
|
498
556
|
name=name.to_s
|
499
557
|
last=name[-1]
|
500
558
|
name.chomp! '!' and name << ?_
|
501
|
-
|
559
|
+
namelist << name
|
502
560
|
unless last==?_
|
503
|
-
accessors << "def #{name.chomp('_')}; self[#{namelist.size}] end\n"
|
504
|
-
accessors << "def #{name.chomp('_')}=(newval);
|
505
|
-
|
561
|
+
accessors << "def #{name.chomp('_')}; self[#{@namelist.size}] end\n"
|
562
|
+
accessors << "def #{name.chomp('_')}=(newval); "+
|
563
|
+
"newval.extend ::RedParse::ListInNode if ::Array===newval and not RedParse::Node===newval;"+
|
564
|
+
"self[#{@namelist.size}]=newval "+
|
565
|
+
"end\n"
|
566
|
+
@namelist << name
|
506
567
|
end
|
507
568
|
}
|
508
569
|
init="
|
509
|
-
def initialize(#{
|
510
|
-
replace [#{namelist.size==1 ?
|
511
|
-
namelist.first :
|
512
|
-
namelist.join(', ')
|
570
|
+
def initialize(#{namelist.join(', ')})
|
571
|
+
replace [#{@namelist.size==1 ?
|
572
|
+
@namelist.first :
|
573
|
+
@namelist.join(', ')
|
513
574
|
}]
|
514
575
|
end
|
515
576
|
alias init_data initialize
|
516
577
|
"
|
517
578
|
|
518
|
-
code= "class ::#{self}\n"+init+accessors.
|
579
|
+
code= "class ::#{self}\n"+init+accessors.join+"\nend\n"
|
519
580
|
if defined? DEBUGGER__ or defined? Debugger
|
520
581
|
Tempfile.open("param_name_defs"){|f|
|
521
582
|
f.write code
|
@@ -525,6 +586,15 @@ class RedParse
|
|
525
586
|
else
|
526
587
|
eval code
|
527
588
|
end
|
589
|
+
|
590
|
+
@namelist.reject!{|name| /_\Z/===name }
|
591
|
+
end
|
592
|
+
|
593
|
+
def self.namelist
|
594
|
+
#@namelist
|
595
|
+
result=superclass.namelist||[] rescue []
|
596
|
+
result.concat @namelist if defined? @namelist
|
597
|
+
return result
|
528
598
|
end
|
529
599
|
|
530
600
|
def lhs_unparse o; unparse(o) end
|
@@ -584,12 +654,14 @@ class RedParse
|
|
584
654
|
end
|
585
655
|
|
586
656
|
def depthwalk(parent=nil,index=nil,subindex=nil,&callback)
|
587
|
-
|
657
|
+
(size-1).downto(0){|i|
|
658
|
+
datum=self[i]
|
588
659
|
case datum
|
589
660
|
when Node
|
590
661
|
datum.depthwalk(self,i,&callback)
|
591
662
|
when Array
|
592
|
-
datum.
|
663
|
+
(datum.size-1).downto(0){|j|
|
664
|
+
x=datum[j]
|
593
665
|
if Node===x
|
594
666
|
x.depthwalk(self,i,j,&callback)
|
595
667
|
else
|
@@ -603,6 +675,24 @@ class RedParse
|
|
603
675
|
callback[ parent,index,subindex,self ]
|
604
676
|
end
|
605
677
|
|
678
|
+
def depthwalk_nodes(parent=nil,index=nil,subindex=nil,&callback)
|
679
|
+
(size-1).downto(0){|i|
|
680
|
+
datum=self[i]
|
681
|
+
case datum
|
682
|
+
when Node
|
683
|
+
datum.depthwalk_nodes(self,i,&callback)
|
684
|
+
when Array
|
685
|
+
(datum.size-1).downto(0){|j|
|
686
|
+
x=datum[j]
|
687
|
+
if Node===x
|
688
|
+
x.depthwalk_nodes(self,i,j,&callback)
|
689
|
+
end
|
690
|
+
}
|
691
|
+
end
|
692
|
+
}
|
693
|
+
callback[ parent,index,subindex,self ]
|
694
|
+
end
|
695
|
+
|
606
696
|
def add_parent_links!
|
607
697
|
walk{|parent,i,subi,o|
|
608
698
|
o.parent=parent if Node===o
|
@@ -611,30 +701,101 @@ class RedParse
|
|
611
701
|
|
612
702
|
attr_accessor :parent
|
613
703
|
|
614
|
-
def xform_tree!(
|
704
|
+
def xform_tree!(*xformers)
|
705
|
+
#search tree for patterns and store results of actions in session
|
615
706
|
session={}
|
616
707
|
depthwalk{|parent,i,subi,o|
|
617
|
-
xformer
|
708
|
+
xformers.each{|xformer|
|
709
|
+
if o
|
710
|
+
tempsession={}
|
711
|
+
xformer.xform!(o,tempsession)
|
712
|
+
merge_replacement_session session, tempsession
|
713
|
+
#elsif xformer===o and Reg::Transform===xformer
|
714
|
+
# new=xformer.right
|
715
|
+
# if Reg::Formula===right
|
716
|
+
# new=new.formula_value(o,session)
|
717
|
+
# end
|
718
|
+
# subi ? parent[i][subi]=new : parent[i]=new
|
719
|
+
end
|
720
|
+
}
|
618
721
|
}
|
619
722
|
session["final"]=true
|
723
|
+
|
724
|
+
#apply saved-up actions stored in session, while making a copy of tree
|
725
|
+
result=::Ron::GraphWalk::graphcopy(self,old2new={}){|cntr,o,i,ty,useit|
|
726
|
+
newo=nil
|
727
|
+
replace_value o.__id__,o,session do |val|
|
728
|
+
newo=val
|
729
|
+
useit[0]=true
|
730
|
+
end
|
731
|
+
newo
|
732
|
+
}
|
733
|
+
finallys=session["finally"] #finallys too
|
734
|
+
finallys.each{|(action,arg)| action[old2new[arg.__id__],session] } if finallys
|
735
|
+
|
736
|
+
return result
|
737
|
+
=begin was
|
738
|
+
finallys=session["finally"]
|
739
|
+
finallys.each{|(action,arg)| action[arg] } if finallys
|
740
|
+
|
620
741
|
depthwalk{|parent,i,subi,o|
|
621
|
-
|
622
|
-
|
623
|
-
if Reg::Formula===new
|
624
|
-
new=new.formula_value(o,session)
|
625
|
-
end
|
742
|
+
next unless parent
|
743
|
+
replace_ivars_and_self o, session do |new|
|
626
744
|
subi ? parent[i][subi]=new : parent[i]=new
|
627
745
|
end
|
628
746
|
}
|
629
|
-
|
630
|
-
new
|
631
|
-
if Reg::Formula===new
|
632
|
-
new=new.formula_value(self,session)
|
633
|
-
end
|
747
|
+
replace_ivars_and_self self,session do |new|
|
748
|
+
fail unless new
|
634
749
|
return new
|
635
|
-
else
|
636
|
-
return self
|
637
750
|
end
|
751
|
+
|
752
|
+
return self
|
753
|
+
=end
|
754
|
+
end
|
755
|
+
|
756
|
+
def replace_ivars_and_self o,session,&replace_self_action
|
757
|
+
o.instance_variables.each{|ovname|
|
758
|
+
ov=o.instance_variable_get(ovname)
|
759
|
+
|
760
|
+
replace_value ov.__id__,ov,session do |new|
|
761
|
+
o.instance_variable_set(ovname,new)
|
762
|
+
end
|
763
|
+
}
|
764
|
+
replace_value o.__id__,o,session, &replace_self_action
|
765
|
+
end
|
766
|
+
|
767
|
+
def replace_value ovid,ov,session,&replace_action
|
768
|
+
if session.has_key? ovid
|
769
|
+
new= session[ovid]
|
770
|
+
if Reg::Formula===new
|
771
|
+
new=new.formula_value(ov,session)
|
772
|
+
end
|
773
|
+
replace_action[new]
|
774
|
+
end
|
775
|
+
end
|
776
|
+
|
777
|
+
def merge_replacement_session session,tempsession
|
778
|
+
ts_has_boundvars= !tempsession.keys.grep(::Symbol).empty?
|
779
|
+
tempsession.each_pair{|k,v|
|
780
|
+
if Integer===k
|
781
|
+
if true
|
782
|
+
v=Reg::WithBoundRefValues.new(v,tempsession) if ts_has_boundvars
|
783
|
+
else
|
784
|
+
v=Ron::GraphWalk.graphcopy(v){|cntr,o,i,ty,useit|
|
785
|
+
if Reg::BoundRef===o
|
786
|
+
useit[0]=true
|
787
|
+
tempsession[o.name]||o
|
788
|
+
end
|
789
|
+
}
|
790
|
+
end
|
791
|
+
if session.has_key? k
|
792
|
+
v=v.chain_to session[k]
|
793
|
+
end
|
794
|
+
session[k]=v
|
795
|
+
elsif "finally"==k
|
796
|
+
session["finally"]=Array(session["finally"]).concat v
|
797
|
+
end
|
798
|
+
}
|
638
799
|
end
|
639
800
|
|
640
801
|
def linerange
|
@@ -657,7 +818,7 @@ class RedParse
|
|
657
818
|
j=nil
|
658
819
|
list=Array.new(node)
|
659
820
|
assignnode=nil
|
660
|
-
list.each_with_index{|
|
821
|
+
list.each_with_index{|assignnode2,jj| assignnode=assignnode2
|
661
822
|
AssignNode===assignnode and break(j=jj)
|
662
823
|
}
|
663
824
|
fail "CommaOpNode without any assignment in final parse tree" unless j
|
@@ -782,38 +943,36 @@ class RedParse
|
|
782
943
|
def unary; false end
|
783
944
|
def lvalue; nil end
|
784
945
|
|
946
|
+
#why not use Ron::GraphWalk.graph_copy instead here?
|
785
947
|
def deep_copy transform={},&override
|
786
948
|
handler=proc{|child|
|
787
949
|
if transform.has_key? child.__id__
|
788
950
|
transform[child.__id__]
|
789
951
|
else
|
790
952
|
case child
|
791
|
-
when Node
|
953
|
+
when Node
|
792
954
|
override&&override[child] or
|
793
955
|
child.deep_copy(transform,&override)
|
794
|
-
when Array
|
795
|
-
child.map(&handler)
|
796
|
-
when Integer,Symbol,Float,nil,false,true,Module
|
956
|
+
when Array
|
957
|
+
child.clone.map!(&handler)
|
958
|
+
when Integer,Symbol,Float,nil,false,true,Module
|
797
959
|
child
|
798
960
|
else
|
799
|
-
child.
|
961
|
+
child.clone
|
800
962
|
end
|
801
963
|
end
|
802
964
|
}
|
803
965
|
|
804
966
|
newdata=map(&handler)
|
805
967
|
|
806
|
-
|
807
|
-
result_module=nil
|
968
|
+
result=clone
|
808
969
|
instance_variables.each{|iv|
|
809
|
-
unless iv=="@data"
|
970
|
+
unless iv=="@data" or iv==:@data
|
810
971
|
val=instance_variable_get(iv)
|
811
|
-
|
812
|
-
result_module=val if iv=="@module" #hacky
|
972
|
+
result.instance_variable_set(iv,handler[val])
|
813
973
|
end
|
814
974
|
}
|
815
|
-
result
|
816
|
-
result.extend result_module if result_module
|
975
|
+
result.replace newdata
|
817
976
|
return result
|
818
977
|
end
|
819
978
|
|
@@ -823,6 +982,7 @@ class RedParse
|
|
823
982
|
when Node
|
824
983
|
node.remove_instance_variable :@offset rescue nil
|
825
984
|
node.remove_instance_variable :@loopword_offset rescue nil
|
985
|
+
node.remove_instance_variable :@iftok_offset rescue nil
|
826
986
|
node.remove_instance_variable :@endline rescue nil
|
827
987
|
node.remove_instance_variable :@lvalue rescue nil
|
828
988
|
if node.respond_to? :lvalue
|
@@ -862,8 +1022,8 @@ class RedParse
|
|
862
1022
|
def +@
|
863
1023
|
node2matcher=proc{|n|
|
864
1024
|
case n
|
865
|
-
when Node
|
866
|
-
when Array
|
1025
|
+
when Node; +n
|
1026
|
+
when Array; +[*n.map(&node2matcher)]
|
867
1027
|
else n
|
868
1028
|
end
|
869
1029
|
}
|
@@ -952,12 +1112,12 @@ class RedParse
|
|
952
1112
|
end
|
953
1113
|
|
954
1114
|
class VarNode<ValueNode
|
1115
|
+
param_names :ident
|
955
1116
|
include FlattenedIvars
|
956
1117
|
attr_accessor :endline,:offset
|
957
1118
|
attr_reader :lvar_type,:in_def
|
958
1119
|
attr_writer :lvalue
|
959
1120
|
|
960
|
-
|
961
1121
|
alias == flattened_ivars_equal?
|
962
1122
|
|
963
1123
|
def initialize(tok)
|
@@ -968,8 +1128,8 @@ class RedParse
|
|
968
1128
|
@in_def=tok.in_def
|
969
1129
|
end
|
970
1130
|
|
971
|
-
def ident; first end
|
972
|
-
def ident=x; self[0]=x end
|
1131
|
+
# def ident; first end
|
1132
|
+
# def ident=x; self[0]=x end
|
973
1133
|
alias image ident
|
974
1134
|
alias startline endline
|
975
1135
|
alias name ident
|
@@ -977,7 +1137,7 @@ class RedParse
|
|
977
1137
|
|
978
1138
|
def parsetree(o)
|
979
1139
|
type=case ident[0]
|
980
|
-
when
|
1140
|
+
when ?$
|
981
1141
|
case ident[1]
|
982
1142
|
when ?1..?9; return [:nth_ref,ident[1..-1].to_i]
|
983
1143
|
when ?&,?+,?`,?'; return [:back_ref,ident[1].chr.to_sym] #`
|
@@ -1040,7 +1200,7 @@ class RedParse
|
|
1040
1200
|
|
1041
1201
|
def dup
|
1042
1202
|
result=super
|
1043
|
-
result.ident
|
1203
|
+
result.ident=ident.dup if ident
|
1044
1204
|
return result
|
1045
1205
|
end
|
1046
1206
|
|
@@ -1059,52 +1219,79 @@ end
|
|
1059
1219
|
end
|
1060
1220
|
|
1061
1221
|
#forward decls
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1222
|
+
class RawOpNode<ValueNode
|
1223
|
+
end
|
1224
|
+
class OpNode<RawOpNode
|
1225
|
+
end
|
1226
|
+
class NotEqualNode<OpNode
|
1227
|
+
end
|
1228
|
+
class MatchNode<OpNode
|
1229
|
+
end
|
1230
|
+
class NotMatchNode<OpNode
|
1231
|
+
end
|
1232
|
+
class ArrowOpNode<RawOpNode
|
1233
|
+
end
|
1234
|
+
class RescueOpNode<RawOpNode
|
1235
|
+
end
|
1236
|
+
class LogicalNode<RawOpNode
|
1237
|
+
end
|
1238
|
+
class AndNode<LogicalNode
|
1239
|
+
end
|
1240
|
+
class OrNode<LogicalNode
|
1241
|
+
end
|
1242
|
+
class RangeNode<RawOpNode
|
1243
|
+
end
|
1244
|
+
class IfOpNode<RawOpNode
|
1245
|
+
end
|
1246
|
+
class UnlessOpNode<RawOpNode
|
1247
|
+
end
|
1248
|
+
class WhileOpNode<RawOpNode
|
1249
|
+
end
|
1250
|
+
class UntilOpNode<RawOpNode
|
1251
|
+
end
|
1252
|
+
|
1253
|
+
OP2CLASS={
|
1086
1254
|
"!="=>NotEqualNode,
|
1087
1255
|
"!~"=>NotMatchNode,
|
1088
1256
|
"=~"=>MatchNode,
|
1257
|
+
"if"=>IfOpNode,
|
1258
|
+
"unless"=>UnlessOpNode,
|
1259
|
+
"while"=>WhileOpNode,
|
1260
|
+
"until"=>UntilOpNode,
|
1261
|
+
".."=>RangeNode,
|
1262
|
+
"..."=>RangeNode,
|
1263
|
+
"=>"=>ArrowOpNode,
|
1264
|
+
"&&"=>AndNode,
|
1265
|
+
"||"=>OrNode,
|
1266
|
+
"and"=>AndNode,
|
1267
|
+
"or"=>OrNode,
|
1268
|
+
"rescue"=>RescueOpNode,
|
1269
|
+
"rescue3"=>RescueOpNode,
|
1089
1270
|
}
|
1090
1271
|
|
1091
1272
|
class RawOpNode<ValueNode
|
1092
1273
|
param_names(:left,:op,:right)
|
1093
|
-
def initialize(left,op,right)
|
1094
|
-
|
1095
|
-
op
|
1274
|
+
def initialize(left,op,right=nil)
|
1275
|
+
op,right=nil,op if right.nil?
|
1276
|
+
if op.respond_to? :ident
|
1277
|
+
@offset=op.offset
|
1278
|
+
op=op.ident
|
1279
|
+
end
|
1096
1280
|
super(left,op,right)
|
1097
|
-
Array((OP2MIXIN[op]||OpNode)).each{|mod|
|
1098
|
-
extend(mod)
|
1099
|
-
mod.instance_method(:initialize).bind(self).call(left,op,right)
|
1100
|
-
}
|
1101
1281
|
end
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1282
|
+
|
1283
|
+
# def initialize_copy other
|
1284
|
+
# rebuild(other.left,other.op,other.right)
|
1285
|
+
# end
|
1286
|
+
|
1287
|
+
def self.create(left,op,right)
|
1288
|
+
op_s=op.ident
|
1289
|
+
k=OP2CLASS[op_s]||OpNode
|
1290
|
+
k.new(left,op,right)
|
1106
1291
|
end
|
1292
|
+
|
1107
1293
|
def image; "(#{op})" end
|
1294
|
+
|
1108
1295
|
def raw_unparse o
|
1109
1296
|
l=left.unparse(o)
|
1110
1297
|
l[/(~| \Z)/] and maybesp=" "
|
@@ -1112,10 +1299,11 @@ end
|
|
1112
1299
|
end
|
1113
1300
|
end
|
1114
1301
|
|
1115
|
-
|
1302
|
+
class OpNode<RawOpNode
|
1116
1303
|
def initialize(left,op,right)
|
1117
1304
|
#@negative_of="="+$1 if /^!([=~])$/===op
|
1118
|
-
|
1305
|
+
op=op.ident if op.respond_to? :ident
|
1306
|
+
super left,op,right
|
1119
1307
|
end
|
1120
1308
|
def to_lisp
|
1121
1309
|
"(#{op} #{left.to_lisp} #{right.to_lisp})"
|
@@ -1141,8 +1329,13 @@ end
|
|
1141
1329
|
# def unparse o=default_unparse_options; raw_unparse o end
|
1142
1330
|
end
|
1143
1331
|
|
1144
|
-
|
1145
|
-
|
1332
|
+
class MatchNode<OpNode
|
1333
|
+
param_names :left,:op_,:right
|
1334
|
+
|
1335
|
+
def initialize(left,op,right=nil)
|
1336
|
+
op,right=nil,op unless right
|
1337
|
+
replace [left,right]
|
1338
|
+
end
|
1146
1339
|
|
1147
1340
|
def parsetree(o)
|
1148
1341
|
if StringNode===left and left.char=='/'
|
@@ -1156,8 +1349,13 @@ end
|
|
1156
1349
|
def op; "=~"; end
|
1157
1350
|
end
|
1158
1351
|
|
1159
|
-
|
1160
|
-
|
1352
|
+
class NotEqualNode<OpNode
|
1353
|
+
param_names :left,:op_,:right
|
1354
|
+
|
1355
|
+
def initialize(left,op,right=nil)
|
1356
|
+
op,right=nil,op unless right
|
1357
|
+
replace [left,right]
|
1358
|
+
end
|
1161
1359
|
|
1162
1360
|
def parsetree(o)
|
1163
1361
|
result=opnode_parsetree(o)
|
@@ -1168,8 +1366,13 @@ end
|
|
1168
1366
|
def op; "!="; end
|
1169
1367
|
end
|
1170
1368
|
|
1171
|
-
|
1172
|
-
|
1369
|
+
class NotMatchNode<OpNode
|
1370
|
+
param_names :left,:op_,:right
|
1371
|
+
|
1372
|
+
def initialize(left,op,right=nil)
|
1373
|
+
op,right=nil,op unless right
|
1374
|
+
replace [left,right]
|
1375
|
+
end
|
1173
1376
|
|
1174
1377
|
def parsetree(o)
|
1175
1378
|
if StringNode===left and left.char=="/"
|
@@ -1177,7 +1380,9 @@ end
|
|
1177
1380
|
elsif StringNode===right and right.char=="/"
|
1178
1381
|
[:not, [:match3, right.parsetree(o), left.parsetree(o)]]
|
1179
1382
|
else
|
1180
|
-
|
1383
|
+
result=opnode_parsetree(o)
|
1384
|
+
result[2]="=#{op[1..1]}".to_sym
|
1385
|
+
result=[:not, result]
|
1181
1386
|
end
|
1182
1387
|
end
|
1183
1388
|
|
@@ -1211,6 +1416,26 @@ end
|
|
1211
1416
|
end
|
1212
1417
|
attr_writer :lvalue
|
1213
1418
|
identity_param :lvalue, nil, true
|
1419
|
+
|
1420
|
+
def extract_unbraced_hash
|
1421
|
+
param_list=Array.new(self)
|
1422
|
+
first=last=nil
|
1423
|
+
param_list.each_with_index{|param,i|
|
1424
|
+
break first=i if ArrowOpNode===param
|
1425
|
+
}
|
1426
|
+
(1..param_list.size).each{|i| param=param_list[-i]
|
1427
|
+
break last=-i if ArrowOpNode===param
|
1428
|
+
}
|
1429
|
+
if first
|
1430
|
+
arrowrange=first..last
|
1431
|
+
arrows=param_list[arrowrange]
|
1432
|
+
h=HashLiteralNode.new(nil,arrows,nil)
|
1433
|
+
h.offset=arrows.first.offset
|
1434
|
+
h.startline=arrows.first.startline
|
1435
|
+
h.endline=arrows.last.endline
|
1436
|
+
return h,arrowrange
|
1437
|
+
end
|
1438
|
+
end
|
1214
1439
|
end
|
1215
1440
|
|
1216
1441
|
class LiteralNode<ValueNode; end
|
@@ -1297,9 +1522,8 @@ end
|
|
1297
1522
|
return "" if empty?
|
1298
1523
|
unparse_nl(first,o,'')+first.unparse(o)+
|
1299
1524
|
self[1..-1].map{|expr|
|
1300
|
-
# p expr
|
1301
1525
|
unparse_nl(expr,o)+expr.unparse(o)
|
1302
|
-
}.
|
1526
|
+
}.join
|
1303
1527
|
end
|
1304
1528
|
end
|
1305
1529
|
|
@@ -1316,7 +1540,7 @@ end
|
|
1316
1540
|
sum=''
|
1317
1541
|
type=:str
|
1318
1542
|
tree=i=nil
|
1319
|
-
result.each_with_index{|tree,i
|
1543
|
+
result.each_with_index{|tree2,i2| tree,i=tree2,i2
|
1320
1544
|
sum+=tree[1]
|
1321
1545
|
tree.first==:str or break(type=:dstr)
|
1322
1546
|
}
|
@@ -1344,42 +1568,70 @@ end
|
|
1344
1568
|
end
|
1345
1569
|
end
|
1346
1570
|
|
1347
|
-
|
1348
|
-
|
1349
|
-
# end
|
1350
|
-
module ArrowOpNode
|
1351
|
-
def initialize(*args)
|
1352
|
-
@module=ArrowOpNode
|
1353
|
-
end
|
1571
|
+
class ArrowOpNode
|
1572
|
+
param_names(:left,:op,:right)
|
1354
1573
|
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
#
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1574
|
+
def initialize(*args)
|
1575
|
+
super
|
1576
|
+
end
|
1577
|
+
|
1578
|
+
#def unparse(o=default_unparse_options)
|
1579
|
+
# left.unparse(o)+" => "+right.unparse(o)
|
1580
|
+
#end
|
1581
|
+
end
|
1582
|
+
|
1583
|
+
class RangeNode
|
1584
|
+
param_names(:first,:op,:last)
|
1585
|
+
def initialize(left,op,right=nil)
|
1586
|
+
op,right="..",op unless right
|
1587
|
+
op=op.ident if op.respond_to? :ident
|
1588
|
+
@exclude_end=!!op[2]
|
1366
1589
|
@as_flow_control=false
|
1367
|
-
|
1590
|
+
super(left,op,right)
|
1368
1591
|
end
|
1369
|
-
def begin;
|
1370
|
-
def end;
|
1371
|
-
def
|
1372
|
-
def
|
1592
|
+
def begin; first end
|
1593
|
+
def end; last end
|
1594
|
+
def left; first end
|
1595
|
+
def right; last end
|
1373
1596
|
def exclude_end?; @exclude_end end
|
1374
1597
|
|
1598
|
+
# def self.[] *list
|
1599
|
+
# result=RawOpNode[*list]
|
1600
|
+
# result.extend RangeNode
|
1601
|
+
# return result
|
1602
|
+
# end
|
1603
|
+
|
1604
|
+
def self.[] *list
|
1605
|
+
new(*list)
|
1606
|
+
end
|
1607
|
+
|
1375
1608
|
def parsetree(o)
|
1376
1609
|
first=first().parsetree(o)
|
1377
1610
|
last=last().parsetree(o)
|
1378
|
-
if
|
1379
|
-
|
1380
|
-
|
1611
|
+
if @as_flow_control
|
1612
|
+
if :lit==first.first and Integer===first.last
|
1613
|
+
first=[:call, [:lit, first.last], :==, [:array, [:gvar, :$.]]]
|
1614
|
+
elsif :lit==first.first && Regexp===first.last or
|
1615
|
+
:dregx==first.first || :dregx_once==first.first
|
1616
|
+
first=[:match, first]
|
1617
|
+
end
|
1618
|
+
|
1619
|
+
if :lit==last.first and Integer===last.last
|
1620
|
+
last=[:call, [:lit, last.last], :==, [:array, [:gvar, :$.]]]
|
1621
|
+
elsif :lit==last.first && Regexp===last.last or
|
1622
|
+
:dregx==last.first || :dregx_once==last.first
|
1623
|
+
last=[:match, last]
|
1624
|
+
end
|
1625
|
+
|
1626
|
+
tag="flip"
|
1627
|
+
else
|
1628
|
+
if :lit==first.first and :lit==last.first and
|
1629
|
+
Fixnum===first.last and Fixnum===last.last and
|
1630
|
+
LiteralNode===first() and LiteralNode===last()
|
1631
|
+
return [:lit, Range.new(first.last,last.last,@exclude_end)]
|
1632
|
+
end
|
1633
|
+
tag="dot"
|
1381
1634
|
end
|
1382
|
-
tag= @as_flow_control ? "flip" : "dot"
|
1383
1635
|
count= @exclude_end ? ?3 : ?2
|
1384
1636
|
tag << count
|
1385
1637
|
[tag.to_sym, first, last]
|
@@ -1400,8 +1652,8 @@ end
|
|
1400
1652
|
class UnOpNode<ValueNode
|
1401
1653
|
param_names(:op,:val)
|
1402
1654
|
def initialize(op,val)
|
1403
|
-
@offset
|
1404
|
-
op=op.ident
|
1655
|
+
@offset||=op.offset rescue val.offset
|
1656
|
+
op=op.ident if op.respond_to? :ident
|
1405
1657
|
/([&*])$/===op and op=$1+"@"
|
1406
1658
|
/^(?:!|not)$/===op and
|
1407
1659
|
val.respond_to? :special_conditions! and
|
@@ -1454,11 +1706,16 @@ end
|
|
1454
1706
|
end
|
1455
1707
|
|
1456
1708
|
class UnaryStarNode<UnOpNode
|
1457
|
-
def initialize(op,val)
|
1458
|
-
op
|
1709
|
+
def initialize(op,val=nil)
|
1710
|
+
op,val="*@",op unless val
|
1711
|
+
op.ident="*@" if op.respond_to? :ident
|
1459
1712
|
super(op,val)
|
1460
1713
|
end
|
1461
1714
|
|
1715
|
+
class<<self
|
1716
|
+
alias [] new
|
1717
|
+
end
|
1718
|
+
|
1462
1719
|
def parsetree(o)
|
1463
1720
|
[:splat, val.rescue_parsetree(o)]
|
1464
1721
|
end
|
@@ -1482,10 +1739,10 @@ end
|
|
1482
1739
|
|
1483
1740
|
class DanglingStarNode<UnaryStarNode
|
1484
1741
|
#param_names :op,:val
|
1485
|
-
def initialize(star)
|
1486
|
-
@offset= star.offset
|
1487
|
-
|
1488
|
-
var
|
1742
|
+
def initialize(star,var=nil)
|
1743
|
+
@offset= star.offset if star.respond_to? :offset
|
1744
|
+
@startline=@endline=star.startline if star.respond_to? :startline
|
1745
|
+
super('*@',var||VarNode[''])
|
1489
1746
|
end
|
1490
1747
|
attr :offset
|
1491
1748
|
def lvars_defined_in; [] end
|
@@ -1554,6 +1811,13 @@ end
|
|
1554
1811
|
end
|
1555
1812
|
attr_writer :lvalue
|
1556
1813
|
identity_param :lvalue, nil, true
|
1814
|
+
|
1815
|
+
def inspect label=nil,indent=0
|
1816
|
+
result=' '*indent
|
1817
|
+
result+="#{label}: " if label
|
1818
|
+
result+='Constant '
|
1819
|
+
result+=map{|name| name.inspect}.join(', ')+"\n"
|
1820
|
+
end
|
1557
1821
|
end
|
1558
1822
|
LookupNode=ConstantNode
|
1559
1823
|
|
@@ -1613,139 +1877,10 @@ end
|
|
1613
1877
|
attr_writer :lvalue
|
1614
1878
|
end
|
1615
1879
|
|
1616
|
-
=begin
|
1617
|
-
class OldParenedNode<ValueNode
|
1618
|
-
param_names :body, :rescues, :else!, :ensure!
|
1619
|
-
def initialize(*args)
|
1620
|
-
@empty_ensure=@op_rescue=nil
|
1621
|
-
replace(
|
1622
|
-
if args.size==3 #()
|
1623
|
-
if (KeywordToken===args.first and args.first.ident=='(')
|
1624
|
-
[args[1]]
|
1625
|
-
else
|
1626
|
-
expr,rescueword,backup=*args
|
1627
|
-
@op_rescue=true
|
1628
|
-
[expr,[RescueNode[[],nil,backup]],nil,nil]
|
1629
|
-
end
|
1630
|
-
else
|
1631
|
-
body,rescues,else_,ensure_=*args[1...-1]
|
1632
|
-
if else_
|
1633
|
-
else_=else_.val or @empty_else=true
|
1634
|
-
end
|
1635
|
-
if ensure_
|
1636
|
-
ensure_=ensure_.val or @empty_ensure=true
|
1637
|
-
end
|
1638
|
-
[body,rescues,else_,ensure_]
|
1639
|
-
end
|
1640
|
-
)
|
1641
|
-
end
|
1642
|
-
|
1643
|
-
alias ensure_ ensure
|
1644
|
-
alias else_ else
|
1645
|
-
|
1646
|
-
attr_reader :empty_ensure, :empty_else
|
1647
|
-
attr_accessor :after_comma, :after_equals
|
1648
|
-
def op?; @op_rescue; end
|
1649
|
-
|
1650
|
-
def image; '(begin)' end
|
1651
|
-
|
1652
|
-
def special_conditions!
|
1653
|
-
if size==1
|
1654
|
-
node=body
|
1655
|
-
node.special_conditions! if node.respond_to? :special_conditions!
|
1656
|
-
end
|
1657
|
-
end
|
1658
|
-
|
1659
|
-
def to_lisp
|
1660
|
-
huh #what about rescues, else, ensure?
|
1661
|
-
body.to_lisp
|
1662
|
-
end
|
1663
|
-
|
1664
|
-
def parsetree(o)
|
1665
|
-
if size==1
|
1666
|
-
body.parsetree(o)
|
1667
|
-
else
|
1668
|
-
body=body()
|
1669
|
-
target=result=[] #was: [:begin, ]
|
1670
|
-
|
1671
|
-
#body,rescues,else_,ensure_=*self
|
1672
|
-
target.push target=[:ensure, ] if ensure_ or @empty_ensure
|
1673
|
-
|
1674
|
-
rescues=rescues().map{|resc| resc.parsetree(o)}
|
1675
|
-
if rescues.empty?
|
1676
|
-
else_ and
|
1677
|
-
body=SequenceNode.new(body,nil,else_)
|
1678
|
-
else_=nil
|
1679
|
-
else
|
1680
|
-
target.push newtarget=[:rescue, ]
|
1681
|
-
else_=else_()
|
1682
|
-
end
|
1683
|
-
if body
|
1684
|
-
needbegin= (BeginNode===body and body.after_equals)
|
1685
|
-
body=body.parsetree(o)
|
1686
|
-
body=[:begin, body] if needbegin and body.first!=:begin and !o[:ruby187]
|
1687
|
-
(newtarget||target).push body if body
|
1688
|
-
end
|
1689
|
-
target.push ensure_.parsetree(o) if ensure_
|
1690
|
-
target.push [:nil] if @empty_ensure
|
1691
|
-
target=newtarget if newtarget
|
1692
|
-
|
1693
|
-
unless rescues.empty?
|
1694
|
-
target.push linked_list(rescues)
|
1695
|
-
end
|
1696
|
-
target.push else_.parsetree(o) if else_ #and !body
|
1697
|
-
result.size==0 and result=[[:nil]]
|
1698
|
-
result=result.last #if @op_rescue
|
1699
|
-
result=[:begin,result] unless o[:ruby187]||op?||result==[:nil]#||result.first==:begin
|
1700
|
-
result
|
1701
|
-
end
|
1702
|
-
end
|
1703
|
-
|
1704
|
-
def rescue_parsetree o
|
1705
|
-
result=parsetree o
|
1706
|
-
result.first==:begin and result=result.last unless o[:ruby187]
|
1707
|
-
result
|
1708
|
-
end
|
1709
|
-
|
1710
|
-
def begin_parsetree(o)
|
1711
|
-
body,rescues,else_,ensure_=*self
|
1712
|
-
needbegin=(rescues&&!rescues.empty?) || ensure_ || @empty_ensure
|
1713
|
-
result=parsetree(o)
|
1714
|
-
needbegin and result=[:begin, result] unless result.first==:begin
|
1715
|
-
result
|
1716
|
-
end
|
1717
|
-
|
1718
|
-
def lvalue
|
1719
|
-
return nil unless size==1
|
1720
|
-
# case first
|
1721
|
-
# when CommaOpNode,UnaryStarNode: #do nothing
|
1722
|
-
# when ParenedNode: return first.lvalue
|
1723
|
-
# else return nil
|
1724
|
-
# end
|
1725
|
-
|
1726
|
-
return @lvalue if defined? @lvalue
|
1727
|
-
@lvalue=true
|
1728
|
-
end
|
1729
|
-
attr_writer :lvalue
|
1730
|
-
|
1731
|
-
def unparse(o=default_unparse_options)
|
1732
|
-
if size==1
|
1733
|
-
"("+(body&&body.unparse(o))+")"
|
1734
|
-
else
|
1735
|
-
result="begin "
|
1736
|
-
body&&result+= body.unparse(o)
|
1737
|
-
result+=unparse_nl(rescues.first,o)
|
1738
|
-
rescues.each{|resc| result+=resc.unparse(o) }
|
1739
|
-
result+=unparse_nl(ensure_,o)+"ensure "+ensure_.unparse(o) if ensure_
|
1740
|
-
result+=unparse_nl(else_,o)+"else "+else_.unparse(o) if else_
|
1741
|
-
result+=";end"
|
1742
|
-
end
|
1743
|
-
end
|
1744
|
-
end
|
1745
|
-
=end
|
1746
|
-
|
1747
1880
|
class ParenedNode<ValueNode
|
1748
|
-
param_names :body
|
1881
|
+
param_names :body
|
1882
|
+
alias val body
|
1883
|
+
alias val= body=
|
1749
1884
|
def initialize(lparen,body,rparen)
|
1750
1885
|
@offset=lparen.offset
|
1751
1886
|
self[0]=body
|
@@ -1825,7 +1960,11 @@ end
|
|
1825
1960
|
end
|
1826
1961
|
target.push else_.parsetree(o) if else_ #and !body
|
1827
1962
|
result.size==0 and result=[[:nil]]
|
1828
|
-
|
1963
|
+
if o[:ruby187] and !rescues.empty?
|
1964
|
+
result.unshift :begin
|
1965
|
+
else
|
1966
|
+
result=result.last
|
1967
|
+
end
|
1829
1968
|
result
|
1830
1969
|
end
|
1831
1970
|
|
@@ -1839,7 +1978,7 @@ end
|
|
1839
1978
|
result+=unparse_nl(ensure_,o)+"ensure "+ensure_.unparse(o) if ensure_
|
1840
1979
|
result+=";ensure" if @empty_ensure
|
1841
1980
|
return result
|
1842
|
-
|
1981
|
+
end
|
1843
1982
|
|
1844
1983
|
end
|
1845
1984
|
|
@@ -1887,7 +2026,11 @@ end
|
|
1887
2026
|
|
1888
2027
|
def parsetree(o)
|
1889
2028
|
result=parsetree_and_rescues(o)
|
1890
|
-
|
2029
|
+
if o[:ruby187] and result.first==:begin
|
2030
|
+
result=result[1]
|
2031
|
+
else
|
2032
|
+
result=[:begin,result] unless result==[:nil]#||result.first==:begin
|
2033
|
+
end
|
1891
2034
|
return result
|
1892
2035
|
end
|
1893
2036
|
|
@@ -1917,8 +2060,14 @@ end
|
|
1917
2060
|
end
|
1918
2061
|
end
|
1919
2062
|
|
1920
|
-
|
1921
|
-
|
2063
|
+
module KeywordOpNode
|
2064
|
+
def unparse o=default_unparse_options
|
2065
|
+
[left.unparse(o),' ',op,' ',right.unparse(o)].join
|
2066
|
+
end
|
2067
|
+
end
|
2068
|
+
|
2069
|
+
class RescueOpNode<RawOpNode
|
2070
|
+
include KeywordOpNode
|
1922
2071
|
param_names :body, :rescues #, :else!, :ensure!
|
1923
2072
|
def initialize(expr,rescueword,backup)
|
1924
2073
|
replace [expr,[RescueNode[[],nil,backup]].extend(ListInNode)]
|
@@ -1928,7 +2077,7 @@ end
|
|
1928
2077
|
def ensure; nil end
|
1929
2078
|
|
1930
2079
|
def left; body end
|
1931
|
-
def right; rescues.action end
|
2080
|
+
def right; rescues[0].action end
|
1932
2081
|
|
1933
2082
|
alias ensure_ ensure
|
1934
2083
|
alias else_ else
|
@@ -2015,12 +2164,34 @@ end
|
|
2015
2164
|
param_names :left,:op,:right
|
2016
2165
|
alias lhs left
|
2017
2166
|
alias rhs right
|
2167
|
+
def self.create(*args)
|
2168
|
+
if args.size==5
|
2169
|
+
if args[3].ident=="rescue3"
|
2170
|
+
lhs,op,rescuee,op2,rescuer=*args
|
2171
|
+
if MULTIASSIGN===lhs or !rescuee.is_list
|
2172
|
+
return RescueOpNode.new(AssignNode.new(lhs,op,rescuee),nil,rescuer)
|
2173
|
+
else
|
2174
|
+
rhs=RescueOpNode.new(rescuee.val,op2,rescuer)
|
2175
|
+
end
|
2176
|
+
else
|
2177
|
+
lhs,op,bogus1,rhs,bogus2=*args
|
2178
|
+
end
|
2179
|
+
super(lhs,op,rhs)
|
2180
|
+
else super
|
2181
|
+
end
|
2182
|
+
end
|
2183
|
+
|
2018
2184
|
def initialize(*args)
|
2019
2185
|
|
2020
2186
|
if args.size==5
|
2187
|
+
#this branch should be dead now
|
2021
2188
|
if args[3].ident=="rescue3"
|
2022
2189
|
lhs,op,rescuee,op2,rescuer=*args
|
2023
|
-
|
2190
|
+
if MULTIASSIGN===lhs or rescuee.is_list?
|
2191
|
+
huh
|
2192
|
+
else
|
2193
|
+
rhs=RescueOpNode.new(rescuee.val,op2,rescuer)
|
2194
|
+
end
|
2024
2195
|
else
|
2025
2196
|
lhs,op,bogus1,rhs,bogus2=*args
|
2026
2197
|
end
|
@@ -2033,14 +2204,20 @@ end
|
|
2033
2204
|
lhs=MultiAssign.new([lhs]) unless lhs.after_comma
|
2034
2205
|
when ParenedNode
|
2035
2206
|
if !lhs.after_comma #look for () around lhs
|
2036
|
-
|
2037
|
-
|
2038
|
-
|
2039
|
-
lhs
|
2040
|
-
|
2041
|
-
|
2207
|
+
if CommaOpNode===lhs.first
|
2208
|
+
lhs=MultiAssign.new(Array.new(lhs.first))
|
2209
|
+
@lhs_parens=true
|
2210
|
+
elsif UnaryStarNode===lhs.first
|
2211
|
+
lhs=MultiAssign.new([lhs.first])
|
2212
|
+
@lhs_parens=true
|
2213
|
+
elsif ParenedNode===lhs.first
|
2214
|
+
@lhs_parens=true
|
2215
|
+
lhs=lhs.first
|
2216
|
+
else
|
2217
|
+
lhs=lhs.first
|
2218
|
+
end
|
2042
2219
|
end
|
2043
|
-
when CommaOpNode
|
2220
|
+
when CommaOpNode
|
2044
2221
|
lhs=MultiAssign.new lhs
|
2045
2222
|
#rhs=Array.new(rhs) if CommaOpNode===rhs
|
2046
2223
|
end
|
@@ -2402,8 +2579,7 @@ end
|
|
2402
2579
|
# [:masgn, *super]
|
2403
2580
|
# end
|
2404
2581
|
def unparse o=default_unparse_options
|
2405
|
-
"("+super+")"
|
2406
|
-
|
2582
|
+
"("+super+")"
|
2407
2583
|
end
|
2408
2584
|
end
|
2409
2585
|
|
@@ -2465,15 +2641,20 @@ end
|
|
2465
2641
|
end
|
2466
2642
|
end
|
2467
2643
|
|
2468
|
-
|
2469
|
-
|
2470
|
-
|
2644
|
+
class LogicalNode
|
2645
|
+
include KeywordOpNode
|
2646
|
+
|
2647
|
+
def self.[](*list)
|
2648
|
+
options=list.pop if Hash===list.last
|
2649
|
+
result=allocate.replace list
|
2650
|
+
opmap=options[:@opmap] if options and options[:@opmap]
|
2651
|
+
opmap||=result.op[0,1]*(list.size-1)
|
2652
|
+
result.instance_variable_set(:@opmap, opmap)
|
2653
|
+
return result
|
2471
2654
|
end
|
2472
|
-
end
|
2473
2655
|
|
2474
|
-
module LogicalNode
|
2475
|
-
include KeywordOpNode
|
2476
2656
|
def initialize(left,op,right)
|
2657
|
+
op=op.ident if op.respond_to? :ident
|
2477
2658
|
@opmap=op[0,1]
|
2478
2659
|
case op
|
2479
2660
|
when "&&"; op="and"
|
@@ -2481,11 +2662,10 @@ end
|
|
2481
2662
|
end
|
2482
2663
|
#@reverse= op=="or"
|
2483
2664
|
#@op=op
|
2484
|
-
@module=LogicalNode
|
2485
2665
|
replace [left,right]
|
2486
2666
|
(size-1).downto(0){|i|
|
2487
2667
|
expr=self[i]
|
2488
|
-
if
|
2668
|
+
if self.class==expr.class
|
2489
2669
|
self[i,1]=Array.new expr
|
2490
2670
|
opmap[i,0]=expr.opmap
|
2491
2671
|
end
|
@@ -2496,15 +2676,6 @@ end
|
|
2496
2676
|
OP_EXPAND={?o=>"or", ?a=>"and", ?&=>"&&", ?|=>"||", nil=>""}
|
2497
2677
|
OP_EQUIV={?o=>"or", ?a=>"and", ?&=>"and", ?|=>"or"}
|
2498
2678
|
|
2499
|
-
def reverse
|
2500
|
-
/\A[o|]/===@opmap
|
2501
|
-
end
|
2502
|
-
def op
|
2503
|
-
OP_EQUIV[@opmap[0]]
|
2504
|
-
end
|
2505
|
-
|
2506
|
-
#these 3 methods are defined in RawOpNode too, hence these
|
2507
|
-
#definitions are ignored. grrrrrrr.
|
2508
2679
|
def unparse o=default_unparse_options
|
2509
2680
|
result=''
|
2510
2681
|
|
@@ -2516,11 +2687,18 @@ end
|
|
2516
2687
|
}
|
2517
2688
|
return result
|
2518
2689
|
end
|
2519
|
-
|
2520
|
-
|
2690
|
+
|
2691
|
+
def left
|
2692
|
+
self[0]
|
2693
|
+
end
|
2694
|
+
def left= val
|
2695
|
+
self[0]=val
|
2521
2696
|
end
|
2522
|
-
def right
|
2523
|
-
|
2697
|
+
def right
|
2698
|
+
self[1]
|
2699
|
+
end
|
2700
|
+
def right= val
|
2701
|
+
self[1]=val
|
2524
2702
|
end
|
2525
2703
|
|
2526
2704
|
def parsetree(o)
|
@@ -2542,21 +2720,44 @@ end
|
|
2542
2720
|
end
|
2543
2721
|
end
|
2544
2722
|
|
2545
|
-
|
2723
|
+
class AndNode<LogicalNode
|
2724
|
+
def reverse
|
2725
|
+
false
|
2726
|
+
end
|
2727
|
+
|
2728
|
+
def op
|
2729
|
+
"and"
|
2730
|
+
end
|
2731
|
+
end
|
2732
|
+
|
2733
|
+
class OrNode<LogicalNode
|
2734
|
+
def reverse
|
2735
|
+
true
|
2736
|
+
end
|
2737
|
+
|
2738
|
+
def op
|
2739
|
+
"or"
|
2740
|
+
end
|
2741
|
+
end
|
2742
|
+
|
2743
|
+
class WhileOpNode
|
2546
2744
|
include KeywordOpNode
|
2745
|
+
param_names :left, :op_, :right
|
2547
2746
|
def condition; right end
|
2548
2747
|
def consequent; left end
|
2549
|
-
def initialize(val1,op,val2)
|
2550
|
-
|
2748
|
+
def initialize(val1,op,val2=nil)
|
2749
|
+
op,val2=nil,op unless val2
|
2750
|
+
op=op.ident if op.respond_to? :ident
|
2551
2751
|
@reverse=false
|
2552
|
-
@module=WhileOpNode
|
2553
2752
|
@loop=true
|
2554
2753
|
@test_first= !( BeginNode===val1 )
|
2754
|
+
replace [val1,val2]
|
2555
2755
|
condition.special_conditions! if condition.respond_to? :special_conditions!
|
2556
2756
|
end
|
2557
2757
|
|
2558
2758
|
def while; condition end
|
2559
2759
|
def do; consequent end
|
2760
|
+
def op; "while" end
|
2560
2761
|
|
2561
2762
|
def parsetree(o)
|
2562
2763
|
cond=condition.rescue_parsetree(o)
|
@@ -2577,21 +2778,24 @@ end
|
|
2577
2778
|
|
2578
2779
|
end
|
2579
2780
|
|
2580
|
-
|
2781
|
+
class UntilOpNode
|
2581
2782
|
include KeywordOpNode
|
2783
|
+
param_names :left,:op_,:right
|
2582
2784
|
def condition; right end
|
2583
2785
|
def consequent; left end
|
2584
|
-
def initialize(val1,op,val2)
|
2585
|
-
|
2786
|
+
def initialize(val1,op,val2=nil)
|
2787
|
+
op,val2=nil,op unless val2
|
2788
|
+
op=op.ident if op.respond_to? :ident
|
2586
2789
|
@reverse=true
|
2587
2790
|
@loop=true
|
2588
2791
|
@test_first= !( BeginNode===val1 )
|
2589
|
-
|
2792
|
+
replace [val1,val2]
|
2590
2793
|
condition.special_conditions! if condition.respond_to? :special_conditions!
|
2591
2794
|
end
|
2592
2795
|
|
2593
2796
|
def while; negate condition end
|
2594
2797
|
def do; consequent end
|
2798
|
+
def op; "until" end
|
2595
2799
|
|
2596
2800
|
def parsetree(o)
|
2597
2801
|
cond=condition.rescue_parsetree(o)
|
@@ -2614,15 +2818,17 @@ end
|
|
2614
2818
|
end
|
2615
2819
|
end
|
2616
2820
|
|
2617
|
-
|
2821
|
+
class UnlessOpNode
|
2618
2822
|
include KeywordOpNode
|
2823
|
+
param_names :left, :op_, :right
|
2619
2824
|
def condition; right end
|
2620
2825
|
def consequent; left end
|
2621
|
-
def initialize(val1,op,val2)
|
2622
|
-
|
2826
|
+
def initialize(val1,op,val2=nil)
|
2827
|
+
op,val2=nil,op unless val2
|
2828
|
+
op=op.ident if op.respond_to? :ident
|
2623
2829
|
@reverse=true
|
2624
2830
|
@loop=false
|
2625
|
-
|
2831
|
+
replace [val1,val2]
|
2626
2832
|
condition.special_conditions! if condition.respond_to? :special_conditions!
|
2627
2833
|
end
|
2628
2834
|
|
@@ -2630,6 +2836,7 @@ end
|
|
2630
2836
|
def then; nil end
|
2631
2837
|
def else; consequent end
|
2632
2838
|
def elsifs; [] end
|
2839
|
+
def op; "unless" end
|
2633
2840
|
|
2634
2841
|
def parsetree(o)
|
2635
2842
|
cond=condition.rescue_parsetree(o)
|
@@ -2642,15 +2849,17 @@ end
|
|
2642
2849
|
end
|
2643
2850
|
end
|
2644
2851
|
|
2645
|
-
|
2852
|
+
class IfOpNode
|
2853
|
+
param_names :left,:op_,:right
|
2646
2854
|
include KeywordOpNode
|
2647
2855
|
def condition; right end
|
2648
2856
|
def consequent; left end
|
2649
|
-
def initialize(left,op,right)
|
2650
|
-
|
2857
|
+
def initialize(left,op,right=nil)
|
2858
|
+
op,right=nil,op unless right
|
2859
|
+
op=op.ident if op.respond_to? :ident
|
2651
2860
|
@reverse=false
|
2652
2861
|
@loop=false
|
2653
|
-
|
2862
|
+
replace [left,right]
|
2654
2863
|
condition.special_conditions! if condition.respond_to? :special_conditions!
|
2655
2864
|
end
|
2656
2865
|
|
@@ -2658,6 +2867,7 @@ end
|
|
2658
2867
|
def then; consequent end
|
2659
2868
|
def else; nil end
|
2660
2869
|
def elsifs; [] end
|
2870
|
+
def op; "if" end
|
2661
2871
|
|
2662
2872
|
def parsetree(o)
|
2663
2873
|
cond=condition.rescue_parsetree(o)
|
@@ -2684,23 +2894,9 @@ end
|
|
2684
2894
|
#handle inlined hash pairs in param list (if any)
|
2685
2895
|
# compr=Object.new
|
2686
2896
|
# def compr.==(other) ArrowOpNode===other end
|
2897
|
+
h,arrowrange=param_list.extract_unbraced_hash
|
2687
2898
|
param_list=Array.new(param_list)
|
2688
|
-
|
2689
|
-
param_list.each_with_index{|param,i|
|
2690
|
-
break first=i if ArrowOpNode===param
|
2691
|
-
}
|
2692
|
-
(1..param_list.size).each{|i| param=param_list[-i]
|
2693
|
-
break last=-i if ArrowOpNode===param
|
2694
|
-
}
|
2695
|
-
if first
|
2696
|
-
arrowrange=first..last
|
2697
|
-
arrows=param_list[arrowrange]
|
2698
|
-
h=HashLiteralNode.new(nil,arrows,nil)
|
2699
|
-
h.offset=arrows.first.offset
|
2700
|
-
h.startline=arrows.first.startline
|
2701
|
-
h.endline=arrows.last.endline
|
2702
|
-
param_list[arrowrange]=[h]
|
2703
|
-
end
|
2899
|
+
param_list[arrowrange]=[h] if arrowrange
|
2704
2900
|
|
2705
2901
|
when ArrowOpNode
|
2706
2902
|
h=HashLiteralNode.new(nil,param_list,nil)
|
@@ -2726,11 +2922,13 @@ end
|
|
2726
2922
|
method=method.ident
|
2727
2923
|
fail unless String===method
|
2728
2924
|
end
|
2925
|
+
|
2729
2926
|
super(nil,method,param_list,blockparams,block)
|
2730
2927
|
#receiver, if any, is tacked on later
|
2731
2928
|
end
|
2732
2929
|
|
2733
2930
|
def real_parens; !@not_real_parens end
|
2931
|
+
def real_parens= x; @not_real_parens=!x end
|
2734
2932
|
|
2735
2933
|
def unparse o=default_unparse_options
|
2736
2934
|
fail if block==false
|
@@ -2743,12 +2941,13 @@ end
|
|
2743
2941
|
block&&[
|
2744
2942
|
@do_end ? " do " : "{",
|
2745
2943
|
block_params&&block_params.unparse(o),
|
2746
|
-
" ",
|
2944
|
+
unparse_nl(block,o," "),
|
2747
2945
|
block.unparse(o),
|
2946
|
+
unparse_nl(endline,o),
|
2748
2947
|
@do_end ? " end" : "}"
|
2749
2948
|
]
|
2750
2949
|
]
|
2751
|
-
return result.
|
2950
|
+
return result.join
|
2752
2951
|
end
|
2753
2952
|
|
2754
2953
|
def image
|
@@ -2756,7 +2955,8 @@ end
|
|
2756
2955
|
end
|
2757
2956
|
|
2758
2957
|
def with_commas
|
2759
|
-
!real_parens and
|
2958
|
+
!real_parens and
|
2959
|
+
args and args.size>0
|
2760
2960
|
end
|
2761
2961
|
|
2762
2962
|
# identity_param :with_commas, false, true
|
@@ -2796,6 +2996,7 @@ end
|
|
2796
2996
|
lasti=args.size-1
|
2797
2997
|
end
|
2798
2998
|
methodname= name
|
2999
|
+
methodname= methodname.chop if /^[~!]@$/===methodname
|
2799
3000
|
methodsym=methodname.to_sym
|
2800
3001
|
is_kw= RubyLexer::FUNCLIKE_KEYWORDS&~/^(BEGIN|END|raise)$/===methodname
|
2801
3002
|
|
@@ -2990,6 +3191,7 @@ end
|
|
2990
3191
|
param_names :params,:body
|
2991
3192
|
def initialize(open_brace,formals,stmts,close_brace)
|
2992
3193
|
stmts||=SequenceNode[{:@offset => open_brace.offset, :@startline=>open_brace.startline}]
|
3194
|
+
stmts=SequenceNode[stmts,{:@offset => open_brace.offset, :@startline=>open_brace.startline}] unless SequenceNode===stmts
|
2993
3195
|
|
2994
3196
|
formals&&=BlockParams.new(Array.new(formals))
|
2995
3197
|
@do_end=true unless open_brace.not_real?
|
@@ -3147,9 +3349,9 @@ end
|
|
3147
3349
|
newdata=with_string_data(*tokens)
|
3148
3350
|
|
3149
3351
|
case token
|
3150
|
-
when HereDocNode
|
3352
|
+
when HereDocNode
|
3151
3353
|
token.list_to_append=newdata
|
3152
|
-
when StringNode
|
3354
|
+
when StringNode #do nothing
|
3153
3355
|
else fail "non-string token class used to construct string node"
|
3154
3356
|
end
|
3155
3357
|
replace token.data
|
@@ -3167,7 +3369,7 @@ end
|
|
3167
3369
|
EVEN_NUM_BSLASHES=/(^|[^\\])((?:\\\\)*)/
|
3168
3370
|
def unparse o=default_unparse_options
|
3169
3371
|
o[:linenum]+=@open.count("\n")
|
3170
|
-
result=[@open,unparse_interior(o),@close,@modifiers].
|
3372
|
+
result=[@open,unparse_interior(o),@close,@modifiers].join
|
3171
3373
|
o[:linenum]+=@close.count("\n")
|
3172
3374
|
return result
|
3173
3375
|
end
|
@@ -3255,7 +3457,7 @@ end
|
|
3255
3457
|
#parse the token list in the string inclusion
|
3256
3458
|
parser=Thread.current[:$RedParse_parser]
|
3257
3459
|
klass=parser.class
|
3258
|
-
data[i]=klass.new(tokens, "(string inclusion)",1,[]
|
3460
|
+
data[i]=klass.new(tokens, "(string inclusion)",1,[],:rubyversion=>parser.rubyversion,:cache_mode=>:none).parse
|
3259
3461
|
end
|
3260
3462
|
} #if data
|
3261
3463
|
# was_nul_header= (String===data.first and data.first.empty?) #and o[:quirks]
|
@@ -3403,7 +3605,7 @@ end
|
|
3403
3605
|
when '/'
|
3404
3606
|
numopts=0
|
3405
3607
|
charset=0
|
3406
|
-
@modifiers
|
3608
|
+
RubyLexer::CharHandler.each_char(@modifiers){|ch|
|
3407
3609
|
if ch==?o
|
3408
3610
|
type=:dregx_once
|
3409
3611
|
elsif numopt=CHAROPT2NUM[ch].nonzero?
|
@@ -3474,7 +3676,7 @@ end
|
|
3474
3676
|
when '/'
|
3475
3677
|
type=:dregx
|
3476
3678
|
numopts=charset=0
|
3477
|
-
@modifiers
|
3679
|
+
RubyLexer::CharHandler.each_char(@modifiers){|ch|
|
3478
3680
|
if ch==?o
|
3479
3681
|
type=:dregx_once
|
3480
3682
|
elsif numopt=CHAROPT2NUM[ch].nonzero?
|
@@ -3527,7 +3729,13 @@ end
|
|
3527
3729
|
end
|
3528
3730
|
|
3529
3731
|
if vals.size==1
|
3530
|
-
|
3732
|
+
if :dregx==type or :dregx_once==type
|
3733
|
+
lang=@modifiers.tr_s("^nesuNESU","")
|
3734
|
+
lang=lang[-1,1] unless lang.empty?
|
3735
|
+
lang.downcase!
|
3736
|
+
regex_options=nil
|
3737
|
+
vals=[Regexp_new( vals.first,numopts,lang )]
|
3738
|
+
end
|
3531
3739
|
type=DOWNSHIFT_STRING_TYPE[type]
|
3532
3740
|
end
|
3533
3741
|
result= vals.unshift(type)
|
@@ -3536,6 +3744,25 @@ end
|
|
3536
3744
|
result=[:match, result] if defined? @implicit_match and @implicit_match
|
3537
3745
|
return result
|
3538
3746
|
end
|
3747
|
+
|
3748
|
+
if //.respond_to? :encoding
|
3749
|
+
LETTER2ENCODING={
|
3750
|
+
?n => Encoding::ASCII,
|
3751
|
+
?u => Encoding::UTF_8,
|
3752
|
+
?e => Encoding::EUC_JP,
|
3753
|
+
?s => Encoding::SJIS,
|
3754
|
+
"" => Encoding::ASCII
|
3755
|
+
}
|
3756
|
+
def Regexp_new(src,opts,lang)
|
3757
|
+
src.encode!(LETTER2ENCODING[lang])
|
3758
|
+
Regexp.new(src,opts)
|
3759
|
+
end
|
3760
|
+
else
|
3761
|
+
def Regexp_new(src,opts,lang)
|
3762
|
+
Regexp.new(src,opts,lang)
|
3763
|
+
end
|
3764
|
+
end
|
3765
|
+
|
3539
3766
|
end
|
3540
3767
|
|
3541
3768
|
class HereDocNode<StringNode
|
@@ -3564,7 +3791,8 @@ end
|
|
3564
3791
|
end
|
3565
3792
|
|
3566
3793
|
|
3567
|
-
|
3794
|
+
#ignore instance vars in here documents when testing equality
|
3795
|
+
def flattened_ivars_equal?(other)
|
3568
3796
|
StringNode===other
|
3569
3797
|
end
|
3570
3798
|
|
@@ -3581,7 +3809,7 @@ end
|
|
3581
3809
|
else fail
|
3582
3810
|
end
|
3583
3811
|
|
3584
|
-
[lead,@char, inner, @char].
|
3812
|
+
[lead,@char, inner, @char].join
|
3585
3813
|
end
|
3586
3814
|
end
|
3587
3815
|
|
@@ -3598,17 +3826,19 @@ end
|
|
3598
3826
|
assert !old_val.raw.has_str_inc?
|
3599
3827
|
val=old_val.raw.translate_escapes(old_val.raw.elems.first).to_sym
|
3600
3828
|
when ?" #"
|
3601
|
-
if old_val.raw.has_str_inc?
|
3829
|
+
if old_val.raw.has_str_inc? or old_val.raw.elems==[""]
|
3602
3830
|
val=StringNode.new(old_val.raw) #ugly hack: this isn't literal
|
3603
3831
|
else
|
3604
3832
|
val=old_val.raw.translate_escapes(old_val.raw.elems.first).to_sym
|
3605
3833
|
end
|
3606
3834
|
else #val=val[1..-1].to_sym
|
3607
|
-
|
3608
|
-
|
3609
|
-
|
3610
|
-
|
3835
|
+
val=old_val.raw
|
3836
|
+
if StringToken===val
|
3837
|
+
val=val.translate_escapes(val.elems.first)
|
3838
|
+
elsif /^[!~]@$/===val
|
3839
|
+
val=val.chop
|
3611
3840
|
end
|
3841
|
+
val=val.to_sym
|
3612
3842
|
end
|
3613
3843
|
when NumberToken
|
3614
3844
|
case val
|
@@ -3651,7 +3881,8 @@ end
|
|
3651
3881
|
":"+
|
3652
3882
|
val.unparse(o)
|
3653
3883
|
when Float
|
3654
|
-
s=
|
3884
|
+
s= val.accurate_to_s
|
3885
|
+
#why must it be *2? I wouldn't think any fudge factor would be necessary
|
3655
3886
|
case s
|
3656
3887
|
when /-inf/i; s="-"+Inf
|
3657
3888
|
when /inf/i; s= Inf
|
@@ -3700,7 +3931,7 @@ end
|
|
3700
3931
|
if name.ident=='('
|
3701
3932
|
#simulate nil
|
3702
3933
|
replace ['nil']
|
3703
|
-
@value=
|
3934
|
+
@value=nil
|
3704
3935
|
else
|
3705
3936
|
replace [name.ident]
|
3706
3937
|
@value=name.respond_to?(:value) && name.value
|
@@ -3739,7 +3970,14 @@ end
|
|
3739
3970
|
@offset=lbrack.offset
|
3740
3971
|
contents or return super()
|
3741
3972
|
if CommaOpNode===contents
|
3973
|
+
h,arrowrange=contents.extract_unbraced_hash
|
3974
|
+
contents[arrowrange]=[h] if arrowrange
|
3742
3975
|
super( *contents )
|
3976
|
+
elsif ArrowOpNode===contents
|
3977
|
+
h=HashLiteralNode.new(nil,contents,nil)
|
3978
|
+
h.startline=contents.startline
|
3979
|
+
h.endline=contents.endline
|
3980
|
+
super HashLiteralNode.new(nil,contents,nil)
|
3743
3981
|
else
|
3744
3982
|
super contents
|
3745
3983
|
end
|
@@ -3820,7 +4058,7 @@ end
|
|
3820
4058
|
result=@reverse ? "unless " : "if "
|
3821
4059
|
result+="#{condition.unparse o}"
|
3822
4060
|
result+=unparse_nl(consequent,o)+"#{consequent.unparse(o)}" if consequent
|
3823
|
-
result+=unparse_nl(elsifs.first,o)+elsifs.map{|n| n.unparse(o)}.
|
4061
|
+
result+=unparse_nl(elsifs.first,o)+elsifs.map{|n| n.unparse(o)}.join if elsifs
|
3824
4062
|
result+=unparse_nl(else_,o)+"else "+else_.unparse(o) if else_
|
3825
4063
|
result+=";else " if defined? @empty_else
|
3826
4064
|
result+=";end"
|
@@ -3914,7 +4152,7 @@ end
|
|
3914
4152
|
def image; "(elsif)" end
|
3915
4153
|
|
3916
4154
|
def unparse o=default_unparse_options
|
3917
|
-
"elsif #{condition.unparse o}#{unparse_nl(consequent,o)}#{consequent.unparse o};"
|
4155
|
+
"elsif #{condition.unparse o}#{unparse_nl(consequent,o)}#{consequent.unparse o if consequent};"
|
3918
4156
|
end
|
3919
4157
|
|
3920
4158
|
def to_lisp
|
@@ -3946,7 +4184,7 @@ end
|
|
3946
4184
|
condition.unparse(o), unparse_nl(body||self,o),
|
3947
4185
|
body&&body.unparse(o),
|
3948
4186
|
";end"
|
3949
|
-
].
|
4187
|
+
].join
|
3950
4188
|
end
|
3951
4189
|
|
3952
4190
|
def while
|
@@ -3982,7 +4220,10 @@ end
|
|
3982
4220
|
def initialize(caseword, condition, semi, whens, otherwise, endword)
|
3983
4221
|
@offset=caseword.offset
|
3984
4222
|
if otherwise
|
3985
|
-
otherwise=otherwise.val
|
4223
|
+
otherwise=otherwise.val
|
4224
|
+
@empty_else=!otherwise
|
4225
|
+
else
|
4226
|
+
@empty_else=false
|
3986
4227
|
end
|
3987
4228
|
whens.extend ListInNode
|
3988
4229
|
super(condition,whens,otherwise)
|
@@ -3992,9 +4233,10 @@ end
|
|
3992
4233
|
|
3993
4234
|
def unparse o=default_unparse_options
|
3994
4235
|
result="case #{condition&&condition.unparse(o)}"+
|
3995
|
-
whens.map{|wh| wh.unparse o}.
|
4236
|
+
whens.map{|wh| wh.unparse o}.join
|
3996
4237
|
|
3997
4238
|
result += unparse_nl(otherwise,o)+"else "+otherwise.unparse(o) if otherwise
|
4239
|
+
result += ";else;" if @empty_else
|
3998
4240
|
result += ";end"
|
3999
4241
|
|
4000
4242
|
return result
|
@@ -4013,6 +4255,7 @@ end
|
|
4013
4255
|
result=[:case, condition&&condition.parsetree(o)]+
|
4014
4256
|
whens.map{|whennode| whennode.parsetree(o)}
|
4015
4257
|
other=otherwise&&otherwise.parsetree(o)
|
4258
|
+
return [] if result==[:case, nil] and !other
|
4016
4259
|
if other and other[0..1]==[:case, nil] and !condition
|
4017
4260
|
result.concat other[2..-1]
|
4018
4261
|
else
|
@@ -4123,7 +4366,12 @@ end
|
|
4123
4366
|
=end
|
4124
4367
|
|
4125
4368
|
vars=self.for.lvalue_parsetree(o)
|
4126
|
-
|
4369
|
+
collection= self.in.begin_parsetree(o)
|
4370
|
+
if ParenedNode===self.in and collection.first==:begin
|
4371
|
+
assert collection.size==2
|
4372
|
+
collection=collection[1]
|
4373
|
+
end
|
4374
|
+
result=[:for, collection, vars]
|
4127
4375
|
result.push self.do.parsetree(o) if self.do
|
4128
4376
|
result
|
4129
4377
|
end
|
@@ -4149,11 +4397,13 @@ end
|
|
4149
4397
|
data=Array[*contents]
|
4150
4398
|
end
|
4151
4399
|
super(*data)
|
4400
|
+
else fail
|
4152
4401
|
end
|
4153
4402
|
@no_braces=!open
|
4154
4403
|
end
|
4155
4404
|
|
4156
4405
|
attr :no_arrows
|
4406
|
+
attr_accessor :no_braces
|
4157
4407
|
attr_writer :offset
|
4158
4408
|
|
4159
4409
|
def image; "({})" end
|
@@ -4272,6 +4522,9 @@ end
|
|
4272
4522
|
|
4273
4523
|
attr_reader :empty_ensure, :empty_else
|
4274
4524
|
|
4525
|
+
def self.namelist
|
4526
|
+
%w[receiver name args body rescues elses ensures]
|
4527
|
+
end
|
4275
4528
|
|
4276
4529
|
# def receiver= x
|
4277
4530
|
# self[0]=x
|
@@ -4296,7 +4549,7 @@ end
|
|
4296
4549
|
def unparse o=default_unparse_options
|
4297
4550
|
result=[
|
4298
4551
|
"def ",receiver&&receiver.unparse(o)+'.',name,
|
4299
|
-
args
|
4552
|
+
args && '('+args.map{|arg| arg.unparse o}.join(',')+')', unparse_nl(body||self,o)
|
4300
4553
|
]
|
4301
4554
|
result<<unparse_and_rescues(o)
|
4302
4555
|
=begin
|
@@ -4309,7 +4562,7 @@ end
|
|
4309
4562
|
result+="ensure\n" if @empty_ensure
|
4310
4563
|
=end
|
4311
4564
|
result<<unparse_nl(endline,o)+"end"
|
4312
|
-
result.
|
4565
|
+
result.join
|
4313
4566
|
end
|
4314
4567
|
|
4315
4568
|
def to_lisp
|
@@ -4318,7 +4571,9 @@ end
|
|
4318
4571
|
end
|
4319
4572
|
|
4320
4573
|
def parsetree(o)
|
4321
|
-
name=name()
|
4574
|
+
name=name()
|
4575
|
+
name=name.chop if /^[!~]@$/===name
|
4576
|
+
name=name.to_sym
|
4322
4577
|
|
4323
4578
|
result=[name, target=[:scope, [:block, ]] ]
|
4324
4579
|
if receiver
|
@@ -4444,7 +4699,9 @@ end
|
|
4444
4699
|
end
|
4445
4700
|
|
4446
4701
|
def str2parsetree(str,o)
|
4447
|
-
if String===str
|
4702
|
+
if String===str
|
4703
|
+
str=str.chop if /^[!~]@$/===str
|
4704
|
+
[:lit, str.to_sym]
|
4448
4705
|
else
|
4449
4706
|
result=str.parsetree(o)
|
4450
4707
|
result[0]=:dsym
|
@@ -4530,7 +4787,7 @@ end
|
|
4530
4787
|
def image; "(module #{name})" end
|
4531
4788
|
|
4532
4789
|
def unparse o=default_unparse_options
|
4533
|
-
"module #{name.unparse o}#{unparse_nl(body||self,o)}#{unparse_and_rescues(o)}
|
4790
|
+
"module #{name.unparse o}#{unparse_nl(body||self,o)}#{unparse_and_rescues(o)}#{unparse_nl(endline,o)}end"
|
4534
4791
|
end
|
4535
4792
|
|
4536
4793
|
def parent; nil end
|
@@ -4581,7 +4838,10 @@ end
|
|
4581
4838
|
def unparse o=default_unparse_options
|
4582
4839
|
result="class #{name.unparse o}"
|
4583
4840
|
result+=" < #{parent.unparse o}" if parent
|
4584
|
-
result+=unparse_nl(body||self,o)+
|
4841
|
+
result+=unparse_nl(body||self,o)+
|
4842
|
+
unparse_and_rescues(o)+
|
4843
|
+
unparse_nl(endline,o)+
|
4844
|
+
"end"
|
4585
4845
|
return result
|
4586
4846
|
end
|
4587
4847
|
|
@@ -4623,6 +4883,7 @@ end
|
|
4623
4883
|
alias object val
|
4624
4884
|
alias obj val
|
4625
4885
|
alias receiver val
|
4886
|
+
alias receiver= val=
|
4626
4887
|
alias name val
|
4627
4888
|
|
4628
4889
|
alias ensure_ ensure
|
@@ -4725,17 +4986,30 @@ end
|
|
4725
4986
|
|
4726
4987
|
class BracketsGetNode<ValueNode
|
4727
4988
|
param_names(:receiver,:lbrack_,:params,:rbrack_)
|
4989
|
+
alias args params
|
4728
4990
|
def initialize(receiver,lbrack,params,rbrack)
|
4729
|
-
|
4730
|
-
when CommaOpNode
|
4991
|
+
case params
|
4992
|
+
when CommaOpNode
|
4993
|
+
h,arrowrange=params.extract_unbraced_hash
|
4994
|
+
params=Array.new params
|
4995
|
+
params[arrowrange]=[h] if arrowrange
|
4996
|
+
when ArrowOpNode
|
4997
|
+
h=HashLiteralNode.new(nil,params,nil)
|
4998
|
+
h.startline=params.startline
|
4999
|
+
h.endline=params.endline
|
5000
|
+
params=[h]
|
4731
5001
|
when nil
|
4732
|
-
|
5002
|
+
params=nil
|
5003
|
+
else
|
5004
|
+
params=[params]
|
4733
5005
|
end
|
4734
5006
|
params.extend ListInNode if params
|
4735
5007
|
@offset=receiver.offset
|
4736
5008
|
super(receiver,params)
|
4737
5009
|
end
|
4738
5010
|
|
5011
|
+
def name; "[]" end
|
5012
|
+
|
4739
5013
|
def image; "(#{receiver.image}.[])" end
|
4740
5014
|
|
4741
5015
|
def unparse o=default_unparse_options
|
@@ -4743,7 +5017,7 @@ end
|
|
4743
5017
|
'[',
|
4744
5018
|
params&¶ms.map{|param| param.unparse o}.join(','),
|
4745
5019
|
']'
|
4746
|
-
].
|
5020
|
+
].join
|
4747
5021
|
end
|
4748
5022
|
|
4749
5023
|
def parsetree(o)
|
@@ -4848,7 +5122,13 @@ end
|
|
4848
5122
|
alias msg error?
|
4849
5123
|
end
|
4850
5124
|
|
4851
|
-
|
5125
|
+
|
5126
|
+
module Nodes
|
5127
|
+
::RedParse::constants.each{|k|
|
5128
|
+
const=::RedParse::const_get(k)
|
5129
|
+
const_set( k,const ) if Module===const and ::RedParse::Node>=const
|
5130
|
+
}
|
5131
|
+
end
|
4852
5132
|
|
4853
5133
|
end
|
4854
5134
|
=begin a (formal?) description
|