ruby_parser 3.13.1 → 3.15.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.autotest +18 -29
- data/History.rdoc +97 -0
- data/Manifest.txt +2 -0
- data/README.rdoc +3 -3
- data/Rakefile +39 -21
- data/bin/ruby_parse +3 -1
- data/bin/ruby_parse_extract_error +8 -3
- data/compare/normalize.rb +43 -3
- data/debugging.md +39 -0
- data/lib/ruby20_parser.rb +3431 -3238
- data/lib/ruby20_parser.y +474 -300
- data/lib/ruby21_parser.rb +3491 -3295
- data/lib/ruby21_parser.y +482 -307
- data/lib/ruby22_parser.rb +3432 -3240
- data/lib/ruby22_parser.y +483 -308
- data/lib/ruby23_parser.rb +3338 -3150
- data/lib/ruby23_parser.y +483 -308
- data/lib/ruby24_parser.rb +3483 -3273
- data/lib/ruby24_parser.y +487 -310
- data/lib/ruby25_parser.rb +3482 -3272
- data/lib/ruby25_parser.y +487 -310
- data/lib/ruby26_parser.rb +3490 -3278
- data/lib/ruby26_parser.y +493 -314
- data/lib/ruby27_parser.rb +7224 -0
- data/lib/ruby27_parser.y +2657 -0
- data/lib/ruby_lexer.rb +483 -459
- data/lib/ruby_lexer.rex +5 -6
- data/lib/ruby_lexer.rex.rb +6 -8
- data/lib/ruby_parser.rb +29 -27
- data/lib/ruby_parser.yy +497 -315
- data/lib/ruby_parser_extras.rb +670 -420
- data/test/test_ruby_lexer.rb +1208 -1121
- data/test/test_ruby_parser.rb +2517 -1955
- data/test/test_ruby_parser_extras.rb +39 -4
- data/tools/munge.rb +10 -5
- data/tools/ripper.rb +13 -2
- metadata +28 -21
- metadata.gz.sig +0 -0
data/lib/ruby_parser_extras.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: ASCII-8BIT
|
2
|
+
# TODO: remove
|
2
3
|
|
3
4
|
require "sexp"
|
4
5
|
require "ruby_lexer"
|
@@ -6,13 +7,50 @@ require "timeout"
|
|
6
7
|
require "rp_extensions"
|
7
8
|
require "rp_stringscanner"
|
8
9
|
|
10
|
+
class Sexp
|
11
|
+
def check_line_numbers
|
12
|
+
raise "bad nil line for:\n%s" % [self.pretty_inspect] if nil_line?
|
13
|
+
raise "bad line number for:\n%s" % [self.pretty_inspect] unless
|
14
|
+
Integer === self.line &&
|
15
|
+
self.line >= 1 &&
|
16
|
+
self.line <= self.line_min
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Returns the maximum line number of the children of self.
|
21
|
+
|
22
|
+
def line_min
|
23
|
+
@line_min ||= [self.deep_each.map(&:line).min, self.line].compact.min
|
24
|
+
end
|
25
|
+
|
26
|
+
def nil_line?
|
27
|
+
self.deep_each.map(&:line).any?(&:nil?)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
9
31
|
module RubyParserStuff
|
10
|
-
VERSION = "3.
|
32
|
+
VERSION = "3.15.1"
|
11
33
|
|
12
34
|
attr_accessor :lexer, :in_def, :in_single, :file
|
13
35
|
attr_accessor :in_kwarg
|
14
36
|
attr_reader :env, :comments
|
15
37
|
|
38
|
+
##
|
39
|
+
# Canonicalize conditionals. Eg:
|
40
|
+
#
|
41
|
+
# not x ? a : b
|
42
|
+
#
|
43
|
+
# becomes:
|
44
|
+
#
|
45
|
+
# x ? b : a
|
46
|
+
|
47
|
+
attr_accessor :canonicalize_conditions
|
48
|
+
|
49
|
+
##
|
50
|
+
# The last token type returned from #next_token
|
51
|
+
|
52
|
+
attr_accessor :last_token_type
|
53
|
+
|
16
54
|
$good20 = []
|
17
55
|
|
18
56
|
%w[
|
@@ -31,6 +69,28 @@ module RubyParserStuff
|
|
31
69
|
end
|
32
70
|
end
|
33
71
|
|
72
|
+
##
|
73
|
+
# for pure ruby systems only
|
74
|
+
|
75
|
+
def do_parse
|
76
|
+
_racc_do_parse_rb(_racc_setup, false)
|
77
|
+
end if ENV["PURE_RUBY"] || ENV["CHECK_LINE_NUMS"]
|
78
|
+
|
79
|
+
if ENV["CHECK_LINE_NUMS"] then
|
80
|
+
def _racc_do_reduce arg, act
|
81
|
+
x = super
|
82
|
+
|
83
|
+
@racc_vstack.grep(Sexp).each do |sexp|
|
84
|
+
sexp.check_line_numbers
|
85
|
+
end
|
86
|
+
x
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
ARG_TYPES = [:arglist, :call_args, :array, :args].map { |k|
|
91
|
+
[k, true]
|
92
|
+
}.to_h
|
93
|
+
|
34
94
|
has_enc = "".respond_to? :encoding
|
35
95
|
|
36
96
|
# This is in sorted order of occurrence according to
|
@@ -48,85 +108,52 @@ module RubyParserStuff
|
|
48
108
|
Encoding::EUC_JP
|
49
109
|
] if has_enc
|
50
110
|
|
51
|
-
|
52
|
-
raise RubyParser::SyntaxError, msg
|
53
|
-
end
|
111
|
+
JUMP_TYPE = [:return, :next, :break, :yield].map { |k| [k, true] }.to_h
|
54
112
|
|
55
|
-
|
56
|
-
node1 = s(:arglist, node1) unless [:arglist, :call_args, :array, :args].include? node1.sexp_type
|
57
|
-
node1 << node2 if node2
|
58
|
-
node1
|
59
|
-
end
|
113
|
+
TAB_WIDTH = 8
|
60
114
|
|
61
|
-
def
|
62
|
-
|
63
|
-
node1 << s(:splat, node2).compact
|
64
|
-
node1
|
65
|
-
end
|
115
|
+
def initialize(options = {})
|
116
|
+
super()
|
66
117
|
|
67
|
-
|
68
|
-
|
69
|
-
when :masgn then
|
70
|
-
if sexp.size == 2 and sexp[1].sexp_type == :array then
|
71
|
-
s(:masgn, *sexp[1].sexp_body.map { |sub| clean_mlhs sub })
|
72
|
-
else
|
73
|
-
debug20 5
|
74
|
-
sexp
|
75
|
-
end
|
76
|
-
when :gasgn, :iasgn, :lasgn, :cvasgn then
|
77
|
-
if sexp.size == 2 then
|
78
|
-
sexp.last
|
79
|
-
else
|
80
|
-
debug20 7
|
81
|
-
sexp # optional value
|
82
|
-
end
|
83
|
-
else
|
84
|
-
raise "unsupported type: #{sexp.inspect}"
|
85
|
-
end
|
86
|
-
end
|
118
|
+
v = self.class.name[/2\d/]
|
119
|
+
raise "Bad Class name #{self.class}" unless v
|
87
120
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
result
|
92
|
-
end
|
121
|
+
self.lexer = RubyLexer.new v && v.to_i
|
122
|
+
self.lexer.parser = self
|
123
|
+
self.in_kwarg = false
|
93
124
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
end
|
125
|
+
@env = RubyParserStuff::Environment.new
|
126
|
+
@comments = []
|
127
|
+
|
128
|
+
@canonicalize_conditions = true
|
129
|
+
|
130
|
+
self.reset
|
101
131
|
end
|
102
132
|
|
103
|
-
def
|
104
|
-
|
133
|
+
def arg_concat node1, node2 # TODO: nuke
|
134
|
+
raise "huh" unless node2
|
105
135
|
|
106
|
-
|
107
|
-
|
108
|
-
when Sexp then
|
109
|
-
case arg.sexp_type
|
110
|
-
when :array, :args, :call_args then # HACK? remove array at some point
|
111
|
-
result.concat arg.sexp_body
|
112
|
-
else
|
113
|
-
result << arg
|
114
|
-
end
|
115
|
-
when Symbol then
|
116
|
-
result << arg
|
117
|
-
when ",", nil then
|
118
|
-
# ignore
|
119
|
-
else
|
120
|
-
raise "unhandled: #{arg.inspect} in #{args.inspect}"
|
121
|
-
end
|
122
|
-
end
|
136
|
+
splat = s(:splat, node2)
|
137
|
+
splat.line node2.line
|
123
138
|
|
124
|
-
|
139
|
+
node1 << splat
|
140
|
+
end
|
141
|
+
|
142
|
+
def argl x
|
143
|
+
x = s(:arglist, x) if x and x.sexp_type == :array
|
144
|
+
x
|
125
145
|
end
|
126
146
|
|
127
147
|
def args args
|
128
148
|
result = s(:args)
|
129
149
|
|
150
|
+
ss = args.grep Sexp
|
151
|
+
if ss.empty? then
|
152
|
+
result.line lexer.lineno
|
153
|
+
else
|
154
|
+
result.line ss.first.line
|
155
|
+
end
|
156
|
+
|
130
157
|
args.each do |arg|
|
131
158
|
case arg
|
132
159
|
when Sexp then
|
@@ -162,13 +189,28 @@ module RubyParserStuff
|
|
162
189
|
result
|
163
190
|
end
|
164
191
|
|
192
|
+
def array_to_hash array
|
193
|
+
case array.sexp_type
|
194
|
+
when :kwsplat then
|
195
|
+
array
|
196
|
+
else
|
197
|
+
s(:hash, *array.sexp_body).line array.line
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
165
201
|
def aryset receiver, index
|
166
202
|
index ||= s()
|
167
|
-
|
203
|
+
l = receiver.line
|
204
|
+
result = s(:attrasgn, receiver, :"[]=",
|
205
|
+
*index.sexp_body).compact # [].sexp_body => nil
|
206
|
+
result.line = l
|
207
|
+
result
|
168
208
|
end
|
169
209
|
|
170
210
|
def assignable(lhs, value = nil)
|
171
211
|
id = lhs.to_sym unless Sexp === lhs
|
212
|
+
|
213
|
+
raise "WTF" if Sexp === id
|
172
214
|
id = id.to_sym if Sexp === id
|
173
215
|
|
174
216
|
raise "write a test 1" if id.to_s =~ /^(?:self|nil|true|false|__LINE__|__FILE__)$/
|
@@ -197,11 +239,33 @@ module RubyParserStuff
|
|
197
239
|
|
198
240
|
self.env[id] ||= :lvar if result.sexp_type == :lasgn
|
199
241
|
|
242
|
+
line = case lhs
|
243
|
+
when Sexp then
|
244
|
+
lhs.line
|
245
|
+
else
|
246
|
+
value && value.line || lexer.lineno
|
247
|
+
end
|
248
|
+
|
200
249
|
result << value if value
|
250
|
+
result.line = line
|
201
251
|
|
202
252
|
return result
|
203
253
|
end
|
204
254
|
|
255
|
+
def backref_assign_error ref
|
256
|
+
# TODO: need a test for this... obviously
|
257
|
+
case ref.sexp_type
|
258
|
+
when :nth_ref then
|
259
|
+
raise "write a test 2"
|
260
|
+
raise SyntaxError, "Can't set variable %p" % ref.last
|
261
|
+
when :back_ref then
|
262
|
+
raise "write a test 3"
|
263
|
+
raise SyntaxError, "Can't set back reference %p" % ref.last
|
264
|
+
else
|
265
|
+
raise "Unknown backref type: #{ref.inspect}"
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
205
269
|
def block_append(head, tail)
|
206
270
|
return head if tail.nil?
|
207
271
|
return tail if head.nil?
|
@@ -215,6 +279,69 @@ module RubyParserStuff
|
|
215
279
|
head << tail
|
216
280
|
end
|
217
281
|
|
282
|
+
def block_dup_check call_or_args, block
|
283
|
+
syntax_error "Both block arg and actual block given." if
|
284
|
+
block and call_or_args.block_pass?
|
285
|
+
end
|
286
|
+
|
287
|
+
def block_var *args
|
288
|
+
result = self.args args
|
289
|
+
result.sexp_type = :masgn
|
290
|
+
result
|
291
|
+
end
|
292
|
+
|
293
|
+
def call_args args
|
294
|
+
result = s(:call_args)
|
295
|
+
|
296
|
+
a = args.grep(Sexp).first
|
297
|
+
if a then
|
298
|
+
result.line a.line
|
299
|
+
else
|
300
|
+
result.line lexer.lineno
|
301
|
+
end
|
302
|
+
|
303
|
+
args.each do |arg|
|
304
|
+
case arg
|
305
|
+
when Sexp then
|
306
|
+
case arg.sexp_type
|
307
|
+
when :array, :args, :call_args then # HACK? remove array at some point
|
308
|
+
result.concat arg.sexp_body
|
309
|
+
else
|
310
|
+
result << arg
|
311
|
+
end
|
312
|
+
when Symbol then
|
313
|
+
result << arg
|
314
|
+
when ",", nil then
|
315
|
+
# ignore
|
316
|
+
else
|
317
|
+
raise "unhandled: #{arg.inspect} in #{args.inspect}"
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
result
|
322
|
+
end
|
323
|
+
|
324
|
+
def clean_mlhs sexp
|
325
|
+
case sexp.sexp_type
|
326
|
+
when :masgn then
|
327
|
+
if sexp.size == 2 and sexp[1].sexp_type == :array then
|
328
|
+
s(:masgn, *sexp[1].sexp_body.map { |sub| clean_mlhs sub })
|
329
|
+
else
|
330
|
+
debug20 5
|
331
|
+
sexp
|
332
|
+
end
|
333
|
+
when :gasgn, :iasgn, :lasgn, :cvasgn then
|
334
|
+
if sexp.size == 2 then
|
335
|
+
sexp.last
|
336
|
+
else
|
337
|
+
debug20 7
|
338
|
+
sexp # optional value
|
339
|
+
end
|
340
|
+
else
|
341
|
+
raise "unsupported type: #{sexp.inspect}"
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
218
345
|
def cond node
|
219
346
|
return nil if node.nil?
|
220
347
|
node = value_expr node
|
@@ -222,56 +349,113 @@ module RubyParserStuff
|
|
222
349
|
case node.sexp_type
|
223
350
|
when :lit then
|
224
351
|
if Regexp === node.last then
|
225
|
-
|
352
|
+
s(:match, node)
|
226
353
|
else
|
227
|
-
|
354
|
+
node
|
228
355
|
end
|
229
356
|
when :and then
|
230
|
-
|
357
|
+
_, lhs, rhs = node
|
358
|
+
s(:and, cond(lhs), cond(rhs))
|
231
359
|
when :or then
|
232
|
-
|
360
|
+
_, lhs, rhs = node
|
361
|
+
s(:or, cond(lhs), cond(rhs))
|
233
362
|
when :dot2 then
|
234
363
|
label = "flip#{node.hash}"
|
235
364
|
env[label] = :lvar
|
236
365
|
_, lhs, rhs = node
|
237
|
-
|
366
|
+
s(:flip2, lhs, rhs) # TODO: recurse?
|
238
367
|
when :dot3 then
|
239
368
|
label = "flip#{node.hash}"
|
240
369
|
env[label] = :lvar
|
241
370
|
_, lhs, rhs = node
|
242
|
-
|
371
|
+
s(:flip3, lhs, rhs)
|
243
372
|
else
|
244
|
-
|
245
|
-
end
|
373
|
+
node
|
374
|
+
end.line node.line
|
246
375
|
end
|
247
376
|
|
248
|
-
|
249
|
-
|
377
|
+
def dedent sexp
|
378
|
+
dedent_count = dedent_size sexp
|
250
379
|
|
251
|
-
|
252
|
-
|
253
|
-
|
380
|
+
skip_one = false
|
381
|
+
sexp.map { |obj|
|
382
|
+
case obj
|
383
|
+
when Symbol then
|
384
|
+
obj
|
385
|
+
when String then
|
386
|
+
obj.lines.map { |l| remove_whitespace_width l, dedent_count }.join
|
387
|
+
when Sexp then
|
388
|
+
case obj.sexp_type
|
389
|
+
when :evstr then
|
390
|
+
skip_one = true
|
391
|
+
obj
|
392
|
+
when :str then
|
393
|
+
_, str = obj
|
394
|
+
str = if skip_one then
|
395
|
+
skip_one = false
|
396
|
+
s1, *rest = str.lines
|
397
|
+
s1 + rest.map { |l| remove_whitespace_width l, dedent_count }.join
|
398
|
+
else
|
399
|
+
str.lines.map { |l| remove_whitespace_width l, dedent_count }.join
|
400
|
+
end
|
254
401
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
return s(:match2, lhs, rhs).line(lhs.line) if Regexp === lhs.last
|
402
|
+
s(:str, str).line obj.line
|
403
|
+
else
|
404
|
+
warn "unprocessed sexp %p" % [obj]
|
405
|
+
end
|
406
|
+
else
|
407
|
+
warn "unprocessed: %p" % [obj]
|
262
408
|
end
|
263
|
-
|
409
|
+
}
|
410
|
+
end
|
264
411
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
when
|
270
|
-
|
412
|
+
def dedent_size sexp
|
413
|
+
skip_one = false
|
414
|
+
sexp.flat_map { |s|
|
415
|
+
case s
|
416
|
+
when Symbol then
|
417
|
+
next
|
418
|
+
when String then
|
419
|
+
s.lines
|
420
|
+
when Sexp then
|
421
|
+
case s.sexp_type
|
422
|
+
when :evstr then
|
423
|
+
skip_one = true
|
424
|
+
next
|
425
|
+
when :str then
|
426
|
+
_, str = s
|
427
|
+
lines = str.lines
|
428
|
+
if skip_one then
|
429
|
+
skip_one = false
|
430
|
+
lines.shift
|
431
|
+
end
|
432
|
+
lines
|
433
|
+
else
|
434
|
+
warn "unprocessed sexp %p" % [s]
|
435
|
+
end
|
436
|
+
else
|
437
|
+
warn "unprocessed: %p" % [s]
|
438
|
+
end.map { |l| whitespace_width l[/^[ \t]*/] }
|
439
|
+
}.compact.min
|
440
|
+
end
|
441
|
+
|
442
|
+
def dedent_string string, width
|
443
|
+
characters_skipped = 0
|
444
|
+
indentation_skipped = 0
|
445
|
+
|
446
|
+
string.chars.each do |char|
|
447
|
+
break if indentation_skipped >= width
|
448
|
+
if char == " "
|
449
|
+
characters_skipped += 1
|
450
|
+
indentation_skipped += 1
|
451
|
+
elsif char == "\t"
|
452
|
+
proposed = TAB_WIDTH * (indentation_skipped / TAB_WIDTH + 1)
|
453
|
+
break if proposed > width
|
454
|
+
characters_skipped += 1
|
455
|
+
indentation_skipped = proposed
|
271
456
|
end
|
272
457
|
end
|
273
|
-
|
274
|
-
return new_call(lhs, :"=~", argl(rhs)).line(lhs.line)
|
458
|
+
string[characters_skipped..-1]
|
275
459
|
end
|
276
460
|
|
277
461
|
def gettable(id)
|
@@ -303,33 +487,94 @@ module RubyParserStuff
|
|
303
487
|
result
|
304
488
|
end
|
305
489
|
|
490
|
+
def hack_encoding str, extra = nil
|
491
|
+
encodings = ENCODING_ORDER.dup
|
492
|
+
encodings.unshift(extra) unless extra.nil?
|
493
|
+
|
494
|
+
# terrible, horrible, no good, very bad, last ditch effort.
|
495
|
+
encodings.each do |enc|
|
496
|
+
begin
|
497
|
+
str.force_encoding enc
|
498
|
+
if str.valid_encoding? then
|
499
|
+
str.encode! Encoding::UTF_8
|
500
|
+
break
|
501
|
+
end
|
502
|
+
rescue ArgumentError # unknown encoding name
|
503
|
+
# do nothing
|
504
|
+
rescue Encoding::InvalidByteSequenceError
|
505
|
+
# do nothing
|
506
|
+
rescue Encoding::UndefinedConversionError
|
507
|
+
# do nothing
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
# no amount of pain is enough for you.
|
512
|
+
raise "Bad encoding. Need a magic encoding comment." unless
|
513
|
+
str.encoding.name == "UTF-8"
|
514
|
+
end
|
515
|
+
|
306
516
|
##
|
307
|
-
#
|
308
|
-
#
|
309
|
-
# not x ? a : b
|
517
|
+
# Returns a UTF-8 encoded string after processing BOMs and magic
|
518
|
+
# encoding comments.
|
310
519
|
#
|
311
|
-
#
|
520
|
+
# Holy crap... ok. Here goes:
|
312
521
|
#
|
313
|
-
#
|
522
|
+
# Ruby's file handling and encoding support is insane. We need to be
|
523
|
+
# able to lex a file. The lexer file is explicitly UTF-8 to make
|
524
|
+
# things cleaner. This allows us to deal with extended chars in
|
525
|
+
# class and method names. In order to do this, we need to encode all
|
526
|
+
# input source files as UTF-8. First, we look for a UTF-8 BOM by
|
527
|
+
# looking at the first line while forcing its encoding to
|
528
|
+
# ASCII-8BIT. If we find a BOM, we strip it and set the expected
|
529
|
+
# encoding to UTF-8. Then, we search for a magic encoding comment.
|
530
|
+
# If found, it overrides the BOM. Finally, we force the encoding of
|
531
|
+
# the input string to whatever was found, and then encode that to
|
532
|
+
# UTF-8 for compatibility with the lexer.
|
314
533
|
|
315
|
-
|
534
|
+
def handle_encoding str
|
535
|
+
str = str.dup
|
536
|
+
has_enc = str.respond_to? :encoding
|
537
|
+
encoding = nil
|
316
538
|
|
317
|
-
|
318
|
-
|
539
|
+
header = str.each_line.first(2)
|
540
|
+
header.map! { |s| s.force_encoding "ASCII-8BIT" } if has_enc
|
319
541
|
|
320
|
-
|
321
|
-
|
542
|
+
first = header.first || ""
|
543
|
+
encoding, str = "utf-8", str.b[3..-1] if first =~ /\A\xEF\xBB\xBF/
|
322
544
|
|
323
|
-
|
324
|
-
|
325
|
-
|
545
|
+
encoding = $1.strip if header.find { |s|
|
546
|
+
s[/^#.*?-\*-.*?coding:\s*([^ ;]+).*?-\*-/, 1] ||
|
547
|
+
s[/^#.*(?:en)?coding(?:\s*[:=])\s*([\w-]+)/, 1]
|
548
|
+
}
|
326
549
|
|
327
|
-
|
328
|
-
|
550
|
+
if encoding then
|
551
|
+
if has_enc then
|
552
|
+
encoding.sub!(/utf-8-.+$/, "utf-8") # HACK for stupid emacs formats
|
553
|
+
hack_encoding str, encoding
|
554
|
+
else
|
555
|
+
warn "Skipping magic encoding comment"
|
556
|
+
end
|
557
|
+
else
|
558
|
+
# nothing specified... ugh. try to encode as utf-8
|
559
|
+
hack_encoding str if has_enc
|
560
|
+
end
|
329
561
|
|
330
|
-
|
562
|
+
str
|
563
|
+
end
|
331
564
|
|
332
|
-
|
565
|
+
def invert_block_call val
|
566
|
+
ret, iter = val
|
567
|
+
type, call = ret
|
568
|
+
|
569
|
+
iter.insert 1, call
|
570
|
+
|
571
|
+
ret = s(type).line ret.line
|
572
|
+
|
573
|
+
[iter, ret]
|
574
|
+
end
|
575
|
+
|
576
|
+
def inverted? val
|
577
|
+
JUMP_TYPE[val[0].sexp_type]
|
333
578
|
end
|
334
579
|
|
335
580
|
def list_append list, item # TODO: nuke me *sigh*
|
@@ -350,12 +595,14 @@ module RubyParserStuff
|
|
350
595
|
|
351
596
|
htype, ttype = head.sexp_type, tail.sexp_type
|
352
597
|
|
353
|
-
head = s(:dstr,
|
598
|
+
head = s(:dstr, "", head).line head.line if htype == :evstr
|
354
599
|
|
355
600
|
case ttype
|
356
601
|
when :str then
|
357
602
|
if htype == :str
|
358
|
-
head.last
|
603
|
+
a, b = head.last, tail.last
|
604
|
+
b = b.dup.force_encoding a.encoding unless Encoding.compatible?(a, b)
|
605
|
+
a << b
|
359
606
|
elsif htype == :dstr and head.size == 2 then
|
360
607
|
head.last << tail.last
|
361
608
|
else
|
@@ -369,15 +616,15 @@ module RubyParserStuff
|
|
369
616
|
head.line = lineno
|
370
617
|
else
|
371
618
|
tail.sexp_type = :array
|
372
|
-
tail[1] = s(:str, tail[1])
|
373
|
-
tail.delete_at 1 if tail[1] == s(:str,
|
619
|
+
tail[1] = s(:str, tail[1]).line tail.line
|
620
|
+
tail.delete_at 1 if tail[1] == s(:str, "")
|
374
621
|
|
375
622
|
head.push(*tail.sexp_body)
|
376
623
|
end
|
377
624
|
when :evstr then
|
378
625
|
if htype == :str then
|
379
626
|
f, l = head.file, head.line
|
380
|
-
head = s(:dstr, *head.sexp_body)
|
627
|
+
head = s(:dstr, *head.sexp_body).line head.line
|
381
628
|
head.file = f
|
382
629
|
head.line = l
|
383
630
|
end
|
@@ -408,12 +655,15 @@ module RubyParserStuff
|
|
408
655
|
node = rhs
|
409
656
|
end
|
410
657
|
|
411
|
-
node
|
658
|
+
node.pop
|
659
|
+
node << s(type, rhs, right).line(rhs.line)
|
412
660
|
|
413
661
|
return left
|
414
662
|
end
|
415
663
|
|
416
|
-
|
664
|
+
result = s(type, left, right)
|
665
|
+
result.line left.line if left.line
|
666
|
+
result
|
417
667
|
end
|
418
668
|
|
419
669
|
def new_aref val
|
@@ -422,6 +672,49 @@ module RubyParserStuff
|
|
422
672
|
new_call val[0], :"[]", val[2]
|
423
673
|
end
|
424
674
|
|
675
|
+
def new_assign lhs, rhs
|
676
|
+
return nil unless lhs
|
677
|
+
|
678
|
+
rhs = value_expr rhs
|
679
|
+
|
680
|
+
case lhs.sexp_type
|
681
|
+
when :lasgn, :iasgn, :cdecl, :cvdecl, :gasgn, :cvasgn, :attrasgn, :safe_attrasgn then
|
682
|
+
lhs << rhs
|
683
|
+
when :const then
|
684
|
+
lhs.sexp_type = :cdecl
|
685
|
+
lhs << rhs
|
686
|
+
else
|
687
|
+
raise "unknown lhs #{lhs.inspect} w/ #{rhs.inspect}"
|
688
|
+
end
|
689
|
+
|
690
|
+
lhs
|
691
|
+
end
|
692
|
+
|
693
|
+
def new_attrasgn recv, meth, call_op = :"."
|
694
|
+
meth = :"#{meth}="
|
695
|
+
|
696
|
+
result = case call_op.to_sym
|
697
|
+
when :"."
|
698
|
+
s(:attrasgn, recv, meth)
|
699
|
+
when :"&."
|
700
|
+
s(:safe_attrasgn, recv, meth)
|
701
|
+
else
|
702
|
+
raise "unknown call operator: `#{type.inspect}`"
|
703
|
+
end
|
704
|
+
|
705
|
+
result.line = recv.line
|
706
|
+
result
|
707
|
+
end
|
708
|
+
|
709
|
+
def new_begin val
|
710
|
+
_, lineno, body, _ = val
|
711
|
+
|
712
|
+
result = body ? s(:begin, body) : s(:nil)
|
713
|
+
result.line lineno
|
714
|
+
|
715
|
+
result
|
716
|
+
end
|
717
|
+
|
425
718
|
def new_body val
|
426
719
|
body, resbody, elsebody, ensurebody = val
|
427
720
|
|
@@ -445,43 +738,27 @@ module RubyParserStuff
|
|
445
738
|
|
446
739
|
if elsebody and not resbody then
|
447
740
|
warning("else without rescue is useless")
|
448
|
-
result = s(:begin, result) if result
|
741
|
+
result = s(:begin, result).line result.line if result
|
449
742
|
result = block_append(result, elsebody)
|
450
743
|
end
|
451
744
|
|
452
|
-
|
745
|
+
if ensurebody
|
746
|
+
lineno = (result || ensurebody).line
|
747
|
+
result = s(:ensure, result, ensurebody).compact.line lineno
|
748
|
+
end
|
453
749
|
|
454
750
|
result
|
455
751
|
end
|
456
752
|
|
457
753
|
def new_brace_body args, body, lineno
|
458
|
-
new_iter(nil, args, body).line
|
754
|
+
new_iter(nil, args, body).line lineno
|
459
755
|
end
|
460
756
|
|
461
|
-
def
|
462
|
-
x = s(:arglist, x) if x and x.sexp_type == :array
|
463
|
-
x
|
464
|
-
end
|
465
|
-
|
466
|
-
def backref_assign_error ref
|
467
|
-
# TODO: need a test for this... obviously
|
468
|
-
case ref.sexp_type
|
469
|
-
when :nth_ref then
|
470
|
-
raise "write a test 2"
|
471
|
-
raise SyntaxError, "Can't set variable %p" % ref.last
|
472
|
-
when :back_ref then
|
473
|
-
raise "write a test 3"
|
474
|
-
raise SyntaxError, "Can't set back reference %p" % ref.last
|
475
|
-
else
|
476
|
-
raise "Unknown backref type: #{ref.inspect}"
|
477
|
-
end
|
478
|
-
end
|
479
|
-
|
480
|
-
def new_call recv, meth, args = nil, call_op = :'.'
|
757
|
+
def new_call recv, meth, args = nil, call_op = :"."
|
481
758
|
result = case call_op.to_sym
|
482
|
-
when :
|
759
|
+
when :"."
|
483
760
|
s(:call, recv, meth)
|
484
|
-
when :
|
761
|
+
when :"&."
|
485
762
|
s(:safe_call, recv, meth)
|
486
763
|
else
|
487
764
|
raise "unknown call operator: `#{type.inspect}`"
|
@@ -491,32 +768,17 @@ module RubyParserStuff
|
|
491
768
|
# TODO: need a test with f(&b) { } to produce warning
|
492
769
|
|
493
770
|
if args
|
494
|
-
if [
|
771
|
+
if ARG_TYPES[args.sexp_type] then
|
495
772
|
result.concat args.sexp_body
|
496
773
|
else
|
497
774
|
result << args
|
498
775
|
end
|
499
776
|
end
|
500
777
|
|
501
|
-
line = result.grep(Sexp).map(&:line).compact.min
|
502
|
-
result.line = line if
|
503
|
-
|
504
|
-
result
|
505
|
-
end
|
506
|
-
|
507
|
-
def new_attrasgn recv, meth, call_op
|
508
|
-
meth = :"#{meth}="
|
509
|
-
|
510
|
-
result = case call_op.to_sym
|
511
|
-
when :'.'
|
512
|
-
s(:attrasgn, recv, meth)
|
513
|
-
when :'&.'
|
514
|
-
s(:safe_attrasgn, recv, meth)
|
515
|
-
else
|
516
|
-
raise "unknown call operator: `#{type.inspect}`"
|
517
|
-
end
|
778
|
+
# line = result.grep(Sexp).map(&:line).compact.min
|
779
|
+
result.line = recv.line if recv
|
780
|
+
result.line ||= lexer.lineno
|
518
781
|
|
519
|
-
result.line = recv.line
|
520
782
|
result
|
521
783
|
end
|
522
784
|
|
@@ -565,11 +827,29 @@ module RubyParserStuff
|
|
565
827
|
result
|
566
828
|
end
|
567
829
|
|
830
|
+
def new_const_op_asgn val
|
831
|
+
lhs, asgn_op, rhs = val[0], val[1].to_sym, val[2]
|
832
|
+
|
833
|
+
result = case asgn_op
|
834
|
+
when :"||" then
|
835
|
+
s(:op_asgn_or, lhs, rhs)
|
836
|
+
when :"&&" then
|
837
|
+
s(:op_asgn_and, lhs, rhs)
|
838
|
+
else
|
839
|
+
s(:op_asgn, lhs, asgn_op, rhs)
|
840
|
+
end
|
841
|
+
|
842
|
+
result.line = lhs.line
|
843
|
+
result
|
844
|
+
end
|
845
|
+
|
568
846
|
def new_defn val
|
569
|
-
(_, line),
|
570
|
-
body ||= s(:nil)
|
847
|
+
(_, line), name, _, args, body, nil_body_line, * = val
|
848
|
+
body ||= s(:nil).line nil_body_line
|
571
849
|
|
572
|
-
|
850
|
+
args.line line
|
851
|
+
|
852
|
+
result = s(:defn, name.to_sym, args).line line
|
573
853
|
|
574
854
|
if body then
|
575
855
|
if body.sexp_type == :block then
|
@@ -579,19 +859,23 @@ module RubyParserStuff
|
|
579
859
|
end
|
580
860
|
end
|
581
861
|
|
582
|
-
args.line line
|
583
|
-
result.line = line
|
584
862
|
result.comments = self.comments.pop
|
585
863
|
|
586
864
|
result
|
587
865
|
end
|
588
866
|
|
589
867
|
def new_defs val
|
590
|
-
recv,
|
591
|
-
|
868
|
+
_, recv, _, _, name, (_in_def, line), args, body, _ = val
|
869
|
+
|
870
|
+
body ||= s(:nil).line line
|
871
|
+
|
872
|
+
args.line line
|
592
873
|
|
593
874
|
result = s(:defs, recv, name.to_sym, args)
|
594
875
|
|
876
|
+
# TODO: remove_begin
|
877
|
+
# TODO: reduce_nodes
|
878
|
+
|
595
879
|
if body then
|
596
880
|
if body.sexp_type == :block then
|
597
881
|
result.push(*body.sexp_body)
|
@@ -616,7 +900,9 @@ module RubyParserStuff
|
|
616
900
|
end
|
617
901
|
|
618
902
|
def new_hash val
|
619
|
-
|
903
|
+
_, line, assocs = val
|
904
|
+
|
905
|
+
s(:hash).line(line).concat assocs.values
|
620
906
|
end
|
621
907
|
|
622
908
|
def new_if c, t, f
|
@@ -637,27 +923,59 @@ module RubyParserStuff
|
|
637
923
|
result << args
|
638
924
|
result << body if body
|
639
925
|
|
640
|
-
|
926
|
+
result.line call.line if call
|
641
927
|
|
642
|
-
|
643
|
-
|
928
|
+
unless args == 0 then
|
929
|
+
args.line call.line if call
|
930
|
+
args.sexp_type = :args
|
931
|
+
end
|
644
932
|
|
645
|
-
|
646
|
-
rhs = value_expr(rhs)
|
647
|
-
rhs = s(:to_ary, rhs) if wrap # HACK: could be array if lhs isn't right
|
648
|
-
rhs
|
933
|
+
result
|
649
934
|
end
|
650
935
|
|
651
936
|
def new_masgn lhs, rhs, wrap = false
|
652
937
|
_, ary = lhs
|
653
938
|
|
939
|
+
line = rhs.line
|
654
940
|
rhs = value_expr(rhs)
|
655
941
|
rhs = ary ? s(:to_ary, rhs) : s(:array, rhs) if wrap
|
942
|
+
rhs.line line if wrap
|
656
943
|
|
657
944
|
lhs.delete_at 1 if ary.nil?
|
658
945
|
lhs << rhs
|
659
946
|
|
660
|
-
lhs
|
947
|
+
lhs
|
948
|
+
end
|
949
|
+
|
950
|
+
def new_masgn_arg rhs, wrap = false
|
951
|
+
rhs = value_expr(rhs)
|
952
|
+
# HACK: could be array if lhs isn't right
|
953
|
+
rhs = s(:to_ary, rhs).line rhs.line if wrap
|
954
|
+
rhs
|
955
|
+
end
|
956
|
+
|
957
|
+
def new_match lhs, rhs
|
958
|
+
if lhs then
|
959
|
+
case lhs.sexp_type
|
960
|
+
when :dregx, :dregx_once then
|
961
|
+
# TODO: no test coverage
|
962
|
+
return s(:match2, lhs, rhs).line(lhs.line)
|
963
|
+
when :lit then
|
964
|
+
return s(:match2, lhs, rhs).line(lhs.line) if Regexp === lhs.last
|
965
|
+
end
|
966
|
+
end
|
967
|
+
|
968
|
+
if rhs then
|
969
|
+
case rhs.sexp_type
|
970
|
+
when :dregx, :dregx_once then
|
971
|
+
# TODO: no test coverage
|
972
|
+
return s(:match3, rhs, lhs).line(lhs.line)
|
973
|
+
when :lit then
|
974
|
+
return s(:match3, rhs, lhs).line(lhs.line) if Regexp === rhs.last
|
975
|
+
end
|
976
|
+
end
|
977
|
+
|
978
|
+
new_call(lhs, :"=~", argl(rhs)).line lhs.line
|
661
979
|
end
|
662
980
|
|
663
981
|
def new_module val
|
@@ -680,37 +998,30 @@ module RubyParserStuff
|
|
680
998
|
|
681
999
|
def new_op_asgn val
|
682
1000
|
lhs, asgn_op, arg = val[0], val[1].to_sym, val[2]
|
683
|
-
name = lhs.value
|
1001
|
+
name = gettable(lhs.value).line lhs.line
|
684
1002
|
arg = remove_begin(arg)
|
685
1003
|
result = case asgn_op # REFACTOR
|
686
1004
|
when :"||" then
|
687
1005
|
lhs << arg
|
688
|
-
s(:op_asgn_or,
|
1006
|
+
s(:op_asgn_or, name, lhs)
|
689
1007
|
when :"&&" then
|
690
1008
|
lhs << arg
|
691
|
-
s(:op_asgn_and,
|
1009
|
+
s(:op_asgn_and, name, lhs)
|
692
1010
|
else
|
693
|
-
|
694
|
-
lhs[2] = new_call(self.gettable(name), asgn_op, argl(arg))
|
1011
|
+
lhs << new_call(name, asgn_op, argl(arg))
|
695
1012
|
lhs
|
696
1013
|
end
|
697
1014
|
result.line = lhs.line
|
698
1015
|
result
|
699
1016
|
end
|
700
1017
|
|
701
|
-
def
|
702
|
-
lhs,
|
1018
|
+
def new_op_asgn1 val
|
1019
|
+
lhs, _, args, _, op, rhs = val
|
703
1020
|
|
704
|
-
|
705
|
-
when :"||" then
|
706
|
-
s(:op_asgn_or, lhs, rhs)
|
707
|
-
when :"&&" then
|
708
|
-
s(:op_asgn_and, lhs, rhs)
|
709
|
-
else
|
710
|
-
s(:op_asgn, lhs, asgn_op, rhs)
|
711
|
-
end
|
1021
|
+
args.sexp_type = :arglist if args
|
712
1022
|
|
713
|
-
result
|
1023
|
+
result = s(:op_asgn1, lhs, args, op.to_sym, rhs)
|
1024
|
+
result.line lhs.line
|
714
1025
|
result
|
715
1026
|
end
|
716
1027
|
|
@@ -719,9 +1030,9 @@ module RubyParserStuff
|
|
719
1030
|
meth = :"#{meth}="
|
720
1031
|
|
721
1032
|
result = case call_op.to_sym
|
722
|
-
when :
|
1033
|
+
when :"."
|
723
1034
|
s(:op_asgn2, recv, meth, op.to_sym, arg)
|
724
|
-
when :
|
1035
|
+
when :"&."
|
725
1036
|
s(:safe_op_asgn2, recv, meth, op.to_sym, arg)
|
726
1037
|
else
|
727
1038
|
raise "unknown call operator: `#{type.inspect}`"
|
@@ -731,21 +1042,49 @@ module RubyParserStuff
|
|
731
1042
|
result
|
732
1043
|
end
|
733
1044
|
|
1045
|
+
def new_qsym_list
|
1046
|
+
result = s(:array).line lexer.lineno
|
1047
|
+
self.lexer.fixup_lineno
|
1048
|
+
result
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
def new_qsym_list_entry val
|
1052
|
+
_, str, _ = val
|
1053
|
+
result = s(:lit, str.to_sym).line lexer.lineno
|
1054
|
+
self.lexer.fixup_lineno
|
1055
|
+
result
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
def new_qword_list
|
1059
|
+
result = s(:array).line lexer.lineno
|
1060
|
+
self.lexer.fixup_lineno
|
1061
|
+
result
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
def new_qword_list_entry val
|
1065
|
+
_, str, _ = val
|
1066
|
+
str.force_encoding("ASCII-8BIT") unless str.valid_encoding?
|
1067
|
+
result = s(:str, str).line lexer.lineno # TODO: problematic? grab from parser
|
1068
|
+
self.lexer.fixup_lineno
|
1069
|
+
result
|
1070
|
+
end
|
1071
|
+
|
734
1072
|
def new_regexp val
|
735
|
-
node = val
|
736
|
-
|
1073
|
+
_, node, options = val
|
1074
|
+
|
1075
|
+
node ||= s(:str, "").line lexer.lineno
|
737
1076
|
|
738
1077
|
o, k = 0, nil
|
739
1078
|
options.split(//).uniq.each do |c| # FIX: this has a better home
|
740
1079
|
v = {
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
1080
|
+
"x" => Regexp::EXTENDED,
|
1081
|
+
"i" => Regexp::IGNORECASE,
|
1082
|
+
"m" => Regexp::MULTILINE,
|
1083
|
+
"o" => Regexp::ONCE,
|
1084
|
+
"n" => Regexp::ENC_NONE,
|
1085
|
+
"e" => Regexp::ENC_EUC,
|
1086
|
+
"s" => Regexp::ENC_SJIS,
|
1087
|
+
"u" => Regexp::ENC_UTF8,
|
749
1088
|
}[c]
|
750
1089
|
raise "unknown regexp option: #{c}" unless v
|
751
1090
|
o += v
|
@@ -778,7 +1117,7 @@ module RubyParserStuff
|
|
778
1117
|
end
|
779
1118
|
node << o if o and o != 0
|
780
1119
|
else
|
781
|
-
node = s(:dregx,
|
1120
|
+
node = s(:dregx, "", node).line node.line
|
782
1121
|
node.sexp_type = :dregx_once if options =~ /o/
|
783
1122
|
node << o if o and o != 0
|
784
1123
|
end
|
@@ -786,19 +1125,20 @@ module RubyParserStuff
|
|
786
1125
|
node
|
787
1126
|
end
|
788
1127
|
|
789
|
-
def new_rescue body, resbody
|
790
|
-
s(:rescue, body, resbody)
|
791
|
-
end
|
792
|
-
|
793
1128
|
def new_resbody cond, body
|
794
1129
|
if body && body.sexp_type == :block then
|
795
1130
|
body.shift # remove block and splat it in directly
|
796
1131
|
else
|
797
1132
|
body = [body]
|
798
1133
|
end
|
1134
|
+
|
799
1135
|
s(:resbody, cond, *body).line cond.line
|
800
1136
|
end
|
801
1137
|
|
1138
|
+
def new_rescue body, resbody
|
1139
|
+
s(:rescue, body, resbody).line body.line
|
1140
|
+
end
|
1141
|
+
|
802
1142
|
def new_sclass val
|
803
1143
|
recv, in_def, in_single, body = val[3], val[4], val[6], val[7]
|
804
1144
|
|
@@ -819,63 +1159,36 @@ module RubyParserStuff
|
|
819
1159
|
end
|
820
1160
|
|
821
1161
|
def new_string val
|
822
|
-
str = val
|
1162
|
+
str, = val
|
823
1163
|
str.force_encoding("UTF-8")
|
1164
|
+
# TODO: remove:
|
824
1165
|
str.force_encoding("ASCII-8BIT") unless str.valid_encoding?
|
825
|
-
result = s(:str, str)
|
1166
|
+
result = s(:str, str).line lexer.lineno
|
826
1167
|
self.lexer.fixup_lineno str.count("\n")
|
827
1168
|
result
|
828
1169
|
end
|
829
1170
|
|
830
|
-
def
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
def new_qword_list
|
839
|
-
result = s(:array)
|
840
|
-
self.lexer.fixup_lineno
|
841
|
-
result
|
842
|
-
end
|
843
|
-
|
844
|
-
def new_word_list
|
845
|
-
result = s(:array)
|
846
|
-
self.lexer.fixup_lineno
|
847
|
-
result
|
848
|
-
end
|
849
|
-
|
850
|
-
def new_word_list_entry val
|
851
|
-
result = val[1].sexp_type == :evstr ? s(:dstr, "", val[1]) : val[1]
|
852
|
-
self.lexer.fixup_lineno
|
853
|
-
result
|
854
|
-
end
|
855
|
-
|
856
|
-
def new_qsym_list
|
857
|
-
result = s(:array)
|
858
|
-
self.lexer.fixup_lineno
|
859
|
-
result
|
860
|
-
end
|
861
|
-
|
862
|
-
def new_qsym_list_entry val
|
863
|
-
result = s(:lit, val[1].to_sym)
|
864
|
-
self.lexer.fixup_lineno
|
865
|
-
result
|
1171
|
+
def new_super args
|
1172
|
+
if args && args.node_type == :block_pass then
|
1173
|
+
s(:super, args).line args.line
|
1174
|
+
else
|
1175
|
+
args ||= s(:arglist).line lexer.lineno
|
1176
|
+
s(:super, *args.sexp_body).line args.line
|
1177
|
+
end
|
866
1178
|
end
|
867
1179
|
|
868
1180
|
def new_symbol_list
|
869
|
-
result = s(:array)
|
1181
|
+
result = s(:array).line lexer.lineno
|
870
1182
|
self.lexer.fixup_lineno
|
871
1183
|
result
|
872
1184
|
end
|
873
1185
|
|
874
1186
|
def new_symbol_list_entry val
|
875
|
-
|
876
|
-
|
1187
|
+
_, sym, _ = val
|
1188
|
+
|
1189
|
+
sym ||= s(:str, "")
|
877
1190
|
|
878
|
-
|
1191
|
+
line = lexer.lineno
|
879
1192
|
|
880
1193
|
case sym.sexp_type
|
881
1194
|
when :dstr then
|
@@ -883,26 +1196,21 @@ module RubyParserStuff
|
|
883
1196
|
when :str then
|
884
1197
|
sym = s(:lit, sym.last.to_sym)
|
885
1198
|
else
|
886
|
-
sym = s(:dsym, "", sym || s(:str, ""))
|
1199
|
+
sym = s(:dsym, "", sym || s(:str, "").line(line))
|
887
1200
|
end
|
1201
|
+
|
1202
|
+
sym.line line
|
1203
|
+
|
888
1204
|
self.lexer.fixup_lineno
|
889
|
-
sym
|
890
|
-
end
|
891
1205
|
|
892
|
-
|
893
|
-
if args && args.node_type == :block_pass then
|
894
|
-
s(:super, args)
|
895
|
-
else
|
896
|
-
args ||= s(:arglist)
|
897
|
-
s(:super, *args.sexp_body)
|
898
|
-
end
|
1206
|
+
sym
|
899
1207
|
end
|
900
1208
|
|
901
1209
|
def new_undef n, m = nil
|
902
1210
|
if m then
|
903
|
-
block_append(n, s(:undef, m))
|
1211
|
+
block_append(n, s(:undef, m).line(m.line))
|
904
1212
|
else
|
905
|
-
s(:undef, n)
|
1213
|
+
s(:undef, n).line n.line
|
906
1214
|
end
|
907
1215
|
end
|
908
1216
|
|
@@ -935,20 +1243,36 @@ module RubyParserStuff
|
|
935
1243
|
new_until_or_while :while, block, expr, pre
|
936
1244
|
end
|
937
1245
|
|
938
|
-
def
|
939
|
-
|
940
|
-
|
1246
|
+
def new_word_list
|
1247
|
+
result = s(:array).line lexer.lineno
|
1248
|
+
self.lexer.fixup_lineno
|
1249
|
+
result
|
1250
|
+
end
|
1251
|
+
|
1252
|
+
def new_word_list_entry val
|
1253
|
+
_, word, _ = val
|
1254
|
+
result = word.sexp_type == :evstr ? s(:dstr, "", word).line(word.line) : word
|
1255
|
+
self.lexer.fixup_lineno
|
1256
|
+
result
|
1257
|
+
end
|
1258
|
+
|
1259
|
+
def new_xstring val
|
1260
|
+
_, node = val
|
1261
|
+
|
1262
|
+
node ||= s(:str, "").line lexer.lineno
|
1263
|
+
|
1264
|
+
if node then
|
1265
|
+
case node.sexp_type
|
941
1266
|
when :str
|
942
|
-
|
1267
|
+
node.sexp_type = :xstr
|
943
1268
|
when :dstr
|
944
|
-
|
1269
|
+
node.sexp_type = :dxstr
|
945
1270
|
else
|
946
|
-
|
1271
|
+
node = s(:dxstr, "", node).line node.line
|
947
1272
|
end
|
948
|
-
str
|
949
|
-
else
|
950
|
-
s(:xstr, '')
|
951
1273
|
end
|
1274
|
+
|
1275
|
+
node
|
952
1276
|
end
|
953
1277
|
|
954
1278
|
def new_yield args = nil
|
@@ -957,113 +1281,32 @@ module RubyParserStuff
|
|
957
1281
|
raise SyntaxError, "Block argument should not be given." if
|
958
1282
|
args && args.node_type == :block_pass
|
959
1283
|
|
960
|
-
args ||= s(:arglist)
|
1284
|
+
args ||= s(:arglist).line lexer.lineno
|
961
1285
|
|
962
1286
|
args.sexp_type = :arglist if [:call_args, :array].include? args.sexp_type
|
963
|
-
args = s(:arglist, args) unless args.sexp_type == :arglist
|
1287
|
+
args = s(:arglist, args).line args.line unless args.sexp_type == :arglist
|
964
1288
|
|
965
|
-
|
1289
|
+
s(:yield, *args.sexp_body).line args.line
|
966
1290
|
end
|
967
1291
|
|
968
1292
|
def next_token
|
969
1293
|
token = self.lexer.next_token
|
970
1294
|
|
971
1295
|
if token and token.first != RubyLexer::EOF then
|
1296
|
+
self.last_token_type = token
|
972
1297
|
return token
|
973
1298
|
else
|
974
|
-
return [false,
|
975
|
-
end
|
976
|
-
end
|
977
|
-
|
978
|
-
def new_assign lhs, rhs
|
979
|
-
return nil unless lhs
|
980
|
-
|
981
|
-
rhs = value_expr rhs
|
982
|
-
|
983
|
-
case lhs.sexp_type
|
984
|
-
when :lasgn, :iasgn, :cdecl, :cvdecl, :gasgn, :cvasgn, :attrasgn, :safe_attrasgn then
|
985
|
-
lhs << rhs
|
986
|
-
when :const then
|
987
|
-
lhs.sexp_type = :cdecl
|
988
|
-
lhs << rhs
|
989
|
-
else
|
990
|
-
raise "unknown lhs #{lhs.inspect} w/ #{rhs.inspect}"
|
991
|
-
end
|
992
|
-
|
993
|
-
lhs
|
994
|
-
end
|
995
|
-
|
996
|
-
##
|
997
|
-
# Returns a UTF-8 encoded string after processing BOMs and magic
|
998
|
-
# encoding comments.
|
999
|
-
#
|
1000
|
-
# Holy crap... ok. Here goes:
|
1001
|
-
#
|
1002
|
-
# Ruby's file handling and encoding support is insane. We need to be
|
1003
|
-
# able to lex a file. The lexer file is explicitly UTF-8 to make
|
1004
|
-
# things cleaner. This allows us to deal with extended chars in
|
1005
|
-
# class and method names. In order to do this, we need to encode all
|
1006
|
-
# input source files as UTF-8. First, we look for a UTF-8 BOM by
|
1007
|
-
# looking at the first line while forcing its encoding to
|
1008
|
-
# ASCII-8BIT. If we find a BOM, we strip it and set the expected
|
1009
|
-
# encoding to UTF-8. Then, we search for a magic encoding comment.
|
1010
|
-
# If found, it overrides the BOM. Finally, we force the encoding of
|
1011
|
-
# the input string to whatever was found, and then encode that to
|
1012
|
-
# UTF-8 for compatibility with the lexer.
|
1013
|
-
|
1014
|
-
def handle_encoding str
|
1015
|
-
str = str.dup
|
1016
|
-
has_enc = str.respond_to? :encoding
|
1017
|
-
encoding = nil
|
1018
|
-
|
1019
|
-
header = str.each_line.first(2)
|
1020
|
-
header.map! { |s| s.force_encoding "ASCII-8BIT" } if has_enc
|
1021
|
-
|
1022
|
-
first = header.first || ""
|
1023
|
-
encoding, str = "utf-8", str[3..-1] if first =~ /\A\xEF\xBB\xBF/
|
1024
|
-
|
1025
|
-
encoding = $1.strip if header.find { |s|
|
1026
|
-
s[/^#.*?-\*-.*?coding:\s*([^ ;]+).*?-\*-/, 1] ||
|
1027
|
-
s[/^#.*(?:en)?coding(?:\s*[:=])\s*([\w-]+)/, 1]
|
1028
|
-
}
|
1029
|
-
|
1030
|
-
if encoding then
|
1031
|
-
if has_enc then
|
1032
|
-
encoding.sub!(/utf-8-.+$/, 'utf-8') # HACK for stupid emacs formats
|
1033
|
-
hack_encoding str, encoding
|
1034
|
-
else
|
1035
|
-
warn "Skipping magic encoding comment"
|
1036
|
-
end
|
1037
|
-
else
|
1038
|
-
# nothing specified... ugh. try to encode as utf-8
|
1039
|
-
hack_encoding str if has_enc
|
1299
|
+
return [false, false]
|
1040
1300
|
end
|
1041
|
-
|
1042
|
-
str
|
1043
1301
|
end
|
1044
1302
|
|
1045
|
-
def
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
str.force_encoding enc
|
1053
|
-
if str.valid_encoding? then
|
1054
|
-
str.encode! Encoding::UTF_8
|
1055
|
-
break
|
1056
|
-
end
|
1057
|
-
rescue Encoding::InvalidByteSequenceError
|
1058
|
-
# do nothing
|
1059
|
-
rescue Encoding::UndefinedConversionError
|
1060
|
-
# do nothing
|
1061
|
-
end
|
1062
|
-
end
|
1063
|
-
|
1064
|
-
# no amount of pain is enough for you.
|
1065
|
-
raise "Bad encoding. Need a magic encoding comment." unless
|
1066
|
-
str.encoding.name == "UTF-8"
|
1303
|
+
def on_error(et, ev, values)
|
1304
|
+
super
|
1305
|
+
rescue Racc::ParseError => e
|
1306
|
+
# I don't like how the exception obscures the error message
|
1307
|
+
e.message.replace "%s:%p :: %s" % [self.file, lexer.lineno, e.message.strip]
|
1308
|
+
warn e.message if $DEBUG
|
1309
|
+
raise
|
1067
1310
|
end
|
1068
1311
|
|
1069
1312
|
##
|
@@ -1078,7 +1321,7 @@ module RubyParserStuff
|
|
1078
1321
|
|
1079
1322
|
self.file = file.dup
|
1080
1323
|
|
1081
|
-
@yydebug = ENV.has_key?
|
1324
|
+
@yydebug = ENV.has_key? "DEBUG"
|
1082
1325
|
|
1083
1326
|
# HACK -- need to get tests passing more than have graceful code
|
1084
1327
|
self.lexer.ss = RPStringScanner.new str
|
@@ -1087,40 +1330,29 @@ module RubyParserStuff
|
|
1087
1330
|
end
|
1088
1331
|
end
|
1089
1332
|
|
1090
|
-
alias
|
1333
|
+
alias parse process
|
1091
1334
|
|
1092
1335
|
def remove_begin node
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1336
|
+
line = node.line
|
1337
|
+
|
1338
|
+
node = node.last while node and node.sexp_type == :begin and node.size == 2
|
1339
|
+
|
1340
|
+
node = s(:nil) if node == s(:begin)
|
1341
|
+
|
1342
|
+
node.line ||= line
|
1343
|
+
|
1098
1344
|
node
|
1099
1345
|
end
|
1100
1346
|
|
1347
|
+
alias value_expr remove_begin # TODO: for now..? could check the tree, but meh?
|
1348
|
+
|
1101
1349
|
def reset
|
1102
1350
|
lexer.reset
|
1103
1351
|
self.in_def = false
|
1104
1352
|
self.in_single = 0
|
1105
1353
|
self.env.reset
|
1106
1354
|
self.comments.clear
|
1107
|
-
|
1108
|
-
|
1109
|
-
def block_dup_check call_or_args, block
|
1110
|
-
syntax_error "Both block arg and actual block given." if
|
1111
|
-
block and call_or_args.block_pass?
|
1112
|
-
end
|
1113
|
-
|
1114
|
-
def inverted? val
|
1115
|
-
[:return, :next, :break, :yield].include? val[0].sexp_type
|
1116
|
-
end
|
1117
|
-
|
1118
|
-
def invert_block_call val
|
1119
|
-
(type, call), iter = val
|
1120
|
-
|
1121
|
-
iter.insert 1, call
|
1122
|
-
|
1123
|
-
[iter, s(type)]
|
1355
|
+
self.last_token_type = nil
|
1124
1356
|
end
|
1125
1357
|
|
1126
1358
|
def ret_args node
|
@@ -1135,7 +1367,7 @@ module RubyParserStuff
|
|
1135
1367
|
|
1136
1368
|
# HACK matz wraps ONE of the FOUR splats in a newline to
|
1137
1369
|
# distinguish. I use paren for now. ugh
|
1138
|
-
node = s(:svalue, node) if node.sexp_type == :splat and not node.paren
|
1370
|
+
node = s(:svalue, node).line node.line if node.sexp_type == :splat and not node.paren
|
1139
1371
|
node.sexp_type = :svalue if node.sexp_type == :arglist && node[1].sexp_type == :splat
|
1140
1372
|
end
|
1141
1373
|
|
@@ -1144,18 +1376,17 @@ module RubyParserStuff
|
|
1144
1376
|
|
1145
1377
|
def s(*args)
|
1146
1378
|
result = Sexp.new(*args)
|
1147
|
-
result.line ||= lexer.lineno if lexer.ss
|
1379
|
+
# result.line ||= lexer.lineno if lexer.ss unless ENV["CHECK_LINE_NUMS"] # otherwise...
|
1148
1380
|
result.file = self.file
|
1149
1381
|
result
|
1150
1382
|
end
|
1151
1383
|
|
1152
|
-
def
|
1153
|
-
|
1154
|
-
node.line = oldnode.line if oldnode
|
1155
|
-
node[2] = value_expr node[2] if node and node.sexp_type == :if
|
1156
|
-
node
|
1384
|
+
def syntax_error msg
|
1385
|
+
raise RubyParser::SyntaxError, msg
|
1157
1386
|
end
|
1158
1387
|
|
1388
|
+
alias yyerror syntax_error
|
1389
|
+
|
1159
1390
|
def void_stmts node
|
1160
1391
|
return nil unless node
|
1161
1392
|
return node unless node.sexp_type == :block
|
@@ -1173,17 +1404,34 @@ module RubyParserStuff
|
|
1173
1404
|
# do nothing for now
|
1174
1405
|
end
|
1175
1406
|
|
1176
|
-
|
1407
|
+
def whitespace_width line, remove_width = nil
|
1408
|
+
col = 0
|
1409
|
+
idx = 0
|
1177
1410
|
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1411
|
+
line.chars.each do |c|
|
1412
|
+
break if remove_width && col >= remove_width
|
1413
|
+
case c
|
1414
|
+
when " " then
|
1415
|
+
col += 1
|
1416
|
+
when "\t" then
|
1417
|
+
n = TAB_WIDTH * (col / TAB_WIDTH + 1)
|
1418
|
+
break if remove_width && n > remove_width
|
1419
|
+
col = n
|
1420
|
+
else
|
1421
|
+
break
|
1422
|
+
end
|
1423
|
+
idx += 1
|
1424
|
+
end
|
1425
|
+
|
1426
|
+
if remove_width then
|
1427
|
+
line[idx..-1]
|
1428
|
+
else
|
1429
|
+
col
|
1430
|
+
end
|
1185
1431
|
end
|
1186
1432
|
|
1433
|
+
alias remove_whitespace_width whitespace_width
|
1434
|
+
|
1187
1435
|
class Keyword
|
1188
1436
|
include RubyLexer::State::Values
|
1189
1437
|
|
@@ -1214,8 +1462,10 @@ module RubyParserStuff
|
|
1214
1462
|
# :expr_fitem = symbol literal as FNAME.
|
1215
1463
|
# :expr_value = :expr_beg -- work to remove. Need multi-state support.
|
1216
1464
|
|
1465
|
+
expr_woot = EXPR_FNAME|EXPR_FITEM
|
1466
|
+
|
1217
1467
|
wordlist = [
|
1218
|
-
["alias", [:kALIAS, :kALIAS ],
|
1468
|
+
["alias", [:kALIAS, :kALIAS ], expr_woot ],
|
1219
1469
|
["and", [:kAND, :kAND ], EXPR_BEG ],
|
1220
1470
|
["begin", [:kBEGIN, :kBEGIN ], EXPR_BEG ],
|
1221
1471
|
["break", [:kBREAK, :kBREAK ], EXPR_MID ],
|
@@ -1245,7 +1495,7 @@ module RubyParserStuff
|
|
1245
1495
|
["super", [:kSUPER, :kSUPER ], EXPR_ARG ],
|
1246
1496
|
["then", [:kTHEN, :kTHEN ], EXPR_BEG ],
|
1247
1497
|
["true", [:kTRUE, :kTRUE ], EXPR_END ],
|
1248
|
-
["undef", [:kUNDEF, :kUNDEF ],
|
1498
|
+
["undef", [:kUNDEF, :kUNDEF ], expr_woot ],
|
1249
1499
|
["unless", [:kUNLESS, :kUNLESS_MOD ], EXPR_BEG ],
|
1250
1500
|
["until", [:kUNTIL, :kUNTIL_MOD ], EXPR_BEG ],
|
1251
1501
|
["when", [:kWHEN, :kWHEN ], EXPR_BEG ],
|
@@ -1325,11 +1575,6 @@ module RubyParserStuff
|
|
1325
1575
|
@debug = debug
|
1326
1576
|
end
|
1327
1577
|
|
1328
|
-
def reset
|
1329
|
-
@stack = [false]
|
1330
|
-
log :reset if debug
|
1331
|
-
end
|
1332
|
-
|
1333
1578
|
def inspect
|
1334
1579
|
"StackState(#{@name}, #{@stack.inspect})"
|
1335
1580
|
end
|
@@ -1366,16 +1611,21 @@ module RubyParserStuff
|
|
1366
1611
|
log :push if debug
|
1367
1612
|
end
|
1368
1613
|
|
1369
|
-
def
|
1370
|
-
|
1371
|
-
|
1372
|
-
log :store if debug
|
1373
|
-
result
|
1614
|
+
def reset
|
1615
|
+
@stack = [false]
|
1616
|
+
log :reset if debug
|
1374
1617
|
end
|
1375
1618
|
|
1376
1619
|
def restore oldstate
|
1377
1620
|
@stack.replace oldstate
|
1378
1621
|
log :restore if debug
|
1379
1622
|
end
|
1623
|
+
|
1624
|
+
def store base = false
|
1625
|
+
result = @stack.dup
|
1626
|
+
@stack.replace [base]
|
1627
|
+
log :store if debug
|
1628
|
+
result
|
1629
|
+
end
|
1380
1630
|
end
|
1381
1631
|
end
|