prism 1.7.0 → 1.8.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/CHANGELOG.md +17 -1
- data/Makefile +7 -1
- data/docs/releasing.md +2 -4
- data/docs/ruby_api.md +1 -0
- data/ext/prism/extension.h +1 -1
- data/include/prism/version.h +2 -2
- data/lib/prism/compiler.rb +152 -152
- data/lib/prism/lex_compat.rb +17 -75
- data/lib/prism/lex_ripper.rb +64 -0
- data/lib/prism/node.rb +1104 -1
- data/lib/prism/serialize.rb +1 -1
- data/lib/prism/translation/parser_current.rb +1 -1
- data/lib/prism/translation/parser_versions.rb +36 -0
- data/lib/prism/translation/ripper/lexer.rb +46 -0
- data/lib/prism/translation/ripper.rb +25 -2
- data/lib/prism/translation/ruby_parser.rb +1 -1
- data/lib/prism/translation.rb +5 -5
- data/lib/prism/visitor.rb +152 -152
- data/lib/prism.rb +1 -1
- data/prism.gemspec +5 -11
- data/rbi/prism/translation/parser_versions.rbi +23 -0
- data/sig/prism/node.rbs +1 -0
- data/src/prism.c +48 -27
- metadata +5 -11
- data/lib/prism/translation/parser33.rb +0 -13
- data/lib/prism/translation/parser34.rb +0 -13
- data/lib/prism/translation/parser35.rb +0 -8
- data/lib/prism/translation/parser40.rb +0 -13
- data/lib/prism/translation/parser41.rb +0 -13
- data/rbi/prism/translation/parser33.rbi +0 -6
- data/rbi/prism/translation/parser34.rbi +0 -6
- data/rbi/prism/translation/parser35.rbi +0 -4
- data/rbi/prism/translation/parser40.rbi +0 -6
- data/rbi/prism/translation/parser41.rbi +0 -6
data/lib/prism/lex_compat.rb
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
# :markup: markdown
|
|
3
3
|
|
|
4
4
|
require "delegate"
|
|
5
|
-
require "ripper"
|
|
6
5
|
|
|
7
6
|
module Prism
|
|
8
7
|
# This class is responsible for lexing the source using prism and then
|
|
@@ -249,8 +248,8 @@ module Prism
|
|
|
249
248
|
class IdentToken < Token
|
|
250
249
|
def ==(other) # :nodoc:
|
|
251
250
|
(self[0...-1] == other[0...-1]) && (
|
|
252
|
-
(other[3] == Ripper::EXPR_LABEL | Ripper::EXPR_END) ||
|
|
253
|
-
(other[3] & Ripper::
|
|
251
|
+
(other[3] == Translation::Ripper::EXPR_LABEL | Translation::Ripper::EXPR_END) ||
|
|
252
|
+
(other[3] & (Translation::Ripper::EXPR_ARG | Translation::Ripper::EXPR_CMDARG) != 0)
|
|
254
253
|
)
|
|
255
254
|
end
|
|
256
255
|
end
|
|
@@ -261,8 +260,8 @@ module Prism
|
|
|
261
260
|
def ==(other) # :nodoc:
|
|
262
261
|
return false unless self[0...-1] == other[0...-1]
|
|
263
262
|
|
|
264
|
-
if self[3] == Ripper::EXPR_ARG | Ripper::EXPR_LABELED
|
|
265
|
-
other[3] & Ripper::EXPR_ARG | Ripper::EXPR_LABELED != 0
|
|
263
|
+
if self[3] == Translation::Ripper::EXPR_ARG | Translation::Ripper::EXPR_LABELED
|
|
264
|
+
other[3] & Translation::Ripper::EXPR_ARG | Translation::Ripper::EXPR_LABELED != 0
|
|
266
265
|
else
|
|
267
266
|
self[3] == other[3]
|
|
268
267
|
end
|
|
@@ -280,8 +279,8 @@ module Prism
|
|
|
280
279
|
class ParamToken < Token
|
|
281
280
|
def ==(other) # :nodoc:
|
|
282
281
|
(self[0...-1] == other[0...-1]) && (
|
|
283
|
-
(other[3] == Ripper::EXPR_END) ||
|
|
284
|
-
(other[3] == Ripper::EXPR_END | Ripper::EXPR_LABEL)
|
|
282
|
+
(other[3] == Translation::Ripper::EXPR_END) ||
|
|
283
|
+
(other[3] == Translation::Ripper::EXPR_END | Translation::Ripper::EXPR_LABEL)
|
|
285
284
|
)
|
|
286
285
|
end
|
|
287
286
|
end
|
|
@@ -615,6 +614,11 @@ module Prism
|
|
|
615
614
|
|
|
616
615
|
private_constant :Heredoc
|
|
617
616
|
|
|
617
|
+
# In previous versions of Ruby, Ripper wouldn't flush the bom before the
|
|
618
|
+
# first token, so we had to have a hack in place to account for that.
|
|
619
|
+
BOM_FLUSHED = RUBY_VERSION >= "3.3.0"
|
|
620
|
+
private_constant :BOM_FLUSHED
|
|
621
|
+
|
|
618
622
|
attr_reader :source, :options
|
|
619
623
|
|
|
620
624
|
def initialize(source, **options)
|
|
@@ -630,13 +634,9 @@ module Prism
|
|
|
630
634
|
|
|
631
635
|
result = Prism.lex(source, **options)
|
|
632
636
|
result_value = result.value
|
|
633
|
-
previous_state = nil #:
|
|
637
|
+
previous_state = nil #: State?
|
|
634
638
|
last_heredoc_end = nil #: Integer?
|
|
635
639
|
|
|
636
|
-
# In previous versions of Ruby, Ripper wouldn't flush the bom before the
|
|
637
|
-
# first token, so we had to have a hack in place to account for that. This
|
|
638
|
-
# checks for that behavior.
|
|
639
|
-
bom_flushed = Ripper.lex("\xEF\xBB\xBF# test")[0][0][1] == 0
|
|
640
640
|
bom = source.byteslice(0..2) == "\xEF\xBB\xBF"
|
|
641
641
|
|
|
642
642
|
result_value.each_with_index do |(token, lex_state), index|
|
|
@@ -651,7 +651,7 @@ module Prism
|
|
|
651
651
|
if bom && lineno == 1
|
|
652
652
|
column -= 3
|
|
653
653
|
|
|
654
|
-
if index == 0 && column == 0 && !
|
|
654
|
+
if index == 0 && column == 0 && !BOM_FLUSHED
|
|
655
655
|
flushed =
|
|
656
656
|
case token.type
|
|
657
657
|
when :BACK_REFERENCE, :INSTANCE_VARIABLE, :CLASS_VARIABLE,
|
|
@@ -675,7 +675,7 @@ module Prism
|
|
|
675
675
|
|
|
676
676
|
event = RIPPER.fetch(token.type)
|
|
677
677
|
value = token.value
|
|
678
|
-
lex_state = Ripper::Lexer::State.new(lex_state)
|
|
678
|
+
lex_state = Translation::Ripper::Lexer::State.new(lex_state)
|
|
679
679
|
|
|
680
680
|
token =
|
|
681
681
|
case event
|
|
@@ -689,7 +689,7 @@ module Prism
|
|
|
689
689
|
last_heredoc_end = token.location.end_offset
|
|
690
690
|
IgnoreStateToken.new([[lineno, column], event, value, lex_state])
|
|
691
691
|
when :on_ident
|
|
692
|
-
if lex_state == Ripper::EXPR_END
|
|
692
|
+
if lex_state == Translation::Ripper::EXPR_END
|
|
693
693
|
# If we have an identifier that follows a method name like:
|
|
694
694
|
#
|
|
695
695
|
# def foo bar
|
|
@@ -699,7 +699,7 @@ module Prism
|
|
|
699
699
|
# yet. We do this more accurately, so we need to allow comparing
|
|
700
700
|
# against both END and END|LABEL.
|
|
701
701
|
ParamToken.new([[lineno, column], event, value, lex_state])
|
|
702
|
-
elsif lex_state == Ripper::EXPR_END | Ripper::EXPR_LABEL
|
|
702
|
+
elsif lex_state == Translation::Ripper::EXPR_END | Translation::Ripper::EXPR_LABEL
|
|
703
703
|
# In the event that we're comparing identifiers, we're going to
|
|
704
704
|
# allow a little divergence. Ripper doesn't account for local
|
|
705
705
|
# variables introduced through named captures in regexes, and we
|
|
@@ -739,7 +739,7 @@ module Prism
|
|
|
739
739
|
counter += { on_embexpr_beg: -1, on_embexpr_end: 1 }[current_event] || 0
|
|
740
740
|
end
|
|
741
741
|
|
|
742
|
-
Ripper::Lexer::State.new(result_value[current_index][1])
|
|
742
|
+
Translation::Ripper::Lexer::State.new(result_value[current_index][1])
|
|
743
743
|
else
|
|
744
744
|
previous_state
|
|
745
745
|
end
|
|
@@ -867,62 +867,4 @@ module Prism
|
|
|
867
867
|
end
|
|
868
868
|
|
|
869
869
|
private_constant :LexCompat
|
|
870
|
-
|
|
871
|
-
# This is a class that wraps the Ripper lexer to produce almost exactly the
|
|
872
|
-
# same tokens.
|
|
873
|
-
class LexRipper # :nodoc:
|
|
874
|
-
attr_reader :source
|
|
875
|
-
|
|
876
|
-
def initialize(source)
|
|
877
|
-
@source = source
|
|
878
|
-
end
|
|
879
|
-
|
|
880
|
-
def result
|
|
881
|
-
previous = [] #: [[Integer, Integer], Symbol, String, untyped] | []
|
|
882
|
-
results = [] #: Array[[[Integer, Integer], Symbol, String, untyped]]
|
|
883
|
-
|
|
884
|
-
lex(source).each do |token|
|
|
885
|
-
case token[1]
|
|
886
|
-
when :on_sp
|
|
887
|
-
# skip
|
|
888
|
-
when :on_tstring_content
|
|
889
|
-
if previous[1] == :on_tstring_content && (token[2].start_with?("\#$") || token[2].start_with?("\#@"))
|
|
890
|
-
previous[2] << token[2]
|
|
891
|
-
else
|
|
892
|
-
results << token
|
|
893
|
-
previous = token
|
|
894
|
-
end
|
|
895
|
-
when :on_words_sep
|
|
896
|
-
if previous[1] == :on_words_sep
|
|
897
|
-
previous[2] << token[2]
|
|
898
|
-
else
|
|
899
|
-
results << token
|
|
900
|
-
previous = token
|
|
901
|
-
end
|
|
902
|
-
else
|
|
903
|
-
results << token
|
|
904
|
-
previous = token
|
|
905
|
-
end
|
|
906
|
-
end
|
|
907
|
-
|
|
908
|
-
results
|
|
909
|
-
end
|
|
910
|
-
|
|
911
|
-
private
|
|
912
|
-
|
|
913
|
-
if Ripper.method(:lex).parameters.assoc(:keyrest)
|
|
914
|
-
def lex(source)
|
|
915
|
-
Ripper.lex(source, raise_errors: true)
|
|
916
|
-
end
|
|
917
|
-
else
|
|
918
|
-
def lex(source)
|
|
919
|
-
ripper = Ripper::Lexer.new(source)
|
|
920
|
-
ripper.lex.tap do |result|
|
|
921
|
-
raise SyntaxError, ripper.errors.map(&:message).join(' ;') if ripper.errors.any?
|
|
922
|
-
end
|
|
923
|
-
end
|
|
924
|
-
end
|
|
925
|
-
end
|
|
926
|
-
|
|
927
|
-
private_constant :LexRipper
|
|
928
870
|
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# :markup: markdown
|
|
3
|
+
|
|
4
|
+
require "ripper"
|
|
5
|
+
|
|
6
|
+
module Prism
|
|
7
|
+
# This is a class that wraps the Ripper lexer to produce almost exactly the
|
|
8
|
+
# same tokens.
|
|
9
|
+
class LexRipper # :nodoc:
|
|
10
|
+
attr_reader :source
|
|
11
|
+
|
|
12
|
+
def initialize(source)
|
|
13
|
+
@source = source
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def result
|
|
17
|
+
previous = [] #: [[Integer, Integer], Symbol, String, untyped] | []
|
|
18
|
+
results = [] #: Array[[[Integer, Integer], Symbol, String, untyped]]
|
|
19
|
+
|
|
20
|
+
lex(source).each do |token|
|
|
21
|
+
case token[1]
|
|
22
|
+
when :on_sp
|
|
23
|
+
# skip
|
|
24
|
+
when :on_tstring_content
|
|
25
|
+
if previous[1] == :on_tstring_content && (token[2].start_with?("\#$") || token[2].start_with?("\#@"))
|
|
26
|
+
previous[2] << token[2]
|
|
27
|
+
else
|
|
28
|
+
results << token
|
|
29
|
+
previous = token
|
|
30
|
+
end
|
|
31
|
+
when :on_words_sep
|
|
32
|
+
if previous[1] == :on_words_sep
|
|
33
|
+
previous[2] << token[2]
|
|
34
|
+
else
|
|
35
|
+
results << token
|
|
36
|
+
previous = token
|
|
37
|
+
end
|
|
38
|
+
else
|
|
39
|
+
results << token
|
|
40
|
+
previous = token
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
results
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
if Ripper.method(:lex).parameters.assoc(:keyrest)
|
|
50
|
+
def lex(source)
|
|
51
|
+
Ripper.lex(source, raise_errors: true)
|
|
52
|
+
end
|
|
53
|
+
else
|
|
54
|
+
def lex(source)
|
|
55
|
+
ripper = Ripper::Lexer.new(source)
|
|
56
|
+
ripper.lex.tap do |result|
|
|
57
|
+
raise SyntaxError, ripper.errors.map(&:message).join(' ;') if ripper.errors.any?
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private_constant :LexRipper
|
|
64
|
+
end
|