syntax_tree 3.6.3 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +15 -1
- data/Gemfile.lock +5 -5
- data/README.md +32 -10
- data/bin/profile +5 -6
- data/lib/syntax_tree/cli.rb +3 -3
- data/lib/syntax_tree/formatter.rb +67 -8
- data/lib/syntax_tree/node.rb +775 -527
- data/lib/syntax_tree/parser.rb +335 -245
- data/lib/syntax_tree/version.rb +1 -1
- data/lib/syntax_tree/visitor/environment.rb +81 -0
- data/lib/syntax_tree/visitor/with_environment.rb +141 -0
- data/lib/syntax_tree.rb +14 -2
- data/syntax_tree.gemspec +1 -1
- metadata +6 -4
data/lib/syntax_tree/parser.rb
CHANGED
@@ -60,29 +60,46 @@ module SyntaxTree
|
|
60
60
|
# This represents all of the tokens coming back from the lexer. It is
|
61
61
|
# replacing a simple array because it keeps track of the last deleted token
|
62
62
|
# from the list for better error messages.
|
63
|
-
class TokenList
|
64
|
-
attr_reader :last_deleted
|
63
|
+
class TokenList
|
64
|
+
attr_reader :tokens, :last_deleted
|
65
65
|
|
66
|
-
def initialize
|
67
|
-
|
66
|
+
def initialize
|
67
|
+
@tokens = []
|
68
68
|
@last_deleted = nil
|
69
69
|
end
|
70
70
|
|
71
|
+
def <<(token)
|
72
|
+
tokens << token
|
73
|
+
end
|
74
|
+
|
75
|
+
def [](index)
|
76
|
+
tokens[index]
|
77
|
+
end
|
78
|
+
|
79
|
+
def any?(&block)
|
80
|
+
tokens.any?(&block)
|
81
|
+
end
|
82
|
+
|
83
|
+
def reverse_each(&block)
|
84
|
+
tokens.reverse_each(&block)
|
85
|
+
end
|
86
|
+
|
87
|
+
def rindex(&block)
|
88
|
+
tokens.rindex(&block)
|
89
|
+
end
|
90
|
+
|
71
91
|
def delete(value)
|
72
|
-
@last_deleted =
|
92
|
+
@last_deleted = tokens.delete(value) || @last_deleted
|
73
93
|
end
|
74
94
|
|
75
95
|
def delete_at(index)
|
76
|
-
@last_deleted =
|
96
|
+
@last_deleted = tokens.delete_at(index)
|
77
97
|
end
|
78
98
|
end
|
79
99
|
|
80
100
|
# [String] the source being parsed
|
81
101
|
attr_reader :source
|
82
102
|
|
83
|
-
# [Array[ String ]] the list of lines in the source
|
84
|
-
attr_reader :lines
|
85
|
-
|
86
103
|
# [Array[ SingleByteString | MultiByteString ]] the list of objects that
|
87
104
|
# represent the start of each line in character offsets
|
88
105
|
attr_reader :line_counts
|
@@ -105,12 +122,6 @@ module SyntaxTree
|
|
105
122
|
# example.
|
106
123
|
@source = source
|
107
124
|
|
108
|
-
# Similarly, we keep the lines of the source string around to be able to
|
109
|
-
# check if certain lines contain certain characters. For example, we'll
|
110
|
-
# use this to generate the content that goes after the __END__ keyword.
|
111
|
-
# Or we'll use this to check if a comment has other content on its line.
|
112
|
-
@lines = source.split(/\r?\n/)
|
113
|
-
|
114
125
|
# This is the full set of comments that have been found by the parser.
|
115
126
|
# It's a running list. At the end of every block of statements, they will
|
116
127
|
# go in and attempt to grab any comments that are on their own line and
|
@@ -144,7 +155,7 @@ module SyntaxTree
|
|
144
155
|
# Most of the time, when a parser event consumes one of these events, it
|
145
156
|
# will be deleted from the list. So ideally, this list stays pretty short
|
146
157
|
# over the course of parsing a source string.
|
147
|
-
@tokens = TokenList.new
|
158
|
+
@tokens = TokenList.new
|
148
159
|
|
149
160
|
# Here we're going to build up a list of SingleByteString or
|
150
161
|
# MultiByteString objects. They're each going to represent a string in the
|
@@ -153,7 +164,7 @@ module SyntaxTree
|
|
153
164
|
@line_counts = []
|
154
165
|
last_index = 0
|
155
166
|
|
156
|
-
@source.
|
167
|
+
@source.each_line do |line|
|
157
168
|
@line_counts << if line.size == line.bytesize
|
158
169
|
SingleByteString.new(last_index)
|
159
170
|
else
|
@@ -233,28 +244,55 @@ module SyntaxTree
|
|
233
244
|
# "module" (which would happen to be the innermost keyword). Then the outer
|
234
245
|
# one would only be able to grab the first one. In this way all of the
|
235
246
|
# tokens act as their own stack.
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
247
|
+
#
|
248
|
+
# If we're expecting to be able to find a token and consume it, but can't
|
249
|
+
# actually find it, then we need to raise an error. This is _usually_ caused
|
250
|
+
# by a syntax error in the source that we're printing. It could also be
|
251
|
+
# caused by accidentally attempting to consume a token twice by two
|
252
|
+
# different parser event handlers.
|
241
253
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
# It could also be caused by accidentally attempting to consume a token
|
247
|
-
# twice by two different parser event handlers.
|
248
|
-
unless index
|
249
|
-
token = value == :any ? type.name.split("::", 2).last : value
|
250
|
-
message = "Cannot find expected #{token}"
|
251
|
-
raise ParseError.new(message, *find_token_error(location))
|
252
|
-
end
|
254
|
+
def find_token(type)
|
255
|
+
index = tokens.rindex { |token| token.is_a?(type) }
|
256
|
+
tokens[index] if index
|
257
|
+
end
|
253
258
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
259
|
+
def find_keyword(name)
|
260
|
+
index = tokens.rindex { |token| token.is_a?(Kw) && (token.name == name) }
|
261
|
+
tokens[index] if index
|
262
|
+
end
|
263
|
+
|
264
|
+
def find_operator(name)
|
265
|
+
index = tokens.rindex { |token| token.is_a?(Op) && (token.name == name) }
|
266
|
+
tokens[index] if index
|
267
|
+
end
|
268
|
+
|
269
|
+
def consume_error(name, location)
|
270
|
+
message = "Cannot find expected #{name}"
|
271
|
+
raise ParseError.new(message, *find_token_error(location))
|
272
|
+
end
|
273
|
+
|
274
|
+
def consume_token(type)
|
275
|
+
index = tokens.rindex { |token| token.is_a?(type) }
|
276
|
+
consume_error(type.name.split("::", 2).last, nil) unless index
|
277
|
+
tokens.delete_at(index)
|
278
|
+
end
|
279
|
+
|
280
|
+
def consume_tstring_end(location)
|
281
|
+
index = tokens.rindex { |token| token.is_a?(TStringEnd) }
|
282
|
+
consume_error("string ending", location) unless index
|
283
|
+
tokens.delete_at(index)
|
284
|
+
end
|
285
|
+
|
286
|
+
def consume_keyword(name)
|
287
|
+
index = tokens.rindex { |token| token.is_a?(Kw) && (token.name == name) }
|
288
|
+
consume_error(name, nil) unless index
|
289
|
+
tokens.delete_at(index)
|
290
|
+
end
|
291
|
+
|
292
|
+
def consume_operator(name)
|
293
|
+
index = tokens.rindex { |token| token.is_a?(Op) && (token.name == name) }
|
294
|
+
consume_error(name, nil) unless index
|
295
|
+
tokens.delete_at(index)
|
258
296
|
end
|
259
297
|
|
260
298
|
# A helper function to find a :: operator. We do special handling instead of
|
@@ -283,13 +321,18 @@ module SyntaxTree
|
|
283
321
|
# By finding the next non-space character, we can make sure that the bounds
|
284
322
|
# of the statement list are correct.
|
285
323
|
def find_next_statement_start(position)
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
324
|
+
maximum = source.length
|
325
|
+
|
326
|
+
position.upto(maximum) do |pound_index|
|
327
|
+
case source[pound_index]
|
328
|
+
when "#"
|
329
|
+
return source.index("\n", pound_index + 1) || maximum
|
330
|
+
when " "
|
331
|
+
# continue
|
332
|
+
else
|
333
|
+
return position
|
334
|
+
end
|
290
335
|
end
|
291
|
-
|
292
|
-
position
|
293
336
|
end
|
294
337
|
|
295
338
|
# --------------------------------------------------------------------------
|
@@ -300,8 +343,8 @@ module SyntaxTree
|
|
300
343
|
# :call-seq:
|
301
344
|
# on_BEGIN: (Statements statements) -> BEGINBlock
|
302
345
|
def on_BEGIN(statements)
|
303
|
-
lbrace =
|
304
|
-
rbrace =
|
346
|
+
lbrace = consume_token(LBrace)
|
347
|
+
rbrace = consume_token(RBrace)
|
305
348
|
|
306
349
|
start_char = find_next_statement_start(lbrace.location.end_char)
|
307
350
|
statements.bind(
|
@@ -311,7 +354,7 @@ module SyntaxTree
|
|
311
354
|
rbrace.location.start_column
|
312
355
|
)
|
313
356
|
|
314
|
-
keyword =
|
357
|
+
keyword = consume_keyword(:BEGIN)
|
315
358
|
|
316
359
|
BEGINBlock.new(
|
317
360
|
lbrace: lbrace,
|
@@ -338,8 +381,8 @@ module SyntaxTree
|
|
338
381
|
# :call-seq:
|
339
382
|
# on_END: (Statements statements) -> ENDBlock
|
340
383
|
def on_END(statements)
|
341
|
-
lbrace =
|
342
|
-
rbrace =
|
384
|
+
lbrace = consume_token(LBrace)
|
385
|
+
rbrace = consume_token(RBrace)
|
343
386
|
|
344
387
|
start_char = find_next_statement_start(lbrace.location.end_char)
|
345
388
|
statements.bind(
|
@@ -349,7 +392,7 @@ module SyntaxTree
|
|
349
392
|
rbrace.location.start_column
|
350
393
|
)
|
351
394
|
|
352
|
-
keyword =
|
395
|
+
keyword = consume_keyword(:END)
|
353
396
|
|
354
397
|
ENDBlock.new(
|
355
398
|
lbrace: lbrace,
|
@@ -380,7 +423,7 @@ module SyntaxTree
|
|
380
423
|
# (DynaSymbol | SymbolLiteral) right
|
381
424
|
# ) -> Alias
|
382
425
|
def on_alias(left, right)
|
383
|
-
keyword =
|
426
|
+
keyword = consume_keyword(:alias)
|
384
427
|
|
385
428
|
Alias.new(
|
386
429
|
left: left,
|
@@ -392,8 +435,8 @@ module SyntaxTree
|
|
392
435
|
# :call-seq:
|
393
436
|
# on_aref: (untyped collection, (nil | Args) index) -> ARef
|
394
437
|
def on_aref(collection, index)
|
395
|
-
|
396
|
-
rbracket =
|
438
|
+
consume_token(LBracket)
|
439
|
+
rbracket = consume_token(RBracket)
|
397
440
|
|
398
441
|
ARef.new(
|
399
442
|
collection: collection,
|
@@ -408,8 +451,8 @@ module SyntaxTree
|
|
408
451
|
# (nil | Args) index
|
409
452
|
# ) -> ARefField
|
410
453
|
def on_aref_field(collection, index)
|
411
|
-
|
412
|
-
rbracket =
|
454
|
+
consume_token(LBracket)
|
455
|
+
rbracket = consume_token(RBracket)
|
413
456
|
|
414
457
|
ARefField.new(
|
415
458
|
collection: collection,
|
@@ -427,8 +470,8 @@ module SyntaxTree
|
|
427
470
|
# (nil | Args | ArgsForward) arguments
|
428
471
|
# ) -> ArgParen
|
429
472
|
def on_arg_paren(arguments)
|
430
|
-
lparen =
|
431
|
-
rparen =
|
473
|
+
lparen = consume_token(LParen)
|
474
|
+
rparen = consume_token(RParen)
|
432
475
|
|
433
476
|
# If the arguments exceed the ending of the parentheses, then we know we
|
434
477
|
# have a heredoc in the arguments, and we need to use the bounds of the
|
@@ -470,23 +513,26 @@ module SyntaxTree
|
|
470
513
|
# (false | untyped) block
|
471
514
|
# ) -> Args
|
472
515
|
def on_args_add_block(arguments, block)
|
516
|
+
end_char = arguments.parts.any? && arguments.location.end_char
|
517
|
+
|
473
518
|
# First, see if there is an & operator that could potentially be
|
474
519
|
# associated with the block part of this args_add_block. If there is not,
|
475
520
|
# then just return the arguments.
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
521
|
+
index =
|
522
|
+
tokens.rindex do |token|
|
523
|
+
# If there are any arguments and the operator we found from the list
|
524
|
+
# is not after them, then we're going to return the arguments as-is
|
525
|
+
# because we're looking at an & that occurs before the arguments are
|
526
|
+
# done.
|
527
|
+
return arguments if end_char && token.location.start_char < end_char
|
528
|
+
token.is_a?(Op) && (token.name == :&)
|
529
|
+
end
|
530
|
+
|
531
|
+
return arguments unless index
|
486
532
|
|
487
533
|
# Now we know we have an & operator, so we're going to delete it from the
|
488
534
|
# list of tokens to make sure it doesn't get confused with anything else.
|
489
|
-
tokens.
|
535
|
+
operator = tokens.delete_at(index)
|
490
536
|
|
491
537
|
# Construct the location that represents the block argument.
|
492
538
|
location = operator.location
|
@@ -505,7 +551,7 @@ module SyntaxTree
|
|
505
551
|
# :call-seq:
|
506
552
|
# on_args_add_star: (Args arguments, untyped star) -> Args
|
507
553
|
def on_args_add_star(arguments, argument)
|
508
|
-
beginning =
|
554
|
+
beginning = consume_operator(:*)
|
509
555
|
ending = argument || beginning
|
510
556
|
|
511
557
|
location =
|
@@ -527,7 +573,7 @@ module SyntaxTree
|
|
527
573
|
# :call-seq:
|
528
574
|
# on_args_forward: () -> ArgsForward
|
529
575
|
def on_args_forward
|
530
|
-
op =
|
576
|
+
op = consume_operator(:"...")
|
531
577
|
|
532
578
|
ArgsForward.new(value: op.value, location: op.location)
|
533
579
|
end
|
@@ -547,8 +593,8 @@ module SyntaxTree
|
|
547
593
|
# ArrayLiteral | QSymbols | QWords | Symbols | Words
|
548
594
|
def on_array(contents)
|
549
595
|
if !contents || contents.is_a?(Args)
|
550
|
-
lbracket =
|
551
|
-
rbracket =
|
596
|
+
lbracket = consume_token(LBracket)
|
597
|
+
rbracket = consume_token(RBracket)
|
552
598
|
|
553
599
|
ArrayLiteral.new(
|
554
600
|
lbracket: lbracket,
|
@@ -556,8 +602,7 @@ module SyntaxTree
|
|
556
602
|
location: lbracket.location.to(rbracket.location)
|
557
603
|
)
|
558
604
|
else
|
559
|
-
tstring_end =
|
560
|
-
find_token(TStringEnd, location: contents.beginning.location)
|
605
|
+
tstring_end = consume_tstring_end(contents.beginning.location)
|
561
606
|
|
562
607
|
contents.class.new(
|
563
608
|
beginning: contents.beginning,
|
@@ -567,6 +612,56 @@ module SyntaxTree
|
|
567
612
|
end
|
568
613
|
end
|
569
614
|
|
615
|
+
# Ugh... I really do not like this class. Basically, ripper doesn't provide
|
616
|
+
# enough information about where pins are located in the tree. It only gives
|
617
|
+
# events for ^ ops and var_ref nodes. You have to piece it together
|
618
|
+
# yourself.
|
619
|
+
#
|
620
|
+
# Note that there are edge cases here that we straight up do not address,
|
621
|
+
# because I honestly think it's going to be faster to write a new parser
|
622
|
+
# than to address them. For example, this will not work properly:
|
623
|
+
#
|
624
|
+
# foo in ^((bar = 0; bar; baz))
|
625
|
+
#
|
626
|
+
# If someone actually does something like that, we'll have to find another
|
627
|
+
# way to make this work.
|
628
|
+
class PinVisitor < Visitor
|
629
|
+
attr_reader :pins, :stack
|
630
|
+
|
631
|
+
def initialize(pins)
|
632
|
+
@pins = pins
|
633
|
+
@stack = []
|
634
|
+
end
|
635
|
+
|
636
|
+
def visit(node)
|
637
|
+
return if pins.empty?
|
638
|
+
stack << node
|
639
|
+
super
|
640
|
+
stack.pop
|
641
|
+
end
|
642
|
+
|
643
|
+
def visit_var_ref(node)
|
644
|
+
pins.shift
|
645
|
+
node.pin(stack[-2])
|
646
|
+
end
|
647
|
+
|
648
|
+
def self.visit(node, tokens)
|
649
|
+
start_char = node.location.start_char
|
650
|
+
allocated = []
|
651
|
+
|
652
|
+
tokens.reverse_each do |token|
|
653
|
+
char = token.location.start_char
|
654
|
+
break if char <= start_char
|
655
|
+
|
656
|
+
if token.is_a?(Op) && token.value == "^"
|
657
|
+
allocated.unshift(tokens.delete(token))
|
658
|
+
end
|
659
|
+
end
|
660
|
+
|
661
|
+
new(allocated).visit(node) if allocated.any?
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
570
665
|
# :call-seq:
|
571
666
|
# on_aryptn: (
|
572
667
|
# (nil | VarRef) constant,
|
@@ -583,7 +678,7 @@ module SyntaxTree
|
|
583
678
|
# of the various parts.
|
584
679
|
location =
|
585
680
|
if parts.empty?
|
586
|
-
|
681
|
+
consume_token(LBracket).location.to(consume_token(RBracket).location)
|
587
682
|
else
|
588
683
|
parts[0].location.to(parts[-1].location)
|
589
684
|
end
|
@@ -594,12 +689,13 @@ module SyntaxTree
|
|
594
689
|
if rest.is_a?(VarField) && rest.value.nil?
|
595
690
|
tokens.rindex do |rtoken|
|
596
691
|
case rtoken
|
597
|
-
|
598
|
-
rest = VarField.new(value: nil, location: rtoken.location)
|
692
|
+
when Comma
|
599
693
|
break
|
600
|
-
|
601
|
-
|
602
|
-
|
694
|
+
when Op
|
695
|
+
if rtoken.value == "*"
|
696
|
+
rest = VarField.new(value: nil, location: rtoken.location)
|
697
|
+
break
|
698
|
+
end
|
603
699
|
end
|
604
700
|
end
|
605
701
|
end
|
@@ -644,7 +740,7 @@ module SyntaxTree
|
|
644
740
|
# :call-seq:
|
645
741
|
# on_assoc_splat: (untyped value) -> AssocSplat
|
646
742
|
def on_assoc_splat(value)
|
647
|
-
operator =
|
743
|
+
operator = consume_operator(:**)
|
648
744
|
|
649
745
|
AssocSplat.new(
|
650
746
|
value: value,
|
@@ -704,23 +800,23 @@ module SyntaxTree
|
|
704
800
|
# :call-seq:
|
705
801
|
# on_begin: (untyped bodystmt) -> Begin | PinnedBegin
|
706
802
|
def on_begin(bodystmt)
|
707
|
-
pin =
|
803
|
+
pin = find_operator(:^)
|
708
804
|
|
709
805
|
if pin && pin.location.start_char < bodystmt.location.start_char
|
710
806
|
tokens.delete(pin)
|
711
|
-
|
807
|
+
consume_token(LParen)
|
712
808
|
|
713
|
-
rparen =
|
809
|
+
rparen = consume_token(RParen)
|
714
810
|
location = pin.location.to(rparen.location)
|
715
811
|
|
716
812
|
PinnedBegin.new(statement: bodystmt, location: location)
|
717
813
|
else
|
718
|
-
keyword =
|
814
|
+
keyword = consume_keyword(:begin)
|
719
815
|
end_location =
|
720
816
|
if bodystmt.else_clause
|
721
817
|
bodystmt.location
|
722
818
|
else
|
723
|
-
|
819
|
+
consume_keyword(:end).location
|
724
820
|
end
|
725
821
|
|
726
822
|
bodystmt.bind(
|
@@ -746,13 +842,11 @@ module SyntaxTree
|
|
746
842
|
# Here, we're going to search backward for the token that's between the
|
747
843
|
# two operands that matches the operator so we can delete it from the
|
748
844
|
# list.
|
845
|
+
range = (left.location.end_char + 1)...right.location.start_char
|
749
846
|
index =
|
750
847
|
tokens.rindex do |token|
|
751
|
-
|
752
|
-
|
753
|
-
token.is_a?(Op) && token.value == operator.to_s &&
|
754
|
-
location.start_char > left.location.end_char &&
|
755
|
-
location.end_char < right.location.start_char
|
848
|
+
token.is_a?(Op) && token.name == operator &&
|
849
|
+
range.cover?(token.location.start_char)
|
756
850
|
end
|
757
851
|
|
758
852
|
tokens.delete_at(index) if index
|
@@ -795,7 +889,7 @@ module SyntaxTree
|
|
795
889
|
# :call-seq:
|
796
890
|
# on_blockarg: (Ident name) -> BlockArg
|
797
891
|
def on_blockarg(name)
|
798
|
-
operator =
|
892
|
+
operator = consume_operator(:&)
|
799
893
|
|
800
894
|
location = operator.location
|
801
895
|
location = location.to(name.location) if name
|
@@ -814,7 +908,7 @@ module SyntaxTree
|
|
814
908
|
BodyStmt.new(
|
815
909
|
statements: statements,
|
816
910
|
rescue_clause: rescue_clause,
|
817
|
-
else_keyword: else_clause &&
|
911
|
+
else_keyword: else_clause && consume_keyword(:else),
|
818
912
|
else_clause: else_clause,
|
819
913
|
ensure_clause: ensure_clause,
|
820
914
|
location:
|
@@ -828,8 +922,8 @@ module SyntaxTree
|
|
828
922
|
# Statements statements
|
829
923
|
# ) -> BraceBlock
|
830
924
|
def on_brace_block(block_var, statements)
|
831
|
-
lbrace =
|
832
|
-
rbrace =
|
925
|
+
lbrace = consume_token(LBrace)
|
926
|
+
rbrace = consume_token(RBrace)
|
833
927
|
location = (block_var || lbrace).location
|
834
928
|
|
835
929
|
start_char = find_next_statement_start(location.end_char)
|
@@ -864,7 +958,7 @@ module SyntaxTree
|
|
864
958
|
# :call-seq:
|
865
959
|
# on_break: (Args arguments) -> Break
|
866
960
|
def on_break(arguments)
|
867
|
-
keyword =
|
961
|
+
keyword = consume_keyword(:break)
|
868
962
|
|
869
963
|
location = keyword.location
|
870
964
|
location = location.to(arguments.location) if arguments.parts.any?
|
@@ -900,7 +994,7 @@ module SyntaxTree
|
|
900
994
|
# :call-seq:
|
901
995
|
# on_case: (untyped value, untyped consequent) -> Case | RAssign
|
902
996
|
def on_case(value, consequent)
|
903
|
-
if (keyword =
|
997
|
+
if (keyword = find_keyword(:case))
|
904
998
|
tokens.delete(keyword)
|
905
999
|
|
906
1000
|
Case.new(
|
@@ -911,18 +1005,22 @@ module SyntaxTree
|
|
911
1005
|
)
|
912
1006
|
else
|
913
1007
|
operator =
|
914
|
-
if (keyword =
|
1008
|
+
if (keyword = find_keyword(:in))
|
915
1009
|
tokens.delete(keyword)
|
916
1010
|
else
|
917
|
-
|
1011
|
+
consume_operator(:"=>")
|
918
1012
|
end
|
919
1013
|
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
1014
|
+
node =
|
1015
|
+
RAssign.new(
|
1016
|
+
value: value,
|
1017
|
+
operator: operator,
|
1018
|
+
pattern: consequent,
|
1019
|
+
location: value.location.to(consequent.location)
|
1020
|
+
)
|
1021
|
+
|
1022
|
+
PinVisitor.visit(node, tokens)
|
1023
|
+
node
|
926
1024
|
end
|
927
1025
|
end
|
928
1026
|
|
@@ -933,8 +1031,8 @@ module SyntaxTree
|
|
933
1031
|
# BodyStmt bodystmt
|
934
1032
|
# ) -> ClassDeclaration
|
935
1033
|
def on_class(constant, superclass, bodystmt)
|
936
|
-
beginning =
|
937
|
-
ending =
|
1034
|
+
beginning = consume_keyword(:class)
|
1035
|
+
ending = consume_keyword(:end)
|
938
1036
|
location = (superclass || constant).location
|
939
1037
|
start_char = find_next_statement_start(location.end_char)
|
940
1038
|
|
@@ -1004,20 +1102,20 @@ module SyntaxTree
|
|
1004
1102
|
# :call-seq:
|
1005
1103
|
# on_comment: (String value) -> Comment
|
1006
1104
|
def on_comment(value)
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
line: line,
|
1015
|
-
char: char_pos,
|
1016
|
-
column: current_column,
|
1017
|
-
size: value.size - 1
|
1018
|
-
)
|
1105
|
+
char = char_pos
|
1106
|
+
location =
|
1107
|
+
Location.token(
|
1108
|
+
line: lineno,
|
1109
|
+
char: char,
|
1110
|
+
column: current_column,
|
1111
|
+
size: value.size - 1
|
1019
1112
|
)
|
1020
1113
|
|
1114
|
+
index = source.rindex(/[^\t ]/, char - 1) if char != 0
|
1115
|
+
inline = index && (source[index] != "\n")
|
1116
|
+
comment =
|
1117
|
+
Comment.new(value: value.chomp, inline: inline, location: location)
|
1118
|
+
|
1021
1119
|
@comments << comment
|
1022
1120
|
comment
|
1023
1121
|
end
|
@@ -1092,7 +1190,7 @@ module SyntaxTree
|
|
1092
1190
|
|
1093
1191
|
# Find the beginning of the method definition, which works for single-line
|
1094
1192
|
# and normal method definitions.
|
1095
|
-
beginning =
|
1193
|
+
beginning = consume_keyword(:def)
|
1096
1194
|
|
1097
1195
|
# If there aren't any params then we need to correct the params node
|
1098
1196
|
# location information
|
@@ -1112,7 +1210,7 @@ module SyntaxTree
|
|
1112
1210
|
params = Params.new(location: location)
|
1113
1211
|
end
|
1114
1212
|
|
1115
|
-
ending =
|
1213
|
+
ending = find_keyword(:end)
|
1116
1214
|
|
1117
1215
|
if ending
|
1118
1216
|
tokens.delete(ending)
|
@@ -1150,13 +1248,13 @@ module SyntaxTree
|
|
1150
1248
|
# :call-seq:
|
1151
1249
|
# on_defined: (untyped value) -> Defined
|
1152
1250
|
def on_defined(value)
|
1153
|
-
beginning =
|
1251
|
+
beginning = consume_keyword(:defined?)
|
1154
1252
|
ending = value
|
1155
1253
|
|
1156
1254
|
range = beginning.location.end_char...value.location.start_char
|
1157
1255
|
if source[range].include?("(")
|
1158
|
-
|
1159
|
-
ending =
|
1256
|
+
consume_token(LParen)
|
1257
|
+
ending = consume_token(RParen)
|
1160
1258
|
end
|
1161
1259
|
|
1162
1260
|
Defined.new(
|
@@ -1197,8 +1295,8 @@ module SyntaxTree
|
|
1197
1295
|
params = Params.new(location: location)
|
1198
1296
|
end
|
1199
1297
|
|
1200
|
-
beginning =
|
1201
|
-
ending =
|
1298
|
+
beginning = consume_keyword(:def)
|
1299
|
+
ending = find_keyword(:end)
|
1202
1300
|
|
1203
1301
|
if ending
|
1204
1302
|
tokens.delete(ending)
|
@@ -1238,8 +1336,8 @@ module SyntaxTree
|
|
1238
1336
|
# :call-seq:
|
1239
1337
|
# on_do_block: (BlockVar block_var, BodyStmt bodystmt) -> DoBlock
|
1240
1338
|
def on_do_block(block_var, bodystmt)
|
1241
|
-
beginning =
|
1242
|
-
ending =
|
1339
|
+
beginning = consume_keyword(:do)
|
1340
|
+
ending = consume_keyword(:end)
|
1243
1341
|
location = (block_var || beginning).location
|
1244
1342
|
start_char = find_next_statement_start(location.end_char)
|
1245
1343
|
|
@@ -1261,7 +1359,7 @@ module SyntaxTree
|
|
1261
1359
|
# :call-seq:
|
1262
1360
|
# on_dot2: ((nil | untyped) left, (nil | untyped) right) -> Dot2
|
1263
1361
|
def on_dot2(left, right)
|
1264
|
-
operator =
|
1362
|
+
operator = consume_operator(:"..")
|
1265
1363
|
|
1266
1364
|
beginning = left || operator
|
1267
1365
|
ending = right || operator
|
@@ -1276,7 +1374,7 @@ module SyntaxTree
|
|
1276
1374
|
# :call-seq:
|
1277
1375
|
# on_dot3: ((nil | untyped) left, (nil | untyped) right) -> Dot3
|
1278
1376
|
def on_dot3(left, right)
|
1279
|
-
operator =
|
1377
|
+
operator = consume_operator(:"...")
|
1280
1378
|
|
1281
1379
|
beginning = left || operator
|
1282
1380
|
ending = right || operator
|
@@ -1291,10 +1389,10 @@ module SyntaxTree
|
|
1291
1389
|
# :call-seq:
|
1292
1390
|
# on_dyna_symbol: (StringContent string_content) -> DynaSymbol
|
1293
1391
|
def on_dyna_symbol(string_content)
|
1294
|
-
if find_token(SymBeg
|
1392
|
+
if (symbeg = find_token(SymBeg))
|
1295
1393
|
# A normal dynamic symbol
|
1296
|
-
symbeg
|
1297
|
-
tstring_end =
|
1394
|
+
tokens.delete(symbeg)
|
1395
|
+
tstring_end = consume_tstring_end(symbeg.location)
|
1298
1396
|
|
1299
1397
|
DynaSymbol.new(
|
1300
1398
|
quote: symbeg.value,
|
@@ -1303,8 +1401,8 @@ module SyntaxTree
|
|
1303
1401
|
)
|
1304
1402
|
else
|
1305
1403
|
# A dynamic symbol as a hash key
|
1306
|
-
tstring_beg =
|
1307
|
-
label_end =
|
1404
|
+
tstring_beg = consume_token(TStringBeg)
|
1405
|
+
label_end = consume_token(LabelEnd)
|
1308
1406
|
|
1309
1407
|
DynaSymbol.new(
|
1310
1408
|
parts: string_content.parts,
|
@@ -1317,7 +1415,7 @@ module SyntaxTree
|
|
1317
1415
|
# :call-seq:
|
1318
1416
|
# on_else: (Statements statements) -> Else
|
1319
1417
|
def on_else(statements)
|
1320
|
-
keyword =
|
1418
|
+
keyword = consume_keyword(:else)
|
1321
1419
|
|
1322
1420
|
# else can either end with an end keyword (in which case we'll want to
|
1323
1421
|
# consume that event) or it can end with an ensure keyword (in which case
|
@@ -1357,8 +1455,8 @@ module SyntaxTree
|
|
1357
1455
|
# (nil | Elsif | Else) consequent
|
1358
1456
|
# ) -> Elsif
|
1359
1457
|
def on_elsif(predicate, statements, consequent)
|
1360
|
-
beginning =
|
1361
|
-
ending = consequent ||
|
1458
|
+
beginning = consume_keyword(:elsif)
|
1459
|
+
ending = consequent || consume_keyword(:end)
|
1362
1460
|
|
1363
1461
|
start_char = find_next_statement_start(predicate.location.end_char)
|
1364
1462
|
statements.bind(
|
@@ -1478,11 +1576,11 @@ module SyntaxTree
|
|
1478
1576
|
# :call-seq:
|
1479
1577
|
# on_ensure: (Statements statements) -> Ensure
|
1480
1578
|
def on_ensure(statements)
|
1481
|
-
keyword =
|
1579
|
+
keyword = consume_keyword(:ensure)
|
1482
1580
|
|
1483
1581
|
# We don't want to consume the :@kw event, because that would break
|
1484
1582
|
# def..ensure..end chains.
|
1485
|
-
ending =
|
1583
|
+
ending = find_keyword(:end)
|
1486
1584
|
start_char = find_next_statement_start(keyword.location.end_char)
|
1487
1585
|
statements.bind(
|
1488
1586
|
start_char,
|
@@ -1504,7 +1602,7 @@ module SyntaxTree
|
|
1504
1602
|
# :call-seq:
|
1505
1603
|
# on_excessed_comma: () -> ExcessedComma
|
1506
1604
|
def on_excessed_comma(*)
|
1507
|
-
comma =
|
1605
|
+
comma = consume_token(Comma)
|
1508
1606
|
|
1509
1607
|
ExcessedComma.new(value: comma.value, location: comma.location)
|
1510
1608
|
end
|
@@ -1557,20 +1655,18 @@ module SyntaxTree
|
|
1557
1655
|
# right left parenthesis, or the left splat. We're going to use this to
|
1558
1656
|
# determine how to find the closing of the pattern, as well as determining
|
1559
1657
|
# the location of the node.
|
1560
|
-
opening =
|
1561
|
-
find_token(LBracket, consume: false) ||
|
1562
|
-
find_token(LParen, consume: false) || left
|
1658
|
+
opening = find_token(LBracket) || find_token(LParen) || left
|
1563
1659
|
|
1564
1660
|
# The closing is based on the opening, which is either the matched
|
1565
1661
|
# punctuation or the right splat.
|
1566
1662
|
closing =
|
1567
1663
|
case opening
|
1568
|
-
|
1664
|
+
when LBracket
|
1569
1665
|
tokens.delete(opening)
|
1570
|
-
|
1571
|
-
|
1666
|
+
consume_token(RBracket)
|
1667
|
+
when LParen
|
1572
1668
|
tokens.delete(opening)
|
1573
|
-
|
1669
|
+
consume_token(RParen)
|
1574
1670
|
else
|
1575
1671
|
right
|
1576
1672
|
end
|
@@ -1591,13 +1687,13 @@ module SyntaxTree
|
|
1591
1687
|
# Statements statements
|
1592
1688
|
# ) -> For
|
1593
1689
|
def on_for(index, collection, statements)
|
1594
|
-
beginning =
|
1595
|
-
in_keyword =
|
1596
|
-
ending =
|
1690
|
+
beginning = consume_keyword(:for)
|
1691
|
+
in_keyword = consume_keyword(:in)
|
1692
|
+
ending = consume_keyword(:end)
|
1597
1693
|
|
1598
1694
|
# Consume the do keyword if it exists so that it doesn't get confused for
|
1599
1695
|
# some other block
|
1600
|
-
keyword =
|
1696
|
+
keyword = find_keyword(:do)
|
1601
1697
|
if keyword &&
|
1602
1698
|
keyword.location.start_char > collection.location.end_char &&
|
1603
1699
|
keyword.location.end_char < ending.location.start_char
|
@@ -1645,8 +1741,8 @@ module SyntaxTree
|
|
1645
1741
|
# :call-seq:
|
1646
1742
|
# on_hash: ((nil | Array[AssocNew | AssocSplat]) assocs) -> HashLiteral
|
1647
1743
|
def on_hash(assocs)
|
1648
|
-
lbrace =
|
1649
|
-
rbrace =
|
1744
|
+
lbrace = consume_token(LBrace)
|
1745
|
+
rbrace = consume_token(RBrace)
|
1650
1746
|
|
1651
1747
|
HashLiteral.new(
|
1652
1748
|
lbrace: lbrace,
|
@@ -1730,8 +1826,8 @@ module SyntaxTree
|
|
1730
1826
|
if keyword_rest
|
1731
1827
|
# We're doing this to delete the token from the list so that it doesn't
|
1732
1828
|
# confuse future patterns by thinking they have an extra ** on the end.
|
1733
|
-
|
1734
|
-
elsif (token =
|
1829
|
+
consume_operator(:**)
|
1830
|
+
elsif (token = find_operator(:**))
|
1735
1831
|
tokens.delete(token)
|
1736
1832
|
|
1737
1833
|
# Create an artificial VarField if we find an extra ** on the end. This
|
@@ -1744,8 +1840,8 @@ module SyntaxTree
|
|
1744
1840
|
# If there's no constant, there may be braces, so we're going to look for
|
1745
1841
|
# those to get our bounds.
|
1746
1842
|
unless constant
|
1747
|
-
lbrace = find_token(LBrace
|
1748
|
-
rbrace = find_token(RBrace
|
1843
|
+
lbrace = find_token(LBrace)
|
1844
|
+
rbrace = find_token(RBrace)
|
1749
1845
|
|
1750
1846
|
if lbrace && rbrace
|
1751
1847
|
parts = [lbrace, *parts, rbrace]
|
@@ -1784,8 +1880,8 @@ module SyntaxTree
|
|
1784
1880
|
# (nil | Elsif | Else) consequent
|
1785
1881
|
# ) -> If
|
1786
1882
|
def on_if(predicate, statements, consequent)
|
1787
|
-
beginning =
|
1788
|
-
ending = consequent ||
|
1883
|
+
beginning = consume_keyword(:if)
|
1884
|
+
ending = consequent || consume_keyword(:end)
|
1789
1885
|
|
1790
1886
|
start_char = find_next_statement_start(predicate.location.end_char)
|
1791
1887
|
statements.bind(
|
@@ -1817,7 +1913,7 @@ module SyntaxTree
|
|
1817
1913
|
# :call-seq:
|
1818
1914
|
# on_if_mod: (untyped predicate, untyped statement) -> IfMod
|
1819
1915
|
def on_if_mod(predicate, statement)
|
1820
|
-
|
1916
|
+
consume_keyword(:if)
|
1821
1917
|
|
1822
1918
|
IfMod.new(
|
1823
1919
|
statement: statement,
|
@@ -1860,11 +1956,11 @@ module SyntaxTree
|
|
1860
1956
|
# Here we have a rightward assignment
|
1861
1957
|
return pattern unless statements
|
1862
1958
|
|
1863
|
-
beginning =
|
1864
|
-
ending = consequent ||
|
1959
|
+
beginning = consume_keyword(:in)
|
1960
|
+
ending = consequent || consume_keyword(:end)
|
1865
1961
|
|
1866
1962
|
statements_start = pattern
|
1867
|
-
if (token =
|
1963
|
+
if (token = find_keyword(:then))
|
1868
1964
|
tokens.delete(token)
|
1869
1965
|
statements_start = token
|
1870
1966
|
end
|
@@ -1878,12 +1974,16 @@ module SyntaxTree
|
|
1878
1974
|
ending.location.start_column
|
1879
1975
|
)
|
1880
1976
|
|
1881
|
-
|
1882
|
-
|
1883
|
-
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
1977
|
+
node =
|
1978
|
+
In.new(
|
1979
|
+
pattern: pattern,
|
1980
|
+
statements: statements,
|
1981
|
+
consequent: consequent,
|
1982
|
+
location: beginning.location.to(ending.location)
|
1983
|
+
)
|
1984
|
+
|
1985
|
+
PinVisitor.visit(node, tokens)
|
1986
|
+
node
|
1887
1987
|
end
|
1888
1988
|
|
1889
1989
|
# :call-seq:
|
@@ -1938,7 +2038,7 @@ module SyntaxTree
|
|
1938
2038
|
# :call-seq:
|
1939
2039
|
# on_kwrest_param: ((nil | Ident) name) -> KwRestParam
|
1940
2040
|
def on_kwrest_param(name)
|
1941
|
-
location =
|
2041
|
+
location = consume_operator(:**).location
|
1942
2042
|
location = location.to(name.location) if name
|
1943
2043
|
|
1944
2044
|
KwRestParam.new(name: name, location: location)
|
@@ -1984,7 +2084,7 @@ module SyntaxTree
|
|
1984
2084
|
# (BodyStmt | Statements) statements
|
1985
2085
|
# ) -> Lambda
|
1986
2086
|
def on_lambda(params, statements)
|
1987
|
-
beginning =
|
2087
|
+
beginning = consume_token(TLambda)
|
1988
2088
|
braces =
|
1989
2089
|
tokens.any? do |token|
|
1990
2090
|
token.is_a?(TLamBeg) &&
|
@@ -1995,7 +2095,7 @@ module SyntaxTree
|
|
1995
2095
|
# capturing lambda var until 3.2, we need to normalize all of that here.
|
1996
2096
|
params =
|
1997
2097
|
case params
|
1998
|
-
|
2098
|
+
when Paren
|
1999
2099
|
# In this case we've gotten to the <3.2 parentheses wrapping a set of
|
2000
2100
|
# parameters case. Here we need to manually scan for lambda locals.
|
2001
2101
|
range = (params.location.start_char + 1)...params.location.end_char
|
@@ -2015,23 +2115,23 @@ module SyntaxTree
|
|
2015
2115
|
location: params.location,
|
2016
2116
|
comments: params.comments
|
2017
2117
|
)
|
2018
|
-
|
2118
|
+
when Params
|
2019
2119
|
# In this case we've gotten to the <3.2 plain set of parameters. In
|
2020
2120
|
# this case there cannot be lambda locals, so we will wrap the
|
2021
2121
|
# parameters into a lambda var that has no locals.
|
2022
2122
|
LambdaVar.new(params: params, locals: [], location: params.location)
|
2023
|
-
|
2123
|
+
when LambdaVar
|
2024
2124
|
# In this case we've gotten to 3.2+ lambda var. In this case we don't
|
2025
2125
|
# need to do anything and can just the value as given.
|
2026
2126
|
params
|
2027
2127
|
end
|
2028
2128
|
|
2029
2129
|
if braces
|
2030
|
-
opening =
|
2031
|
-
closing =
|
2130
|
+
opening = consume_token(TLamBeg)
|
2131
|
+
closing = consume_token(RBrace)
|
2032
2132
|
else
|
2033
|
-
opening =
|
2034
|
-
closing =
|
2133
|
+
opening = consume_keyword(:do)
|
2134
|
+
closing = consume_keyword(:end)
|
2035
2135
|
end
|
2036
2136
|
|
2037
2137
|
start_char = find_next_statement_start(opening.location.end_char)
|
@@ -2262,7 +2362,7 @@ module SyntaxTree
|
|
2262
2362
|
# (nil | ARefField | Field | Ident | VarField) part
|
2263
2363
|
# ) -> MLHS
|
2264
2364
|
def on_mlhs_add_star(mlhs, part)
|
2265
|
-
beginning =
|
2365
|
+
beginning = consume_operator(:*)
|
2266
2366
|
ending = part || beginning
|
2267
2367
|
|
2268
2368
|
location = beginning.location.to(ending.location)
|
@@ -2285,8 +2385,8 @@ module SyntaxTree
|
|
2285
2385
|
# :call-seq:
|
2286
2386
|
# on_mlhs_paren: ((MLHS | MLHSParen) contents) -> MLHSParen
|
2287
2387
|
def on_mlhs_paren(contents)
|
2288
|
-
lparen =
|
2289
|
-
rparen =
|
2388
|
+
lparen = consume_token(LParen)
|
2389
|
+
rparen = consume_token(RParen)
|
2290
2390
|
|
2291
2391
|
comma_range = lparen.location.end_char...rparen.location.start_char
|
2292
2392
|
contents.comma = true if source[comma_range].strip.end_with?(",")
|
@@ -2303,8 +2403,8 @@ module SyntaxTree
|
|
2303
2403
|
# BodyStmt bodystmt
|
2304
2404
|
# ) -> ModuleDeclaration
|
2305
2405
|
def on_module(constant, bodystmt)
|
2306
|
-
beginning =
|
2307
|
-
ending =
|
2406
|
+
beginning = consume_keyword(:module)
|
2407
|
+
ending = consume_keyword(:end)
|
2308
2408
|
start_char = find_next_statement_start(constant.location.end_char)
|
2309
2409
|
|
2310
2410
|
bodystmt.bind(
|
@@ -2343,7 +2443,7 @@ module SyntaxTree
|
|
2343
2443
|
# :call-seq:
|
2344
2444
|
# on_mrhs_add_star: (MRHS mrhs, untyped value) -> MRHS
|
2345
2445
|
def on_mrhs_add_star(mrhs, value)
|
2346
|
-
beginning =
|
2446
|
+
beginning = consume_operator(:*)
|
2347
2447
|
ending = value || beginning
|
2348
2448
|
|
2349
2449
|
arg_star =
|
@@ -2371,7 +2471,7 @@ module SyntaxTree
|
|
2371
2471
|
# :call-seq:
|
2372
2472
|
# on_next: (Args arguments) -> Next
|
2373
2473
|
def on_next(arguments)
|
2374
|
-
keyword =
|
2474
|
+
keyword = consume_keyword(:next)
|
2375
2475
|
|
2376
2476
|
location = keyword.location
|
2377
2477
|
location = location.to(arguments.location) if arguments.parts.any?
|
@@ -2486,8 +2586,8 @@ module SyntaxTree
|
|
2486
2586
|
# :call-seq:
|
2487
2587
|
# on_paren: (untyped contents) -> Paren
|
2488
2588
|
def on_paren(contents)
|
2489
|
-
lparen =
|
2490
|
-
rparen =
|
2589
|
+
lparen = consume_token(LParen)
|
2590
|
+
rparen = consume_token(RParen)
|
2491
2591
|
|
2492
2592
|
if contents.is_a?(Params)
|
2493
2593
|
location = contents.location
|
@@ -2551,13 +2651,13 @@ module SyntaxTree
|
|
2551
2651
|
# :call-seq:
|
2552
2652
|
# on_program: (Statements statements) -> Program
|
2553
2653
|
def on_program(statements)
|
2554
|
-
last_column = source.length - line_counts
|
2654
|
+
last_column = source.length - line_counts.last.start
|
2555
2655
|
location =
|
2556
2656
|
Location.new(
|
2557
2657
|
start_line: 1,
|
2558
2658
|
start_char: 0,
|
2559
2659
|
start_column: 0,
|
2560
|
-
end_line:
|
2660
|
+
end_line: line_counts.length - 1,
|
2561
2661
|
end_char: source.length,
|
2562
2662
|
end_column: last_column
|
2563
2663
|
)
|
@@ -2692,7 +2792,7 @@ module SyntaxTree
|
|
2692
2792
|
# :call-seq:
|
2693
2793
|
# on_qsymbols_new: () -> QSymbols
|
2694
2794
|
def on_qsymbols_new
|
2695
|
-
beginning =
|
2795
|
+
beginning = consume_token(QSymbolsBeg)
|
2696
2796
|
|
2697
2797
|
QSymbols.new(
|
2698
2798
|
beginning: beginning,
|
@@ -2733,7 +2833,7 @@ module SyntaxTree
|
|
2733
2833
|
# :call-seq:
|
2734
2834
|
# on_qwords_new: () -> QWords
|
2735
2835
|
def on_qwords_new
|
2736
|
-
beginning =
|
2836
|
+
beginning = consume_token(QWordsBeg)
|
2737
2837
|
|
2738
2838
|
QWords.new(
|
2739
2839
|
beginning: beginning,
|
@@ -2798,7 +2898,7 @@ module SyntaxTree
|
|
2798
2898
|
# :call-seq:
|
2799
2899
|
# on_redo: () -> Redo
|
2800
2900
|
def on_redo
|
2801
|
-
keyword =
|
2901
|
+
keyword = consume_keyword(:redo)
|
2802
2902
|
|
2803
2903
|
Redo.new(value: keyword.value, location: keyword.location)
|
2804
2904
|
end
|
@@ -2874,7 +2974,7 @@ module SyntaxTree
|
|
2874
2974
|
# :call-seq:
|
2875
2975
|
# on_regexp_new: () -> RegexpContent
|
2876
2976
|
def on_regexp_new
|
2877
|
-
regexp_beg =
|
2977
|
+
regexp_beg = consume_token(RegexpBeg)
|
2878
2978
|
|
2879
2979
|
RegexpContent.new(
|
2880
2980
|
beginning: regexp_beg.value,
|
@@ -2891,7 +2991,7 @@ module SyntaxTree
|
|
2891
2991
|
# (nil | Rescue) consequent
|
2892
2992
|
# ) -> Rescue
|
2893
2993
|
def on_rescue(exceptions, variable, statements, consequent)
|
2894
|
-
keyword =
|
2994
|
+
keyword = consume_keyword(:rescue)
|
2895
2995
|
exceptions = exceptions[0] if exceptions.is_a?(Array)
|
2896
2996
|
|
2897
2997
|
last_node = variable || exceptions || keyword
|
@@ -2943,7 +3043,7 @@ module SyntaxTree
|
|
2943
3043
|
# :call-seq:
|
2944
3044
|
# on_rescue_mod: (untyped statement, untyped value) -> RescueMod
|
2945
3045
|
def on_rescue_mod(statement, value)
|
2946
|
-
|
3046
|
+
consume_keyword(:rescue)
|
2947
3047
|
|
2948
3048
|
RescueMod.new(
|
2949
3049
|
statement: statement,
|
@@ -2955,7 +3055,7 @@ module SyntaxTree
|
|
2955
3055
|
# :call-seq:
|
2956
3056
|
# on_rest_param: ((nil | Ident) name) -> RestParam
|
2957
3057
|
def on_rest_param(name)
|
2958
|
-
location =
|
3058
|
+
location = consume_operator(:*).location
|
2959
3059
|
location = location.to(name.location) if name
|
2960
3060
|
|
2961
3061
|
RestParam.new(name: name, location: location)
|
@@ -2964,7 +3064,7 @@ module SyntaxTree
|
|
2964
3064
|
# :call-seq:
|
2965
3065
|
# on_retry: () -> Retry
|
2966
3066
|
def on_retry
|
2967
|
-
keyword =
|
3067
|
+
keyword = consume_keyword(:retry)
|
2968
3068
|
|
2969
3069
|
Retry.new(value: keyword.value, location: keyword.location)
|
2970
3070
|
end
|
@@ -2972,7 +3072,7 @@ module SyntaxTree
|
|
2972
3072
|
# :call-seq:
|
2973
3073
|
# on_return: (Args arguments) -> Return
|
2974
3074
|
def on_return(arguments)
|
2975
|
-
keyword =
|
3075
|
+
keyword = consume_keyword(:return)
|
2976
3076
|
|
2977
3077
|
Return.new(
|
2978
3078
|
arguments: arguments,
|
@@ -2983,7 +3083,7 @@ module SyntaxTree
|
|
2983
3083
|
# :call-seq:
|
2984
3084
|
# on_return0: () -> Return0
|
2985
3085
|
def on_return0
|
2986
|
-
keyword =
|
3086
|
+
keyword = consume_keyword(:return)
|
2987
3087
|
|
2988
3088
|
Return0.new(value: keyword.value, location: keyword.location)
|
2989
3089
|
end
|
@@ -3010,8 +3110,8 @@ module SyntaxTree
|
|
3010
3110
|
# :call-seq:
|
3011
3111
|
# on_sclass: (untyped target, BodyStmt bodystmt) -> SClass
|
3012
3112
|
def on_sclass(target, bodystmt)
|
3013
|
-
beginning =
|
3014
|
-
ending =
|
3113
|
+
beginning = consume_keyword(:class)
|
3114
|
+
ending = consume_keyword(:end)
|
3015
3115
|
start_char = find_next_statement_start(target.location.end_char)
|
3016
3116
|
|
3017
3117
|
bodystmt.bind(
|
@@ -3109,7 +3209,7 @@ module SyntaxTree
|
|
3109
3209
|
# :call-seq:
|
3110
3210
|
# on_string_dvar: ((Backref | VarRef) variable) -> StringDVar
|
3111
3211
|
def on_string_dvar(variable)
|
3112
|
-
embvar =
|
3212
|
+
embvar = consume_token(EmbVar)
|
3113
3213
|
|
3114
3214
|
StringDVar.new(
|
3115
3215
|
variable: variable,
|
@@ -3120,8 +3220,8 @@ module SyntaxTree
|
|
3120
3220
|
# :call-seq:
|
3121
3221
|
# on_string_embexpr: (Statements statements) -> StringEmbExpr
|
3122
3222
|
def on_string_embexpr(statements)
|
3123
|
-
embexpr_beg =
|
3124
|
-
embexpr_end =
|
3223
|
+
embexpr_beg = consume_token(EmbExprBeg)
|
3224
|
+
embexpr_end = consume_token(EmbExprEnd)
|
3125
3225
|
|
3126
3226
|
statements.bind(
|
3127
3227
|
embexpr_beg.location.end_char,
|
@@ -3162,8 +3262,8 @@ module SyntaxTree
|
|
3162
3262
|
location: heredoc.location
|
3163
3263
|
)
|
3164
3264
|
else
|
3165
|
-
tstring_beg =
|
3166
|
-
tstring_end =
|
3265
|
+
tstring_beg = consume_token(TStringBeg)
|
3266
|
+
tstring_end = consume_tstring_end(tstring_beg.location)
|
3167
3267
|
|
3168
3268
|
location =
|
3169
3269
|
Location.new(
|
@@ -3189,7 +3289,7 @@ module SyntaxTree
|
|
3189
3289
|
# :call-seq:
|
3190
3290
|
# on_super: ((ArgParen | Args) arguments) -> Super
|
3191
3291
|
def on_super(arguments)
|
3192
|
-
keyword =
|
3292
|
+
keyword = consume_keyword(:super)
|
3193
3293
|
|
3194
3294
|
Super.new(
|
3195
3295
|
arguments: arguments,
|
@@ -3236,7 +3336,7 @@ module SyntaxTree
|
|
3236
3336
|
# ) -> SymbolLiteral
|
3237
3337
|
def on_symbol_literal(value)
|
3238
3338
|
if value.is_a?(SymbolContent)
|
3239
|
-
symbeg =
|
3339
|
+
symbeg = consume_token(SymBeg)
|
3240
3340
|
|
3241
3341
|
SymbolLiteral.new(
|
3242
3342
|
value: value.value,
|
@@ -3280,7 +3380,7 @@ module SyntaxTree
|
|
3280
3380
|
# :call-seq:
|
3281
3381
|
# on_symbols_new: () -> Symbols
|
3282
3382
|
def on_symbols_new
|
3283
|
-
beginning =
|
3383
|
+
beginning = consume_token(SymbolsBeg)
|
3284
3384
|
|
3285
3385
|
Symbols.new(
|
3286
3386
|
beginning: beginning,
|
@@ -3410,13 +3510,13 @@ module SyntaxTree
|
|
3410
3510
|
# We have somewhat special handling of the not operator since if it has
|
3411
3511
|
# parentheses they don't get reported as a paren node for some reason.
|
3412
3512
|
|
3413
|
-
beginning =
|
3513
|
+
beginning = consume_keyword(:not)
|
3414
3514
|
ending = statement || beginning
|
3415
3515
|
parentheses = source[beginning.location.end_char] == "("
|
3416
3516
|
|
3417
3517
|
if parentheses
|
3418
|
-
|
3419
|
-
ending =
|
3518
|
+
consume_token(LParen)
|
3519
|
+
ending = consume_token(RParen)
|
3420
3520
|
end
|
3421
3521
|
|
3422
3522
|
Not.new(
|
@@ -3449,7 +3549,7 @@ module SyntaxTree
|
|
3449
3549
|
# :call-seq:
|
3450
3550
|
# on_undef: (Array[DynaSymbol | SymbolLiteral] symbols) -> Undef
|
3451
3551
|
def on_undef(symbols)
|
3452
|
-
keyword =
|
3552
|
+
keyword = consume_keyword(:undef)
|
3453
3553
|
|
3454
3554
|
Undef.new(
|
3455
3555
|
symbols: symbols,
|
@@ -3464,8 +3564,8 @@ module SyntaxTree
|
|
3464
3564
|
# ((nil | Elsif | Else) consequent)
|
3465
3565
|
# ) -> Unless
|
3466
3566
|
def on_unless(predicate, statements, consequent)
|
3467
|
-
beginning =
|
3468
|
-
ending = consequent ||
|
3567
|
+
beginning = consume_keyword(:unless)
|
3568
|
+
ending = consequent || consume_keyword(:end)
|
3469
3569
|
|
3470
3570
|
start_char = find_next_statement_start(predicate.location.end_char)
|
3471
3571
|
statements.bind(
|
@@ -3486,7 +3586,7 @@ module SyntaxTree
|
|
3486
3586
|
# :call-seq:
|
3487
3587
|
# on_unless_mod: (untyped predicate, untyped statement) -> UnlessMod
|
3488
3588
|
def on_unless_mod(predicate, statement)
|
3489
|
-
|
3589
|
+
consume_keyword(:unless)
|
3490
3590
|
|
3491
3591
|
UnlessMod.new(
|
3492
3592
|
statement: statement,
|
@@ -3498,12 +3598,12 @@ module SyntaxTree
|
|
3498
3598
|
# :call-seq:
|
3499
3599
|
# on_until: (untyped predicate, Statements statements) -> Until
|
3500
3600
|
def on_until(predicate, statements)
|
3501
|
-
beginning =
|
3502
|
-
ending =
|
3601
|
+
beginning = consume_keyword(:until)
|
3602
|
+
ending = consume_keyword(:end)
|
3503
3603
|
|
3504
3604
|
# Consume the do keyword if it exists so that it doesn't get confused for
|
3505
3605
|
# some other block
|
3506
|
-
keyword =
|
3606
|
+
keyword = find_keyword(:do)
|
3507
3607
|
if keyword && keyword.location.start_char > predicate.location.end_char &&
|
3508
3608
|
keyword.location.end_char < ending.location.start_char
|
3509
3609
|
tokens.delete(keyword)
|
@@ -3528,7 +3628,7 @@ module SyntaxTree
|
|
3528
3628
|
# :call-seq:
|
3529
3629
|
# on_until_mod: (untyped predicate, untyped statement) -> UntilMod
|
3530
3630
|
def on_until_mod(predicate, statement)
|
3531
|
-
|
3631
|
+
consume_keyword(:until)
|
3532
3632
|
|
3533
3633
|
UntilMod.new(
|
3534
3634
|
statement: statement,
|
@@ -3540,7 +3640,7 @@ module SyntaxTree
|
|
3540
3640
|
# :call-seq:
|
3541
3641
|
# on_var_alias: (GVar left, (Backref | GVar) right) -> VarAlias
|
3542
3642
|
def on_var_alias(left, right)
|
3543
|
-
keyword =
|
3643
|
+
keyword = consume_keyword(:alias)
|
3544
3644
|
|
3545
3645
|
VarAlias.new(
|
3546
3646
|
left: left,
|
@@ -3569,17 +3669,7 @@ module SyntaxTree
|
|
3569
3669
|
# :call-seq:
|
3570
3670
|
# on_var_ref: ((Const | CVar | GVar | Ident | IVar | Kw) value) -> VarRef
|
3571
3671
|
def on_var_ref(value)
|
3572
|
-
|
3573
|
-
|
3574
|
-
if pin && pin.location.start_char == value.location.start_char - 1
|
3575
|
-
tokens.delete(pin)
|
3576
|
-
PinnedVarRef.new(
|
3577
|
-
value: value,
|
3578
|
-
location: pin.location.to(value.location)
|
3579
|
-
)
|
3580
|
-
else
|
3581
|
-
VarRef.new(value: value, location: value.location)
|
3582
|
-
end
|
3672
|
+
VarRef.new(value: value, location: value.location)
|
3583
3673
|
end
|
3584
3674
|
|
3585
3675
|
# :call-seq:
|
@@ -3604,11 +3694,11 @@ module SyntaxTree
|
|
3604
3694
|
# (nil | Else | When) consequent
|
3605
3695
|
# ) -> When
|
3606
3696
|
def on_when(arguments, statements, consequent)
|
3607
|
-
beginning =
|
3608
|
-
ending = consequent ||
|
3697
|
+
beginning = consume_keyword(:when)
|
3698
|
+
ending = consequent || consume_keyword(:end)
|
3609
3699
|
|
3610
3700
|
statements_start = arguments
|
3611
|
-
if (token =
|
3701
|
+
if (token = find_keyword(:then))
|
3612
3702
|
tokens.delete(token)
|
3613
3703
|
statements_start = token
|
3614
3704
|
end
|
@@ -3634,12 +3724,12 @@ module SyntaxTree
|
|
3634
3724
|
# :call-seq:
|
3635
3725
|
# on_while: (untyped predicate, Statements statements) -> While
|
3636
3726
|
def on_while(predicate, statements)
|
3637
|
-
beginning =
|
3638
|
-
ending =
|
3727
|
+
beginning = consume_keyword(:while)
|
3728
|
+
ending = consume_keyword(:end)
|
3639
3729
|
|
3640
3730
|
# Consume the do keyword if it exists so that it doesn't get confused for
|
3641
3731
|
# some other block
|
3642
|
-
keyword =
|
3732
|
+
keyword = find_keyword(:do)
|
3643
3733
|
if keyword && keyword.location.start_char > predicate.location.end_char &&
|
3644
3734
|
keyword.location.end_char < ending.location.start_char
|
3645
3735
|
tokens.delete(keyword)
|
@@ -3664,7 +3754,7 @@ module SyntaxTree
|
|
3664
3754
|
# :call-seq:
|
3665
3755
|
# on_while_mod: (untyped predicate, untyped statement) -> WhileMod
|
3666
3756
|
def on_while_mod(predicate, statement)
|
3667
|
-
|
3757
|
+
consume_keyword(:while)
|
3668
3758
|
|
3669
3759
|
WhileMod.new(
|
3670
3760
|
statement: statement,
|
@@ -3727,7 +3817,7 @@ module SyntaxTree
|
|
3727
3817
|
# :call-seq:
|
3728
3818
|
# on_words_new: () -> Words
|
3729
3819
|
def on_words_new
|
3730
|
-
beginning =
|
3820
|
+
beginning = consume_token(WordsBeg)
|
3731
3821
|
|
3732
3822
|
Words.new(
|
3733
3823
|
beginning: beginning,
|
@@ -3761,7 +3851,7 @@ module SyntaxTree
|
|
3761
3851
|
if heredoc && heredoc.beginning.value.include?("`")
|
3762
3852
|
heredoc.location
|
3763
3853
|
else
|
3764
|
-
|
3854
|
+
consume_token(Backtick).location
|
3765
3855
|
end
|
3766
3856
|
|
3767
3857
|
XString.new(parts: [], location: location)
|
@@ -3781,7 +3871,7 @@ module SyntaxTree
|
|
3781
3871
|
location: heredoc.location
|
3782
3872
|
)
|
3783
3873
|
else
|
3784
|
-
ending =
|
3874
|
+
ending = consume_tstring_end(xstring.location)
|
3785
3875
|
|
3786
3876
|
XStringLiteral.new(
|
3787
3877
|
parts: xstring.parts,
|
@@ -3793,7 +3883,7 @@ module SyntaxTree
|
|
3793
3883
|
# :call-seq:
|
3794
3884
|
# on_yield: ((Args | Paren) arguments) -> Yield
|
3795
3885
|
def on_yield(arguments)
|
3796
|
-
keyword =
|
3886
|
+
keyword = consume_keyword(:yield)
|
3797
3887
|
|
3798
3888
|
Yield.new(
|
3799
3889
|
arguments: arguments,
|
@@ -3804,7 +3894,7 @@ module SyntaxTree
|
|
3804
3894
|
# :call-seq:
|
3805
3895
|
# on_yield0: () -> Yield0
|
3806
3896
|
def on_yield0
|
3807
|
-
keyword =
|
3897
|
+
keyword = consume_keyword(:yield)
|
3808
3898
|
|
3809
3899
|
Yield0.new(value: keyword.value, location: keyword.location)
|
3810
3900
|
end
|
@@ -3812,7 +3902,7 @@ module SyntaxTree
|
|
3812
3902
|
# :call-seq:
|
3813
3903
|
# on_zsuper: () -> ZSuper
|
3814
3904
|
def on_zsuper
|
3815
|
-
keyword =
|
3905
|
+
keyword = consume_keyword(:super)
|
3816
3906
|
|
3817
3907
|
ZSuper.new(value: keyword.value, location: keyword.location)
|
3818
3908
|
end
|