ruby_parser 3.13.1 → 3.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,13 +6,45 @@ require "timeout"
6
6
  require "rp_extensions"
7
7
  require "rp_stringscanner"
8
8
 
9
+ class Sexp
10
+ def check_line_numbers
11
+ raise "bad nil line for:\n%s" % [self.pretty_inspect] if nil_line?
12
+ raise "bad line number for:\n%s" % [self.pretty_inspect] unless
13
+ Integer === self.line &&
14
+ self.line >= 1 &&
15
+ self.line <= self.line_min
16
+ end
17
+
18
+ ##
19
+ # Returns the maximum line number of the children of self.
20
+
21
+ def line_min
22
+ @line_min ||= [self.deep_each.map(&:line).min, self.line].compact.min
23
+ end
24
+
25
+ def nil_line?
26
+ self.deep_each.map(&:line).any?(&:nil?)
27
+ end
28
+ end
29
+
9
30
  module RubyParserStuff
10
- VERSION = "3.13.1"
31
+ VERSION = "3.14.0"
11
32
 
12
33
  attr_accessor :lexer, :in_def, :in_single, :file
13
34
  attr_accessor :in_kwarg
14
35
  attr_reader :env, :comments
15
36
 
37
+ ##
38
+ # Canonicalize conditionals. Eg:
39
+ #
40
+ # not x ? a : b
41
+ #
42
+ # becomes:
43
+ #
44
+ # x ? b : a
45
+
46
+ attr_accessor :canonicalize_conditions
47
+
16
48
  $good20 = []
17
49
 
18
50
  %w[
@@ -31,6 +63,28 @@ module RubyParserStuff
31
63
  end
32
64
  end
33
65
 
66
+ ##
67
+ # for pure ruby systems only
68
+
69
+ def do_parse
70
+ _racc_do_parse_rb(_racc_setup, false)
71
+ end if ENV["PURE_RUBY"] || ENV["CHECK_LINE_NUMS"]
72
+
73
+ if ENV["CHECK_LINE_NUMS"] then
74
+ def _racc_do_reduce arg, act
75
+ x = super
76
+
77
+ @racc_vstack.grep(Sexp).each do |sexp|
78
+ sexp.check_line_numbers
79
+ end
80
+ x
81
+ end
82
+ end
83
+
84
+ ARG_TYPES = [:arglist, :call_args, :array, :args].map { |k|
85
+ [k, true]
86
+ }.to_h
87
+
34
88
  has_enc = "".respond_to? :encoding
35
89
 
36
90
  # This is in sorted order of occurrence according to
@@ -48,85 +102,58 @@ module RubyParserStuff
48
102
  Encoding::EUC_JP
49
103
  ] if has_enc
50
104
 
51
- def syntax_error msg
52
- raise RubyParser::SyntaxError, msg
105
+ JUMP_TYPE = [:return, :next, :break, :yield].map { |k| [k, true] }.to_h
106
+
107
+ TAB_WIDTH = 8
108
+
109
+ def initialize(options = {})
110
+ super()
111
+
112
+ v = self.class.name[/2\d/]
113
+ raise "Bad Class name #{self.class}" unless v
114
+
115
+ self.lexer = RubyLexer.new v && v.to_i
116
+ self.lexer.parser = self
117
+ self.in_kwarg = false
118
+
119
+ @env = RubyParserStuff::Environment.new
120
+ @comments = []
121
+
122
+ @canonicalize_conditions = true
123
+
124
+ self.reset
53
125
  end
54
126
 
55
127
  def arg_blk_pass node1, node2 # TODO: nuke
56
- node1 = s(:arglist, node1) unless [:arglist, :call_args, :array, :args].include? node1.sexp_type
128
+ node1 = s(:arglist, node1) unless ARG_TYPES[node1.sexp_type]
57
129
  node1 << node2 if node2
58
130
  node1
59
131
  end
60
132
 
61
133
  def arg_concat node1, node2 # TODO: nuke
62
134
  raise "huh" unless node2
63
- node1 << s(:splat, node2).compact
64
- node1
65
- end
66
135
 
67
- def clean_mlhs sexp
68
- case sexp.sexp_type
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
136
+ splat = s(:splat, node2)
137
+ splat.line node2.line
87
138
 
88
- def block_var *args
89
- result = self.args args
90
- result.sexp_type = :masgn
91
- result
92
- end
93
-
94
- def array_to_hash array
95
- case array.sexp_type
96
- when :kwsplat then
97
- array
98
- else
99
- s(:hash, *array.sexp_body)
100
- end
139
+ node1 << splat
101
140
  end
102
141
 
103
- def call_args args
104
- result = s(:call_args)
105
-
106
- args.each do |arg|
107
- case arg
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
123
-
124
- result
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
- s(:attrasgn, receiver, :"[]=", *index.sexp_body).compact # [].sexp_body => nil
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
- return s(:match, node)
352
+ s(:match, node)
226
353
  else
227
- return node
354
+ node
228
355
  end
229
356
  when :and then
230
- return s(:and, cond(node[1]), cond(node[2]))
357
+ _, lhs, rhs = node
358
+ s(:and, cond(lhs), cond(rhs))
231
359
  when :or then
232
- return s(:or, cond(node[1]), cond(node[2]))
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
- return s(:flip2, lhs, rhs)
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
- return s(:flip3, lhs, rhs)
371
+ s(:flip3, lhs, rhs)
243
372
  else
244
- return node
245
- end
373
+ node
374
+ end.line node.line
246
375
  end
247
376
 
248
- ##
249
- # for pure ruby systems only
377
+ def dedent sexp
378
+ dedent_count = dedent_size sexp
250
379
 
251
- def do_parse
252
- _racc_do_parse_rb(_racc_setup, false)
253
- end if ENV['PURE_RUBY']
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
- def new_match lhs, rhs
256
- if lhs then
257
- case lhs.sexp_type
258
- when :dregx, :dregx_once then
259
- return s(:match2, lhs, rhs).line(lhs.line)
260
- when :lit then
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
- end
409
+ }
410
+ end
264
411
 
265
- if rhs then
266
- case rhs.sexp_type
267
- when :dregx, :dregx_once then
268
- return s(:match3, rhs, lhs).line(lhs.line)
269
- when :lit then
270
- return s(:match3, rhs, lhs).line(lhs.line) if Regexp === rhs.last
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,92 @@ 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 Encoding::InvalidByteSequenceError
503
+ # do nothing
504
+ rescue Encoding::UndefinedConversionError
505
+ # do nothing
506
+ end
507
+ end
508
+
509
+ # no amount of pain is enough for you.
510
+ raise "Bad encoding. Need a magic encoding comment." unless
511
+ str.encoding.name == "UTF-8"
512
+ end
513
+
306
514
  ##
307
- # Canonicalize conditionals. Eg:
308
- #
309
- # not x ? a : b
515
+ # Returns a UTF-8 encoded string after processing BOMs and magic
516
+ # encoding comments.
310
517
  #
311
- # becomes:
518
+ # Holy crap... ok. Here goes:
312
519
  #
313
- # x ? b : a
520
+ # Ruby's file handling and encoding support is insane. We need to be
521
+ # able to lex a file. The lexer file is explicitly UTF-8 to make
522
+ # things cleaner. This allows us to deal with extended chars in
523
+ # class and method names. In order to do this, we need to encode all
524
+ # input source files as UTF-8. First, we look for a UTF-8 BOM by
525
+ # looking at the first line while forcing its encoding to
526
+ # ASCII-8BIT. If we find a BOM, we strip it and set the expected
527
+ # encoding to UTF-8. Then, we search for a magic encoding comment.
528
+ # If found, it overrides the BOM. Finally, we force the encoding of
529
+ # the input string to whatever was found, and then encode that to
530
+ # UTF-8 for compatibility with the lexer.
314
531
 
315
- attr_accessor :canonicalize_conditions
532
+ def handle_encoding str
533
+ str = str.dup
534
+ has_enc = str.respond_to? :encoding
535
+ encoding = nil
316
536
 
317
- def initialize(options = {})
318
- super()
537
+ header = str.each_line.first(2)
538
+ header.map! { |s| s.force_encoding "ASCII-8BIT" } if has_enc
319
539
 
320
- v = self.class.name[/2\d/]
321
- raise "Bad Class name #{self.class}" unless v
540
+ first = header.first || ""
541
+ encoding, str = "utf-8", str[3..-1] if first =~ /\A\xEF\xBB\xBF/
322
542
 
323
- self.lexer = RubyLexer.new v && v.to_i
324
- self.lexer.parser = self
325
- self.in_kwarg = false
543
+ encoding = $1.strip if header.find { |s|
544
+ s[/^#.*?-\*-.*?coding:\s*([^ ;]+).*?-\*-/, 1] ||
545
+ s[/^#.*(?:en)?coding(?:\s*[:=])\s*([\w-]+)/, 1]
546
+ }
326
547
 
327
- @env = RubyParserStuff::Environment.new
328
- @comments = []
548
+ if encoding then
549
+ if has_enc then
550
+ encoding.sub!(/utf-8-.+$/, "utf-8") # HACK for stupid emacs formats
551
+ hack_encoding str, encoding
552
+ else
553
+ warn "Skipping magic encoding comment"
554
+ end
555
+ else
556
+ # nothing specified... ugh. try to encode as utf-8
557
+ hack_encoding str if has_enc
558
+ end
329
559
 
330
- @canonicalize_conditions = true
560
+ str
561
+ end
331
562
 
332
- self.reset
563
+ def invert_block_call val
564
+ ret, iter = val
565
+ type, call = ret
566
+
567
+ iter.insert 1, call
568
+
569
+ ret = s(type).line ret.line
570
+
571
+ [iter, ret]
572
+ end
573
+
574
+ def inverted? val
575
+ JUMP_TYPE[val[0].sexp_type]
333
576
  end
334
577
 
335
578
  def list_append list, item # TODO: nuke me *sigh*
@@ -350,7 +593,7 @@ module RubyParserStuff
350
593
 
351
594
  htype, ttype = head.sexp_type, tail.sexp_type
352
595
 
353
- head = s(:dstr, '', head) if htype == :evstr
596
+ head = s(:dstr, "", head).line head.line if htype == :evstr
354
597
 
355
598
  case ttype
356
599
  when :str then
@@ -369,15 +612,15 @@ module RubyParserStuff
369
612
  head.line = lineno
370
613
  else
371
614
  tail.sexp_type = :array
372
- tail[1] = s(:str, tail[1])
373
- tail.delete_at 1 if tail[1] == s(:str, '')
615
+ tail[1] = s(:str, tail[1]).line tail.line
616
+ tail.delete_at 1 if tail[1] == s(:str, "")
374
617
 
375
618
  head.push(*tail.sexp_body)
376
619
  end
377
620
  when :evstr then
378
621
  if htype == :str then
379
622
  f, l = head.file, head.line
380
- head = s(:dstr, *head.sexp_body)
623
+ head = s(:dstr, *head.sexp_body).line head.line
381
624
  head.file = f
382
625
  head.line = l
383
626
  end
@@ -408,12 +651,15 @@ module RubyParserStuff
408
651
  node = rhs
409
652
  end
410
653
 
411
- node[2] = s(type, rhs, right)
654
+ node.pop
655
+ node << s(type, rhs, right).line(rhs.line)
412
656
 
413
657
  return left
414
658
  end
415
659
 
416
- return s(type, left, right)
660
+ result = s(type, left, right)
661
+ result.line left.line if left.line
662
+ result
417
663
  end
418
664
 
419
665
  def new_aref val
@@ -422,6 +668,40 @@ module RubyParserStuff
422
668
  new_call val[0], :"[]", val[2]
423
669
  end
424
670
 
671
+ def new_assign lhs, rhs
672
+ return nil unless lhs
673
+
674
+ rhs = value_expr rhs
675
+
676
+ case lhs.sexp_type
677
+ when :lasgn, :iasgn, :cdecl, :cvdecl, :gasgn, :cvasgn, :attrasgn, :safe_attrasgn then
678
+ lhs << rhs
679
+ when :const then
680
+ lhs.sexp_type = :cdecl
681
+ lhs << rhs
682
+ else
683
+ raise "unknown lhs #{lhs.inspect} w/ #{rhs.inspect}"
684
+ end
685
+
686
+ lhs
687
+ end
688
+
689
+ def new_attrasgn recv, meth, call_op = :"."
690
+ meth = :"#{meth}="
691
+
692
+ result = case call_op.to_sym
693
+ when :"."
694
+ s(:attrasgn, recv, meth)
695
+ when :"&."
696
+ s(:safe_attrasgn, recv, meth)
697
+ else
698
+ raise "unknown call operator: `#{type.inspect}`"
699
+ end
700
+
701
+ result.line = recv.line
702
+ result
703
+ end
704
+
425
705
  def new_body val
426
706
  body, resbody, elsebody, ensurebody = val
427
707
 
@@ -445,43 +725,24 @@ module RubyParserStuff
445
725
 
446
726
  if elsebody and not resbody then
447
727
  warning("else without rescue is useless")
448
- result = s(:begin, result) if result
728
+ result = s(:begin, result).line result.line if result
449
729
  result = block_append(result, elsebody)
450
730
  end
451
731
 
452
- result = s(:ensure, result, ensurebody).compact if ensurebody
732
+ result = s(:ensure, result, ensurebody).compact.line result.line if ensurebody
453
733
 
454
734
  result
455
735
  end
456
736
 
457
737
  def new_brace_body args, body, lineno
458
- new_iter(nil, args, body).line(lineno)
738
+ new_iter(nil, args, body).line lineno
459
739
  end
460
740
 
461
- def argl x
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 = :'.'
741
+ def new_call recv, meth, args = nil, call_op = :"."
481
742
  result = case call_op.to_sym
482
- when :'.'
743
+ when :"."
483
744
  s(:call, recv, meth)
484
- when :'&.'
745
+ when :"&."
485
746
  s(:safe_call, recv, meth)
486
747
  else
487
748
  raise "unknown call operator: `#{type.inspect}`"
@@ -491,35 +752,20 @@ module RubyParserStuff
491
752
  # TODO: need a test with f(&b) { } to produce warning
492
753
 
493
754
  if args
494
- if [:arglist, :args, :array, :call_args].include? args.sexp_type
755
+ if ARG_TYPES[args.sexp_type] then
495
756
  result.concat args.sexp_body
496
757
  else
497
758
  result << args
498
759
  end
499
760
  end
500
761
 
501
- line = result.grep(Sexp).map(&:line).compact.min
502
- result.line = line if line
762
+ # line = result.grep(Sexp).map(&:line).compact.min
763
+ result.line = recv.line if recv
764
+ result.line ||= lexer.lineno
503
765
 
504
766
  result
505
767
  end
506
768
 
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
518
-
519
- result.line = recv.line
520
- result
521
- end
522
-
523
769
  def new_case expr, body, line
524
770
  result = s(:case, expr)
525
771
 
@@ -565,11 +811,27 @@ module RubyParserStuff
565
811
  result
566
812
  end
567
813
 
814
+ def new_const_op_asgn val
815
+ lhs, asgn_op, rhs = val[0], val[1].to_sym, val[2]
816
+
817
+ result = case asgn_op
818
+ when :"||" then
819
+ s(:op_asgn_or, lhs, rhs)
820
+ when :"&&" then
821
+ s(:op_asgn_and, lhs, rhs)
822
+ else
823
+ s(:op_asgn, lhs, asgn_op, rhs)
824
+ end
825
+
826
+ result.line = lhs.line
827
+ result
828
+ end
829
+
568
830
  def new_defn val
569
- (_, line), (name, _), _, args, body, * = val
570
- body ||= s(:nil)
831
+ (_, line), name, _, args, body, nil_body_line, * = val
832
+ body ||= s(:nil).line nil_body_line
571
833
 
572
- result = s(:defn, name.to_sym, args)
834
+ result = s(:defn, name.to_sym, args).line line
573
835
 
574
836
  if body then
575
837
  if body.sexp_type == :block then
@@ -579,8 +841,6 @@ module RubyParserStuff
579
841
  end
580
842
  end
581
843
 
582
- args.line line
583
- result.line = line
584
844
  result.comments = self.comments.pop
585
845
 
586
846
  result
@@ -588,7 +848,10 @@ module RubyParserStuff
588
848
 
589
849
  def new_defs val
590
850
  recv, (name, _line), args, body = val[1], val[4], val[6], val[7]
591
- body ||= s(:nil)
851
+ line, _ = val[5]
852
+ body ||= s(:nil).line line
853
+
854
+ args.line line
592
855
 
593
856
  result = s(:defs, recv, name.to_sym, args)
594
857
 
@@ -637,27 +900,59 @@ module RubyParserStuff
637
900
  result << args
638
901
  result << body if body
639
902
 
640
- args.sexp_type = :args unless args == 0
903
+ result.line call.line if call
641
904
 
642
- result
643
- end
905
+ unless args == 0 then
906
+ args.line call.line if call
907
+ args.sexp_type = :args
908
+ end
644
909
 
645
- def new_masgn_arg rhs, wrap = false
646
- rhs = value_expr(rhs)
647
- rhs = s(:to_ary, rhs) if wrap # HACK: could be array if lhs isn't right
648
- rhs
910
+ result
649
911
  end
650
912
 
651
913
  def new_masgn lhs, rhs, wrap = false
652
914
  _, ary = lhs
653
915
 
916
+ line = rhs.line
654
917
  rhs = value_expr(rhs)
655
918
  rhs = ary ? s(:to_ary, rhs) : s(:array, rhs) if wrap
919
+ rhs.line line if wrap
656
920
 
657
921
  lhs.delete_at 1 if ary.nil?
658
922
  lhs << rhs
659
923
 
660
- lhs
924
+ lhs
925
+ end
926
+
927
+ def new_masgn_arg rhs, wrap = false
928
+ rhs = value_expr(rhs)
929
+ # HACK: could be array if lhs isn't right
930
+ rhs = s(:to_ary, rhs).line rhs.line if wrap
931
+ rhs
932
+ end
933
+
934
+ def new_match lhs, rhs
935
+ if lhs then
936
+ case lhs.sexp_type
937
+ when :dregx, :dregx_once then
938
+ # TODO: no test coverage
939
+ return s(:match2, lhs, rhs).line(lhs.line)
940
+ when :lit then
941
+ return s(:match2, lhs, rhs).line(lhs.line) if Regexp === lhs.last
942
+ end
943
+ end
944
+
945
+ if rhs then
946
+ case rhs.sexp_type
947
+ when :dregx, :dregx_once then
948
+ # TODO: no test coverage
949
+ return s(:match3, rhs, lhs).line(lhs.line)
950
+ when :lit then
951
+ return s(:match3, rhs, lhs).line(lhs.line) if Regexp === rhs.last
952
+ end
953
+ end
954
+
955
+ new_call(lhs, :"=~", argl(rhs)).line lhs.line
661
956
  end
662
957
 
663
958
  def new_module val
@@ -680,37 +975,30 @@ module RubyParserStuff
680
975
 
681
976
  def new_op_asgn val
682
977
  lhs, asgn_op, arg = val[0], val[1].to_sym, val[2]
683
- name = lhs.value
978
+ name = gettable(lhs.value).line lhs.line
684
979
  arg = remove_begin(arg)
685
980
  result = case asgn_op # REFACTOR
686
981
  when :"||" then
687
982
  lhs << arg
688
- s(:op_asgn_or, self.gettable(name), lhs)
983
+ s(:op_asgn_or, name, lhs)
689
984
  when :"&&" then
690
985
  lhs << arg
691
- s(:op_asgn_and, self.gettable(name), lhs)
986
+ s(:op_asgn_and, name, lhs)
692
987
  else
693
- # TODO: why [2] ?
694
- lhs[2] = new_call(self.gettable(name), asgn_op, argl(arg))
988
+ lhs << new_call(name, asgn_op, argl(arg))
695
989
  lhs
696
990
  end
697
991
  result.line = lhs.line
698
992
  result
699
993
  end
700
994
 
701
- def new_const_op_asgn val
702
- lhs, asgn_op, rhs = val[0], val[1].to_sym, val[2]
995
+ def new_op_asgn1 val
996
+ lhs, _, args, _, op, rhs = val
703
997
 
704
- result = case asgn_op
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
998
+ args.sexp_type = :arglist if args
712
999
 
713
- result.line = lhs.line
1000
+ result = s(:op_asgn1, lhs, args, op.to_sym, rhs)
1001
+ result.line lhs.line
714
1002
  result
715
1003
  end
716
1004
 
@@ -719,9 +1007,9 @@ module RubyParserStuff
719
1007
  meth = :"#{meth}="
720
1008
 
721
1009
  result = case call_op.to_sym
722
- when :'.'
1010
+ when :"."
723
1011
  s(:op_asgn2, recv, meth, op.to_sym, arg)
724
- when :'&.'
1012
+ when :"&."
725
1013
  s(:safe_op_asgn2, recv, meth, op.to_sym, arg)
726
1014
  else
727
1015
  raise "unknown call operator: `#{type.inspect}`"
@@ -731,21 +1019,49 @@ module RubyParserStuff
731
1019
  result
732
1020
  end
733
1021
 
1022
+ def new_qsym_list
1023
+ result = s(:array).line lexer.lineno
1024
+ self.lexer.fixup_lineno
1025
+ result
1026
+ end
1027
+
1028
+ def new_qsym_list_entry val
1029
+ _, str, _ = val
1030
+ result = s(:lit, str.to_sym).line lexer.lineno
1031
+ self.lexer.fixup_lineno
1032
+ result
1033
+ end
1034
+
1035
+ def new_qword_list
1036
+ result = s(:array).line lexer.lineno
1037
+ self.lexer.fixup_lineno
1038
+ result
1039
+ end
1040
+
1041
+ def new_qword_list_entry val
1042
+ _, str, _ = val
1043
+ str.force_encoding("ASCII-8BIT") unless str.valid_encoding?
1044
+ result = s(:str, str).line lexer.lineno # TODO: problematic? grab from parser
1045
+ self.lexer.fixup_lineno
1046
+ result
1047
+ end
1048
+
734
1049
  def new_regexp val
735
- node = val[1] || s(:str, '')
736
- options = val[2]
1050
+ _, node, options = val
1051
+
1052
+ node ||= s(:str, "").line lexer.lineno
737
1053
 
738
1054
  o, k = 0, nil
739
1055
  options.split(//).uniq.each do |c| # FIX: this has a better home
740
1056
  v = {
741
- 'x' => Regexp::EXTENDED,
742
- 'i' => Regexp::IGNORECASE,
743
- 'm' => Regexp::MULTILINE,
744
- 'o' => Regexp::ONCE,
745
- 'n' => Regexp::ENC_NONE,
746
- 'e' => Regexp::ENC_EUC,
747
- 's' => Regexp::ENC_SJIS,
748
- 'u' => Regexp::ENC_UTF8,
1057
+ "x" => Regexp::EXTENDED,
1058
+ "i" => Regexp::IGNORECASE,
1059
+ "m" => Regexp::MULTILINE,
1060
+ "o" => Regexp::ONCE,
1061
+ "n" => Regexp::ENC_NONE,
1062
+ "e" => Regexp::ENC_EUC,
1063
+ "s" => Regexp::ENC_SJIS,
1064
+ "u" => Regexp::ENC_UTF8,
749
1065
  }[c]
750
1066
  raise "unknown regexp option: #{c}" unless v
751
1067
  o += v
@@ -778,7 +1094,7 @@ module RubyParserStuff
778
1094
  end
779
1095
  node << o if o and o != 0
780
1096
  else
781
- node = s(:dregx, '', node);
1097
+ node = s(:dregx, "", node).line node.line
782
1098
  node.sexp_type = :dregx_once if options =~ /o/
783
1099
  node << o if o and o != 0
784
1100
  end
@@ -786,19 +1102,20 @@ module RubyParserStuff
786
1102
  node
787
1103
  end
788
1104
 
789
- def new_rescue body, resbody
790
- s(:rescue, body, resbody)
791
- end
792
-
793
1105
  def new_resbody cond, body
794
1106
  if body && body.sexp_type == :block then
795
1107
  body.shift # remove block and splat it in directly
796
1108
  else
797
1109
  body = [body]
798
1110
  end
1111
+
799
1112
  s(:resbody, cond, *body).line cond.line
800
1113
  end
801
1114
 
1115
+ def new_rescue body, resbody
1116
+ s(:rescue, body, resbody).line body.line
1117
+ end
1118
+
802
1119
  def new_sclass val
803
1120
  recv, in_def, in_single, body = val[3], val[4], val[6], val[7]
804
1121
 
@@ -819,63 +1136,35 @@ module RubyParserStuff
819
1136
  end
820
1137
 
821
1138
  def new_string val
822
- str = val[0]
1139
+ str, = val
823
1140
  str.force_encoding("UTF-8")
824
1141
  str.force_encoding("ASCII-8BIT") unless str.valid_encoding?
825
- result = s(:str, str)
1142
+ result = s(:str, str).line lexer.lineno
826
1143
  self.lexer.fixup_lineno str.count("\n")
827
1144
  result
828
1145
  end
829
1146
 
830
- def new_qword_list_entry val
831
- str = val[1]
832
- str.force_encoding("ASCII-8BIT") unless str.valid_encoding?
833
- result = s(:str, str)
834
- self.lexer.fixup_lineno
835
- result
836
- end
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
1147
+ def new_super args
1148
+ if args && args.node_type == :block_pass then
1149
+ s(:super, args).line args.line
1150
+ else
1151
+ args ||= s(:arglist).line lexer.lineno
1152
+ s(:super, *args.sexp_body).line args.line
1153
+ end
866
1154
  end
867
1155
 
868
1156
  def new_symbol_list
869
- result = s(:array)
1157
+ result = s(:array).line lexer.lineno
870
1158
  self.lexer.fixup_lineno
871
1159
  result
872
1160
  end
873
1161
 
874
1162
  def new_symbol_list_entry val
875
- _list, sym, _nil = val # TODO: use _list
876
- result = val[1]
1163
+ _, sym, _ = val
877
1164
 
878
- result ||= s(:str, "")
1165
+ sym ||= s(:str, "")
1166
+
1167
+ line = lexer.lineno
879
1168
 
880
1169
  case sym.sexp_type
881
1170
  when :dstr then
@@ -883,26 +1172,21 @@ module RubyParserStuff
883
1172
  when :str then
884
1173
  sym = s(:lit, sym.last.to_sym)
885
1174
  else
886
- sym = s(:dsym, "", sym || s(:str, ""))
1175
+ sym = s(:dsym, "", sym || s(:str, "").line(line))
887
1176
  end
1177
+
1178
+ sym.line line
1179
+
888
1180
  self.lexer.fixup_lineno
889
- sym
890
- end
891
1181
 
892
- def new_super args
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
1182
+ sym
899
1183
  end
900
1184
 
901
1185
  def new_undef n, m = nil
902
1186
  if m then
903
- block_append(n, s(:undef, m))
1187
+ block_append(n, s(:undef, m).line(m.line))
904
1188
  else
905
- s(:undef, n)
1189
+ s(:undef, n).line n.line
906
1190
  end
907
1191
  end
908
1192
 
@@ -935,6 +1219,19 @@ module RubyParserStuff
935
1219
  new_until_or_while :while, block, expr, pre
936
1220
  end
937
1221
 
1222
+ def new_word_list
1223
+ result = s(:array).line lexer.lineno
1224
+ self.lexer.fixup_lineno
1225
+ result
1226
+ end
1227
+
1228
+ def new_word_list_entry val
1229
+ _, word, _ = val
1230
+ result = word.sexp_type == :evstr ? s(:dstr, "", word).line(word.line) : word
1231
+ self.lexer.fixup_lineno
1232
+ result
1233
+ end
1234
+
938
1235
  def new_xstring str
939
1236
  if str then
940
1237
  case str.sexp_type
@@ -943,11 +1240,11 @@ module RubyParserStuff
943
1240
  when :dstr
944
1241
  str.sexp_type = :dxstr
945
1242
  else
946
- str = s(:dxstr, '', str)
1243
+ str = s(:dxstr, "", str)
947
1244
  end
948
1245
  str
949
1246
  else
950
- s(:xstr, '')
1247
+ s(:xstr, "")
951
1248
  end
952
1249
  end
953
1250
 
@@ -957,12 +1254,12 @@ module RubyParserStuff
957
1254
  raise SyntaxError, "Block argument should not be given." if
958
1255
  args && args.node_type == :block_pass
959
1256
 
960
- args ||= s(:arglist)
1257
+ args ||= s(:arglist).line lexer.lineno
961
1258
 
962
1259
  args.sexp_type = :arglist if [:call_args, :array].include? args.sexp_type
963
- args = s(:arglist, args) unless args.sexp_type == :arglist
1260
+ args = s(:arglist, args).line args.line unless args.sexp_type == :arglist
964
1261
 
965
- return s(:yield, *args.sexp_body)
1262
+ s(:yield, *args.sexp_body).line args.line
966
1263
  end
967
1264
 
968
1265
  def next_token
@@ -971,99 +1268,17 @@ module RubyParserStuff
971
1268
  if token and token.first != RubyLexer::EOF then
972
1269
  return token
973
1270
  else
974
- return [false, '$end']
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
1271
+ return [false, false]
1040
1272
  end
1041
-
1042
- str
1043
1273
  end
1044
1274
 
1045
- def hack_encoding str, extra = nil
1046
- encodings = ENCODING_ORDER.dup
1047
- encodings.unshift(extra) unless extra.nil?
1048
-
1049
- # terrible, horrible, no good, very bad, last ditch effort.
1050
- encodings.each do |enc|
1051
- begin
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"
1275
+ def on_error(et, ev, values)
1276
+ super
1277
+ rescue Racc::ParseError => e
1278
+ # I don't like how the exception obscures the error message
1279
+ e.message.replace "%s:%p :: %s" % [self.file, lexer.lineno, e.message.strip]
1280
+ warn e.message if $DEBUG
1281
+ raise
1067
1282
  end
1068
1283
 
1069
1284
  ##
@@ -1078,7 +1293,7 @@ module RubyParserStuff
1078
1293
 
1079
1294
  self.file = file.dup
1080
1295
 
1081
- @yydebug = ENV.has_key? 'DEBUG'
1296
+ @yydebug = ENV.has_key? "DEBUG"
1082
1297
 
1083
1298
  # HACK -- need to get tests passing more than have graceful code
1084
1299
  self.lexer.ss = RPStringScanner.new str
@@ -1087,17 +1302,22 @@ module RubyParserStuff
1087
1302
  end
1088
1303
  end
1089
1304
 
1090
- alias :parse :process
1305
+ alias parse process
1091
1306
 
1092
1307
  def remove_begin node
1093
- oldnode = node
1094
- if node and node.sexp_type == :begin and node.size == 2 then
1095
- node = node.last
1096
- node.line = oldnode.line
1097
- end
1308
+ line = node.line
1309
+
1310
+ node = node.last while node and node.sexp_type == :begin and node.size == 2
1311
+
1312
+ node = s(:nil) if node == s(:begin)
1313
+
1314
+ node.line ||= line
1315
+
1098
1316
  node
1099
1317
  end
1100
1318
 
1319
+ alias value_expr remove_begin # TODO: for now..? could check the tree, but meh?
1320
+
1101
1321
  def reset
1102
1322
  lexer.reset
1103
1323
  self.in_def = false
@@ -1106,23 +1326,6 @@ module RubyParserStuff
1106
1326
  self.comments.clear
1107
1327
  end
1108
1328
 
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)]
1124
- end
1125
-
1126
1329
  def ret_args node
1127
1330
  if node then
1128
1331
  raise "write a test 5" if node.sexp_type == :block_pass
@@ -1135,7 +1338,7 @@ module RubyParserStuff
1135
1338
 
1136
1339
  # HACK matz wraps ONE of the FOUR splats in a newline to
1137
1340
  # distinguish. I use paren for now. ugh
1138
- node = s(:svalue, node) if node.sexp_type == :splat and not node.paren
1341
+ node = s(:svalue, node).line node.line if node.sexp_type == :splat and not node.paren
1139
1342
  node.sexp_type = :svalue if node.sexp_type == :arglist && node[1].sexp_type == :splat
1140
1343
  end
1141
1344
 
@@ -1144,18 +1347,17 @@ module RubyParserStuff
1144
1347
 
1145
1348
  def s(*args)
1146
1349
  result = Sexp.new(*args)
1147
- result.line ||= lexer.lineno if lexer.ss # otherwise...
1350
+ # result.line ||= lexer.lineno if lexer.ss unless ENV["CHECK_LINE_NUMS"] # otherwise...
1148
1351
  result.file = self.file
1149
1352
  result
1150
1353
  end
1151
1354
 
1152
- def value_expr oldnode # HACK: much more to do
1153
- node = remove_begin oldnode
1154
- node.line = oldnode.line if oldnode
1155
- node[2] = value_expr node[2] if node and node.sexp_type == :if
1156
- node
1355
+ def syntax_error msg
1356
+ raise RubyParser::SyntaxError, msg
1157
1357
  end
1158
1358
 
1359
+ alias yyerror syntax_error
1360
+
1159
1361
  def void_stmts node
1160
1362
  return nil unless node
1161
1363
  return node unless node.sexp_type == :block
@@ -1173,17 +1375,34 @@ module RubyParserStuff
1173
1375
  # do nothing for now
1174
1376
  end
1175
1377
 
1176
- alias yyerror syntax_error
1378
+ def whitespace_width line, remove_width = nil
1379
+ col = 0
1380
+ idx = 0
1177
1381
 
1178
- def on_error(et, ev, values)
1179
- super
1180
- rescue Racc::ParseError => e
1181
- # I don't like how the exception obscures the error message
1182
- e.message.replace "%s:%p :: %s" % [self.file, lexer.lineno, e.message.strip]
1183
- warn e.message if $DEBUG
1184
- raise
1382
+ line.chars.each do |c|
1383
+ break if remove_width && col >= remove_width
1384
+ case c
1385
+ when " " then
1386
+ col += 1
1387
+ when "\t" then
1388
+ n = TAB_WIDTH * (col / TAB_WIDTH + 1)
1389
+ break if remove_width && n > remove_width
1390
+ col = n
1391
+ else
1392
+ break
1393
+ end
1394
+ idx += 1
1395
+ end
1396
+
1397
+ if remove_width then
1398
+ line[idx..-1]
1399
+ else
1400
+ col
1401
+ end
1185
1402
  end
1186
1403
 
1404
+ alias remove_whitespace_width whitespace_width
1405
+
1187
1406
  class Keyword
1188
1407
  include RubyLexer::State::Values
1189
1408
 
@@ -1214,8 +1433,10 @@ module RubyParserStuff
1214
1433
  # :expr_fitem = symbol literal as FNAME.
1215
1434
  # :expr_value = :expr_beg -- work to remove. Need multi-state support.
1216
1435
 
1436
+ expr_woot = EXPR_FNAME|EXPR_FITEM
1437
+
1217
1438
  wordlist = [
1218
- ["alias", [:kALIAS, :kALIAS ], EXPR_FNAME|EXPR_FITEM],
1439
+ ["alias", [:kALIAS, :kALIAS ], expr_woot ],
1219
1440
  ["and", [:kAND, :kAND ], EXPR_BEG ],
1220
1441
  ["begin", [:kBEGIN, :kBEGIN ], EXPR_BEG ],
1221
1442
  ["break", [:kBREAK, :kBREAK ], EXPR_MID ],
@@ -1245,7 +1466,7 @@ module RubyParserStuff
1245
1466
  ["super", [:kSUPER, :kSUPER ], EXPR_ARG ],
1246
1467
  ["then", [:kTHEN, :kTHEN ], EXPR_BEG ],
1247
1468
  ["true", [:kTRUE, :kTRUE ], EXPR_END ],
1248
- ["undef", [:kUNDEF, :kUNDEF ], EXPR_FNAME|EXPR_FITEM],
1469
+ ["undef", [:kUNDEF, :kUNDEF ], expr_woot ],
1249
1470
  ["unless", [:kUNLESS, :kUNLESS_MOD ], EXPR_BEG ],
1250
1471
  ["until", [:kUNTIL, :kUNTIL_MOD ], EXPR_BEG ],
1251
1472
  ["when", [:kWHEN, :kWHEN ], EXPR_BEG ],
@@ -1325,11 +1546,6 @@ module RubyParserStuff
1325
1546
  @debug = debug
1326
1547
  end
1327
1548
 
1328
- def reset
1329
- @stack = [false]
1330
- log :reset if debug
1331
- end
1332
-
1333
1549
  def inspect
1334
1550
  "StackState(#{@name}, #{@stack.inspect})"
1335
1551
  end
@@ -1366,16 +1582,21 @@ module RubyParserStuff
1366
1582
  log :push if debug
1367
1583
  end
1368
1584
 
1369
- def store base = false
1370
- result = @stack.dup
1371
- @stack.replace [base]
1372
- log :store if debug
1373
- result
1585
+ def reset
1586
+ @stack = [false]
1587
+ log :reset if debug
1374
1588
  end
1375
1589
 
1376
1590
  def restore oldstate
1377
1591
  @stack.replace oldstate
1378
1592
  log :restore if debug
1379
1593
  end
1594
+
1595
+ def store base = false
1596
+ result = @stack.dup
1597
+ @stack.replace [base]
1598
+ log :store if debug
1599
+ result
1600
+ end
1380
1601
  end
1381
1602
  end