prism 1.7.0 → 1.9.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -1
  3. data/Makefile +7 -1
  4. data/config.yml +4 -4
  5. data/docs/releasing.md +2 -4
  6. data/docs/ripper_translation.md +8 -17
  7. data/docs/ruby_api.md +1 -0
  8. data/ext/prism/extension.h +1 -1
  9. data/include/prism/ast.h +4 -4
  10. data/include/prism/version.h +2 -2
  11. data/lib/prism/compiler.rb +152 -152
  12. data/lib/prism/lex_compat.rb +133 -150
  13. data/lib/prism/node.rb +1131 -20
  14. data/lib/prism/parse_result.rb +9 -0
  15. data/lib/prism/serialize.rb +1 -1
  16. data/lib/prism/translation/parser_current.rb +1 -1
  17. data/lib/prism/translation/parser_versions.rb +36 -0
  18. data/lib/prism/translation/ripper/filter.rb +53 -0
  19. data/lib/prism/translation/ripper/lexer.rb +135 -0
  20. data/lib/prism/translation/ripper.rb +84 -38
  21. data/lib/prism/translation/ruby_parser.rb +1 -1
  22. data/lib/prism/translation.rb +5 -5
  23. data/lib/prism/visitor.rb +152 -152
  24. data/lib/prism.rb +1 -14
  25. data/prism.gemspec +5 -11
  26. data/rbi/prism/node.rbi +3 -0
  27. data/rbi/prism/translation/parser_versions.rbi +23 -0
  28. data/rbi/prism.rbi +0 -3
  29. data/sig/prism/node.rbs +4 -0
  30. data/sig/prism/parse_result.rbs +1 -0
  31. data/sig/prism.rbs +54 -40
  32. data/src/prism.c +48 -27
  33. metadata +5 -11
  34. data/lib/prism/translation/parser33.rb +0 -13
  35. data/lib/prism/translation/parser34.rb +0 -13
  36. data/lib/prism/translation/parser35.rb +0 -8
  37. data/lib/prism/translation/parser40.rb +0 -13
  38. data/lib/prism/translation/parser41.rb +0 -13
  39. data/rbi/prism/translation/parser33.rbi +0 -6
  40. data/rbi/prism/translation/parser34.rbi +0 -6
  41. data/rbi/prism/translation/parser35.rbi +0 -4
  42. data/rbi/prism/translation/parser40.rbi +0 -6
  43. data/rbi/prism/translation/parser41.rbi +0 -6
@@ -76,6 +76,15 @@ module Prism
76
76
  source.byteslice(byte_offset, length) or raise
77
77
  end
78
78
 
79
+ # Converts the line number and column in bytes to a byte offset.
80
+ def byte_offset(line, column)
81
+ normal = line - @start_line
82
+ raise IndexError if normal < 0
83
+ offsets.fetch(normal) + column
84
+ rescue IndexError
85
+ raise ArgumentError, "line #{line} is out of range"
86
+ end
87
+
79
88
  # Binary search through the offsets to find the line number for the given
80
89
  # byte offset.
81
90
  def line(byte_offset)
@@ -21,7 +21,7 @@ module Prism
21
21
 
22
22
  # The minor version of prism that we are expecting to find in the serialized
23
23
  # strings.
24
- MINOR_VERSION = 7
24
+ MINOR_VERSION = 9
25
25
 
26
26
  # The patch version of prism that we are expecting to find in the serialized
27
27
  # strings.
@@ -16,7 +16,7 @@ module Prism
16
16
  ParserCurrent = Parser41
17
17
  else
18
18
  # Keep this in sync with released Ruby.
19
- parser = Parser34
19
+ parser = Parser40
20
20
  major, minor, _patch = Gem::Version.new(RUBY_VERSION).segments
21
21
  warn "warning: `Prism::Translation::Current` is loading #{parser.name}, " \
22
22
  "but you are running #{major}.#{minor}."
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+ # :markup: markdown
3
+
4
+ module Prism
5
+ module Translation
6
+ # This class is the entry-point for Ruby 3.3 of `Prism::Translation::Parser`.
7
+ class Parser33 < Parser
8
+ def version # :nodoc:
9
+ 33
10
+ end
11
+ end
12
+
13
+ # This class is the entry-point for Ruby 3.4 of `Prism::Translation::Parser`.
14
+ class Parser34 < Parser
15
+ def version # :nodoc:
16
+ 34
17
+ end
18
+ end
19
+
20
+ # This class is the entry-point for Ruby 4.0 of `Prism::Translation::Parser`.
21
+ class Parser40 < Parser
22
+ def version # :nodoc:
23
+ 40
24
+ end
25
+ end
26
+
27
+ Parser35 = Parser40 # :nodoc:
28
+
29
+ # This class is the entry-point for Ruby 4.1 of `Prism::Translation::Parser`.
30
+ class Parser41 < Parser
31
+ def version # :nodoc:
32
+ 41
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Prism
4
+ module Translation
5
+ class Ripper
6
+ class Filter # :nodoc:
7
+ # :stopdoc:
8
+ def initialize(src, filename = '-', lineno = 1)
9
+ @__lexer = Lexer.new(src, filename, lineno)
10
+ @__line = nil
11
+ @__col = nil
12
+ @__state = nil
13
+ end
14
+
15
+ def filename
16
+ @__lexer.filename
17
+ end
18
+
19
+ def lineno
20
+ @__line
21
+ end
22
+
23
+ def column
24
+ @__col
25
+ end
26
+
27
+ def state
28
+ @__state
29
+ end
30
+
31
+ def parse(init = nil)
32
+ data = init
33
+ @__lexer.lex.each do |pos, event, tok, state|
34
+ @__line, @__col = *pos
35
+ @__state = state
36
+ data = if respond_to?(event, true)
37
+ then __send__(event, tok, data)
38
+ else on_default(event, tok, data)
39
+ end
40
+ end
41
+ data
42
+ end
43
+
44
+ private
45
+
46
+ def on_default(event, token, data)
47
+ data
48
+ end
49
+ # :startdoc:
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+ # :markup: markdown
3
+
4
+ require_relative "../ripper"
5
+
6
+ module Prism
7
+ module Translation
8
+ class Ripper
9
+ class Lexer < Ripper # :nodoc:
10
+ # :stopdoc:
11
+ class State
12
+
13
+ attr_reader :to_int, :to_s
14
+
15
+ def initialize(i)
16
+ @to_int = i
17
+ @to_s = Ripper.lex_state_name(i)
18
+ freeze
19
+ end
20
+
21
+ def [](index)
22
+ case index
23
+ when 0, :to_int
24
+ @to_int
25
+ when 1, :to_s
26
+ @to_s
27
+ else
28
+ nil
29
+ end
30
+ end
31
+
32
+ alias to_i to_int
33
+ alias inspect to_s
34
+ def pretty_print(q) q.text(to_s) end
35
+ def ==(i) super or to_int == i end
36
+ def &(i) self.class.new(to_int & i) end
37
+ def |(i) self.class.new(to_int | i) end
38
+ def allbits?(i) to_int.allbits?(i) end
39
+ def anybits?(i) to_int.anybits?(i) end
40
+ def nobits?(i) to_int.nobits?(i) end
41
+
42
+ # Instances are frozen and there are only a handful of them so we cache them here.
43
+ STATES = Hash.new { |h,k| h[k] = State.new(k) }
44
+
45
+ def self.cached(i)
46
+ STATES[i]
47
+ end
48
+ end
49
+
50
+ class Elem
51
+ attr_accessor :pos, :event, :tok, :state, :message
52
+
53
+ def initialize(pos, event, tok, state, message = nil)
54
+ @pos = pos
55
+ @event = event
56
+ @tok = tok
57
+ @state = State.cached(state)
58
+ @message = message
59
+ end
60
+
61
+ def [](index)
62
+ case index
63
+ when 0, :pos
64
+ @pos
65
+ when 1, :event
66
+ @event
67
+ when 2, :tok
68
+ @tok
69
+ when 3, :state
70
+ @state
71
+ when 4, :message
72
+ @message
73
+ else
74
+ nil
75
+ end
76
+ end
77
+
78
+ def inspect
79
+ "#<#{self.class}: #{event}@#{pos[0]}:#{pos[1]}:#{state}: #{tok.inspect}#{": " if message}#{message}>"
80
+ end
81
+
82
+ alias to_s inspect
83
+
84
+ def pretty_print(q)
85
+ q.group(2, "#<#{self.class}:", ">") {
86
+ q.breakable
87
+ q.text("#{event}@#{pos[0]}:#{pos[1]}")
88
+ q.breakable
89
+ state.pretty_print(q)
90
+ q.breakable
91
+ q.text("token: ")
92
+ tok.pretty_print(q)
93
+ if message
94
+ q.breakable
95
+ q.text("message: ")
96
+ q.text(message)
97
+ end
98
+ }
99
+ end
100
+
101
+ def to_a
102
+ if @message
103
+ [@pos, @event, @tok, @state, @message]
104
+ else
105
+ [@pos, @event, @tok, @state]
106
+ end
107
+ end
108
+ end
109
+
110
+ # Pretty much just the same as Prism.lex_compat.
111
+ def lex(raise_errors: false)
112
+ Ripper.lex(@source, filename, lineno, raise_errors: raise_errors)
113
+ end
114
+
115
+ # Returns the lex_compat result wrapped in `Elem`. Errors are omitted.
116
+ # Since ripper is a streaming parser, tokens are expected to be emitted in the order
117
+ # that the parser encounters them. This is not implemented.
118
+ def parse(...)
119
+ lex(...).map do |position, event, token, state|
120
+ Elem.new(position, event, token, state.to_int)
121
+ end
122
+ end
123
+
124
+ # Similar to parse but ripper sorts the elements by position in the source. Also
125
+ # includes errors. Since prism does error recovery, in cases of syntax errors
126
+ # the result may differ greatly compared to ripper.
127
+ def scan(...)
128
+ parse(...)
129
+ end
130
+
131
+ # :startdoc:
132
+ end
133
+ end
134
+ end
135
+ end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  # :markup: markdown
3
3
 
4
- require "ripper"
5
-
6
4
  module Prism
7
5
  module Translation
8
6
  # This class provides a compatibility layer between prism and Ripper. It
@@ -80,6 +78,19 @@ module Prism
80
78
  end
81
79
  end
82
80
 
81
+ # Tokenizes the Ruby program and returns an array of strings.
82
+ # The +filename+ and +lineno+ arguments are mostly ignored, since the
83
+ # return value is just the tokenized input.
84
+ # By default, this method does not handle syntax errors in +src+,
85
+ # use the +raise_errors+ keyword to raise a SyntaxError for an error in +src+.
86
+ #
87
+ # p Ripper.tokenize("def m(a) nil end")
88
+ # # => ["def", " ", "m", "(", "a", ")", " ", "nil", " ", "end"]
89
+ #
90
+ def self.tokenize(...)
91
+ lex(...).map(&:value)
92
+ end
93
+
83
94
  # This contains a table of all of the parser events and their
84
95
  # corresponding arity.
85
96
  PARSER_EVENT_TABLE = {
@@ -426,9 +437,35 @@ module Prism
426
437
  end
427
438
  end
428
439
 
440
+ autoload :Filter, "prism/translation/ripper/filter"
441
+ autoload :Lexer, "prism/translation/ripper/lexer"
429
442
  autoload :SexpBuilder, "prism/translation/ripper/sexp"
430
443
  autoload :SexpBuilderPP, "prism/translation/ripper/sexp"
431
444
 
445
+ # :stopdoc:
446
+ # This is not part of the public API but used by some gems.
447
+
448
+ # Ripper-internal bitflags.
449
+ LEX_STATE_NAMES = %i[
450
+ BEG END ENDARG ENDFN ARG CMDARG MID FNAME DOT CLASS LABEL LABELED FITEM
451
+ ].map.with_index.to_h { |name, i| [2 ** i, name] }.freeze
452
+ private_constant :LEX_STATE_NAMES
453
+
454
+ LEX_STATE_NAMES.each do |value, key|
455
+ const_set("EXPR_#{key}", value)
456
+ end
457
+ EXPR_NONE = 0
458
+ EXPR_VALUE = EXPR_BEG
459
+ EXPR_BEG_ANY = EXPR_BEG | EXPR_MID | EXPR_CLASS
460
+ EXPR_ARG_ANY = EXPR_ARG | EXPR_CMDARG
461
+ EXPR_END_ANY = EXPR_END | EXPR_ENDARG | EXPR_ENDFN
462
+
463
+ def self.lex_state_name(state)
464
+ LEX_STATE_NAMES.filter_map { |flag, name| name if state & flag != 0 }.join("|")
465
+ end
466
+
467
+ # :startdoc:
468
+
432
469
  # The source that is being parsed.
433
470
  attr_reader :source
434
471
 
@@ -795,7 +832,7 @@ module Prism
795
832
  # foo(bar)
796
833
  # ^^^
797
834
  def visit_arguments_node(node)
798
- arguments, _ = visit_call_node_arguments(node, nil, false)
835
+ arguments, _, _ = visit_call_node_arguments(node, nil, false)
799
836
  arguments
800
837
  end
801
838
 
@@ -1005,16 +1042,16 @@ module Prism
1005
1042
  case node.name
1006
1043
  when :[]
1007
1044
  receiver = visit(node.receiver)
1008
- arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
1045
+ arguments, block, has_ripper_block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
1009
1046
 
1010
1047
  bounds(node.location)
1011
1048
  call = on_aref(receiver, arguments)
1012
1049
 
1013
- if block.nil?
1014
- call
1015
- else
1050
+ if has_ripper_block
1016
1051
  bounds(node.location)
1017
1052
  on_method_add_block(call, block)
1053
+ else
1054
+ call
1018
1055
  end
1019
1056
  when :[]=
1020
1057
  receiver = visit(node.receiver)
@@ -1073,9 +1110,9 @@ module Prism
1073
1110
  if node.variable_call?
1074
1111
  on_vcall(message)
1075
1112
  else
1076
- arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
1113
+ arguments, block, has_ripper_block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
1077
1114
  call =
1078
- if node.opening_loc.nil? && arguments&.any?
1115
+ if node.opening_loc.nil? && get_arguments_and_block(node.arguments, node.block).first.any?
1079
1116
  bounds(node.location)
1080
1117
  on_command(message, arguments)
1081
1118
  elsif !node.opening_loc.nil?
@@ -1086,11 +1123,11 @@ module Prism
1086
1123
  on_method_add_arg(on_fcall(message), on_args_new)
1087
1124
  end
1088
1125
 
1089
- if block.nil?
1090
- call
1091
- else
1126
+ if has_ripper_block
1092
1127
  bounds(node.block.location)
1093
1128
  on_method_add_block(call, block)
1129
+ else
1130
+ call
1094
1131
  end
1095
1132
  end
1096
1133
  end
@@ -1114,7 +1151,7 @@ module Prism
1114
1151
  bounds(node.location)
1115
1152
  on_assign(on_field(receiver, call_operator, message), value)
1116
1153
  else
1117
- arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
1154
+ arguments, block, has_ripper_block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location))
1118
1155
  call =
1119
1156
  if node.opening_loc.nil?
1120
1157
  bounds(node.location)
@@ -1132,27 +1169,35 @@ module Prism
1132
1169
  on_method_add_arg(on_call(receiver, call_operator, message), arguments)
1133
1170
  end
1134
1171
 
1135
- if block.nil?
1136
- call
1137
- else
1172
+ if has_ripper_block
1138
1173
  bounds(node.block.location)
1139
1174
  on_method_add_block(call, block)
1175
+ else
1176
+ call
1140
1177
  end
1141
1178
  end
1142
1179
  end
1143
1180
  end
1144
1181
 
1145
- # Visit the arguments and block of a call node and return the arguments
1146
- # and block as they should be used.
1147
- private def visit_call_node_arguments(arguments_node, block_node, trailing_comma)
1182
+ # Extract the arguments and block Ripper-style, which means if the block
1183
+ # is like `&b` then it's moved to arguments.
1184
+ private def get_arguments_and_block(arguments_node, block_node)
1148
1185
  arguments = arguments_node&.arguments || []
1149
1186
  block = block_node
1150
1187
 
1151
1188
  if block.is_a?(BlockArgumentNode)
1152
- arguments << block
1189
+ arguments += [block]
1153
1190
  block = nil
1154
1191
  end
1155
1192
 
1193
+ [arguments, block]
1194
+ end
1195
+
1196
+ # Visit the arguments and block of a call node and return the arguments
1197
+ # and block as they should be used.
1198
+ private def visit_call_node_arguments(arguments_node, block_node, trailing_comma)
1199
+ arguments, block = get_arguments_and_block(arguments_node, block_node)
1200
+
1156
1201
  [
1157
1202
  if arguments.length == 1 && arguments.first.is_a?(ForwardingArgumentsNode)
1158
1203
  visit(arguments.first)
@@ -1166,7 +1211,8 @@ module Prism
1166
1211
  on_args_add_block(args, false)
1167
1212
  end
1168
1213
  end,
1169
- visit(block)
1214
+ visit(block),
1215
+ block != nil,
1170
1216
  ]
1171
1217
  end
1172
1218
 
@@ -1603,10 +1649,10 @@ module Prism
1603
1649
  end
1604
1650
 
1605
1651
  bounds(node.location)
1606
- if receiver.nil?
1607
- on_def(name, parameters, bodystmt)
1608
- else
1652
+ if receiver
1609
1653
  on_defs(receiver, operator, name, parameters, bodystmt)
1654
+ else
1655
+ on_def(name, parameters, bodystmt)
1610
1656
  end
1611
1657
  end
1612
1658
 
@@ -2004,7 +2050,7 @@ module Prism
2004
2050
  # ^^^^^^^^^^^^^^^
2005
2051
  def visit_index_operator_write_node(node)
2006
2052
  receiver = visit(node.receiver)
2007
- arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2053
+ arguments, _, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2008
2054
 
2009
2055
  bounds(node.location)
2010
2056
  target = on_aref_field(receiver, arguments)
@@ -2021,7 +2067,7 @@ module Prism
2021
2067
  # ^^^^^^^^^^^^^^^^
2022
2068
  def visit_index_and_write_node(node)
2023
2069
  receiver = visit(node.receiver)
2024
- arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2070
+ arguments, _, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2025
2071
 
2026
2072
  bounds(node.location)
2027
2073
  target = on_aref_field(receiver, arguments)
@@ -2038,7 +2084,7 @@ module Prism
2038
2084
  # ^^^^^^^^^^^^^^^^
2039
2085
  def visit_index_or_write_node(node)
2040
2086
  receiver = visit(node.receiver)
2041
- arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2087
+ arguments, _, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2042
2088
 
2043
2089
  bounds(node.location)
2044
2090
  target = on_aref_field(receiver, arguments)
@@ -2055,7 +2101,7 @@ module Prism
2055
2101
  # ^^^^^^^^
2056
2102
  def visit_index_target_node(node)
2057
2103
  receiver = visit(node.receiver)
2058
- arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2104
+ arguments, _, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc))
2059
2105
 
2060
2106
  bounds(node.location)
2061
2107
  on_aref_field(receiver, arguments)
@@ -3085,7 +3131,7 @@ module Prism
3085
3131
  # super(foo)
3086
3132
  # ^^^^^^^^^^
3087
3133
  def visit_super_node(node)
3088
- arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.rparen_loc || node.location))
3134
+ arguments, block, has_ripper_block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.rparen_loc || node.location))
3089
3135
 
3090
3136
  if !node.lparen_loc.nil?
3091
3137
  bounds(node.lparen_loc)
@@ -3095,11 +3141,11 @@ module Prism
3095
3141
  bounds(node.location)
3096
3142
  call = on_super(arguments)
3097
3143
 
3098
- if block.nil?
3099
- call
3100
- else
3144
+ if has_ripper_block
3101
3145
  bounds(node.block.location)
3102
3146
  on_method_add_block(call, block)
3147
+ else
3148
+ call
3103
3149
  end
3104
3150
  end
3105
3151
 
@@ -3409,12 +3455,12 @@ module Prism
3409
3455
 
3410
3456
  # :stopdoc:
3411
3457
  def _dispatch_0; end
3412
- def _dispatch_1(_); end
3413
- def _dispatch_2(_, _); end
3414
- def _dispatch_3(_, _, _); end
3415
- def _dispatch_4(_, _, _, _); end
3416
- def _dispatch_5(_, _, _, _, _); end
3417
- def _dispatch_7(_, _, _, _, _, _, _); end
3458
+ def _dispatch_1(arg); arg end
3459
+ def _dispatch_2(arg, _); arg end
3460
+ def _dispatch_3(arg, _, _); arg end
3461
+ def _dispatch_4(arg, _, _, _); arg end
3462
+ def _dispatch_5(arg, _, _, _, _); arg end
3463
+ def _dispatch_7(arg, _, _, _, _, _, _); arg end
3418
3464
  # :startdoc:
3419
3465
 
3420
3466
  #
@@ -1422,7 +1422,7 @@ module Prism
1422
1422
  # ```
1423
1423
  def visit_parameters_node(node)
1424
1424
  children =
1425
- node.compact_child_nodes.map do |element|
1425
+ node.each_child_node.map do |element|
1426
1426
  if element.is_a?(MultiTargetNode)
1427
1427
  visit_destructured_parameter(element)
1428
1428
  else
@@ -7,11 +7,11 @@ module Prism
7
7
  module Translation # steep:ignore
8
8
  autoload :Parser, "prism/translation/parser"
9
9
  autoload :ParserCurrent, "prism/translation/parser_current"
10
- autoload :Parser33, "prism/translation/parser33"
11
- autoload :Parser34, "prism/translation/parser34"
12
- autoload :Parser35, "prism/translation/parser35"
13
- autoload :Parser40, "prism/translation/parser40"
14
- autoload :Parser41, "prism/translation/parser41"
10
+ autoload :Parser33, "prism/translation/parser_versions"
11
+ autoload :Parser34, "prism/translation/parser_versions"
12
+ autoload :Parser35, "prism/translation/parser_versions"
13
+ autoload :Parser40, "prism/translation/parser_versions"
14
+ autoload :Parser41, "prism/translation/parser_versions"
15
15
  autoload :Ripper, "prism/translation/ripper"
16
16
  autoload :RubyParser, "prism/translation/ruby_parser"
17
17
  end