syntax_tree 3.6.3 → 4.0.0
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
- 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
|