prism 0.23.0 → 0.25.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/BSDmakefile +58 -0
- data/CHANGELOG.md +65 -1
- data/Makefile +5 -2
- data/README.md +45 -6
- data/config.yml +499 -4
- data/docs/build_system.md +31 -0
- data/docs/configuration.md +2 -0
- data/docs/cruby_compilation.md +1 -1
- data/docs/parser_translation.md +14 -9
- data/docs/releasing.md +3 -3
- data/docs/ripper_translation.md +50 -0
- data/docs/ruby_api.md +1 -0
- data/docs/serialization.md +26 -5
- data/ext/prism/api_node.c +2342 -1801
- data/ext/prism/api_pack.c +9 -0
- data/ext/prism/extconf.rb +27 -11
- data/ext/prism/extension.c +313 -66
- data/ext/prism/extension.h +5 -4
- data/include/prism/ast.h +213 -64
- data/include/prism/defines.h +106 -2
- data/include/prism/diagnostic.h +134 -71
- data/include/prism/encoding.h +22 -4
- data/include/prism/node.h +93 -0
- data/include/prism/options.h +82 -7
- data/include/prism/pack.h +11 -0
- data/include/prism/parser.h +198 -53
- data/include/prism/prettyprint.h +8 -0
- data/include/prism/static_literals.h +118 -0
- data/include/prism/util/pm_buffer.h +65 -2
- data/include/prism/util/pm_constant_pool.h +18 -1
- data/include/prism/util/pm_integer.h +119 -0
- data/include/prism/util/pm_list.h +1 -1
- data/include/prism/util/pm_newline_list.h +12 -3
- data/include/prism/util/pm_string.h +26 -2
- data/include/prism/version.h +2 -2
- data/include/prism.h +59 -1
- data/lib/prism/compiler.rb +8 -1
- data/lib/prism/debug.rb +46 -3
- data/lib/prism/desugar_compiler.rb +225 -80
- data/lib/prism/dispatcher.rb +29 -0
- data/lib/prism/dot_visitor.rb +87 -16
- data/lib/prism/dsl.rb +315 -300
- data/lib/prism/ffi.rb +165 -84
- data/lib/prism/lex_compat.rb +17 -15
- data/lib/prism/mutation_compiler.rb +11 -0
- data/lib/prism/node.rb +4857 -3750
- data/lib/prism/node_ext.rb +77 -29
- data/lib/prism/pack.rb +4 -0
- data/lib/prism/parse_result/comments.rb +34 -17
- data/lib/prism/parse_result/newlines.rb +3 -1
- data/lib/prism/parse_result.rb +88 -34
- data/lib/prism/pattern.rb +16 -4
- data/lib/prism/polyfill/string.rb +12 -0
- data/lib/prism/serialize.rb +960 -327
- data/lib/prism/translation/parser/compiler.rb +152 -50
- data/lib/prism/translation/parser/lexer.rb +103 -22
- data/lib/prism/translation/parser/rubocop.rb +47 -11
- data/lib/prism/translation/parser.rb +134 -10
- data/lib/prism/translation/parser33.rb +12 -0
- data/lib/prism/translation/parser34.rb +12 -0
- data/lib/prism/translation/ripper/sexp.rb +125 -0
- data/lib/prism/translation/ripper/shim.rb +5 -0
- data/lib/prism/translation/ripper.rb +3248 -379
- data/lib/prism/translation/ruby_parser.rb +35 -18
- data/lib/prism/translation.rb +3 -1
- data/lib/prism/visitor.rb +10 -0
- data/lib/prism.rb +8 -2
- data/prism.gemspec +35 -4
- data/rbi/prism/compiler.rbi +14 -0
- data/rbi/prism/desugar_compiler.rbi +5 -0
- data/rbi/prism/mutation_compiler.rbi +5 -0
- data/rbi/prism/node.rbi +8221 -0
- data/rbi/prism/node_ext.rbi +102 -0
- data/rbi/prism/parse_result.rbi +304 -0
- data/rbi/prism/translation/parser/compiler.rbi +13 -0
- data/rbi/prism/translation/ripper/ripper_compiler.rbi +5 -0
- data/rbi/prism/translation/ripper.rbi +25 -0
- data/rbi/prism/translation/ruby_parser.rbi +11 -0
- data/rbi/prism/visitor.rbi +470 -0
- data/rbi/prism.rbi +39 -7749
- data/sig/prism/compiler.rbs +9 -0
- data/sig/prism/dispatcher.rbs +16 -0
- data/sig/prism/dot_visitor.rbs +6 -0
- data/sig/prism/dsl.rbs +462 -0
- data/sig/prism/mutation_compiler.rbs +158 -0
- data/sig/prism/node.rbs +3529 -0
- data/sig/prism/node_ext.rbs +78 -0
- data/sig/prism/pack.rbs +43 -0
- data/sig/prism/parse_result.rbs +127 -0
- data/sig/prism/pattern.rbs +13 -0
- data/sig/prism/serialize.rbs +7 -0
- data/sig/prism/visitor.rbs +168 -0
- data/sig/prism.rbs +188 -4767
- data/src/diagnostic.c +575 -230
- data/src/encoding.c +211 -108
- data/src/node.c +7526 -447
- data/src/options.c +36 -12
- data/src/pack.c +33 -17
- data/src/prettyprint.c +1297 -1388
- data/src/prism.c +3665 -1121
- data/src/regexp.c +17 -2
- data/src/serialize.c +47 -28
- data/src/static_literals.c +552 -0
- data/src/token_type.c +1 -0
- data/src/util/pm_buffer.c +147 -20
- data/src/util/pm_char.c +4 -4
- data/src/util/pm_constant_pool.c +35 -11
- data/src/util/pm_integer.c +629 -0
- data/src/util/pm_list.c +1 -1
- data/src/util/pm_newline_list.c +20 -8
- data/src/util/pm_string.c +134 -5
- data/src/util/pm_string_list.c +2 -2
- metadata +37 -6
- data/docs/ripper.md +0 -36
- data/rbi/prism_static.rbi +0 -207
- data/sig/prism_static.rbs +0 -201
@@ -1,28 +1,64 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
# typed: ignore
|
3
|
+
|
4
|
+
warn "WARN: Prism is directly supported since RuboCop 1.62. The `prism/translation/parser/rubocop` file is deprecated."
|
2
5
|
|
3
6
|
require "parser"
|
4
7
|
require "rubocop"
|
5
8
|
|
6
|
-
|
7
|
-
|
9
|
+
require_relative "../../prism"
|
10
|
+
require_relative "../parser"
|
8
11
|
|
9
12
|
module Prism
|
10
13
|
module Translation
|
11
14
|
class Parser
|
12
|
-
# This is the special version
|
15
|
+
# This is the special version numbers that should be used in RuboCop
|
13
16
|
# configuration files to trigger using prism.
|
17
|
+
|
18
|
+
# For Ruby 3.3
|
14
19
|
VERSION_3_3 = 80_82_73_83_77.33
|
15
20
|
|
21
|
+
# For Ruby 3.4
|
22
|
+
VERSION_3_4 = 80_82_73_83_77.34
|
23
|
+
|
16
24
|
# This module gets prepended into RuboCop::AST::ProcessedSource.
|
17
25
|
module ProcessedSource
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
Prism::Translation::Parser
|
24
|
-
|
25
|
-
|
26
|
+
# This condition is compatible with rubocop-ast versions up to 1.30.0.
|
27
|
+
if RuboCop::AST::ProcessedSource.instance_method(:parser_class).arity == 1
|
28
|
+
# Redefine parser_class so that we can inject the prism parser into the
|
29
|
+
# list of known parsers.
|
30
|
+
def parser_class(ruby_version)
|
31
|
+
if ruby_version == Prism::Translation::Parser::VERSION_3_3
|
32
|
+
warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.33` is deprecated. " \
|
33
|
+
"Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.3` instead."
|
34
|
+
require_relative "../parser33"
|
35
|
+
Prism::Translation::Parser33
|
36
|
+
elsif ruby_version == Prism::Translation::Parser::VERSION_3_4
|
37
|
+
warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.34` is deprecated. " \
|
38
|
+
"Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.4` instead."
|
39
|
+
require_relative "../parser34"
|
40
|
+
Prism::Translation::Parser34
|
41
|
+
else
|
42
|
+
super
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
# Redefine parser_class so that we can inject the prism parser into the
|
47
|
+
# list of known parsers.
|
48
|
+
def parser_class(ruby_version, _parser_engine)
|
49
|
+
if ruby_version == Prism::Translation::Parser::VERSION_3_3
|
50
|
+
warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.33` is deprecated. " \
|
51
|
+
"Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.3` instead."
|
52
|
+
require_relative "../parser33"
|
53
|
+
Prism::Translation::Parser33
|
54
|
+
elsif ruby_version == Prism::Translation::Parser::VERSION_3_4
|
55
|
+
warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.34` is deprecated. " \
|
56
|
+
"Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.4` instead."
|
57
|
+
require_relative "../parser34"
|
58
|
+
Prism::Translation::Parser34
|
59
|
+
else
|
60
|
+
super
|
61
|
+
end
|
26
62
|
end
|
27
63
|
end
|
28
64
|
end
|
@@ -9,17 +9,20 @@ module Prism
|
|
9
9
|
# the parser gem, and overrides the parse* methods to parse with prism and
|
10
10
|
# then translate.
|
11
11
|
class Parser < ::Parser::Base
|
12
|
+
Diagnostic = ::Parser::Diagnostic # :nodoc:
|
13
|
+
private_constant :Diagnostic
|
14
|
+
|
12
15
|
# The parser gem has a list of diagnostics with a hard-coded set of error
|
13
16
|
# messages. We create our own diagnostic class in order to set our own
|
14
17
|
# error messages.
|
15
|
-
class
|
16
|
-
#
|
18
|
+
class PrismDiagnostic < Diagnostic
|
19
|
+
# This is the cached message coming from prism.
|
17
20
|
attr_reader :message
|
18
21
|
|
19
22
|
# Initialize a new diagnostic with the given message and location.
|
20
|
-
def initialize(message, location)
|
23
|
+
def initialize(message, level, reason, location)
|
21
24
|
@message = message
|
22
|
-
super(
|
25
|
+
super(level, reason, {}, location, [])
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
@@ -43,7 +46,7 @@ module Prism
|
|
43
46
|
source = source_buffer.source
|
44
47
|
|
45
48
|
offset_cache = build_offset_cache(source)
|
46
|
-
result = unwrap(Prism.parse(source, filepath: source_buffer.name), offset_cache)
|
49
|
+
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version)), offset_cache)
|
47
50
|
|
48
51
|
build_ast(result.value, offset_cache)
|
49
52
|
ensure
|
@@ -56,7 +59,7 @@ module Prism
|
|
56
59
|
source = source_buffer.source
|
57
60
|
|
58
61
|
offset_cache = build_offset_cache(source)
|
59
|
-
result = unwrap(Prism.parse(source, filepath: source_buffer.name), offset_cache)
|
62
|
+
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version)), offset_cache)
|
60
63
|
|
61
64
|
[
|
62
65
|
build_ast(result.value, offset_cache),
|
@@ -75,7 +78,7 @@ module Prism
|
|
75
78
|
offset_cache = build_offset_cache(source)
|
76
79
|
result =
|
77
80
|
begin
|
78
|
-
unwrap(Prism.parse_lex(source, filepath: source_buffer.name), offset_cache)
|
81
|
+
unwrap(Prism.parse_lex(source, filepath: source_buffer.name, version: convert_for_prism(version)), offset_cache)
|
79
82
|
rescue ::Parser::SyntaxError
|
80
83
|
raise if !recover
|
81
84
|
end
|
@@ -106,14 +109,123 @@ module Prism
|
|
106
109
|
true
|
107
110
|
end
|
108
111
|
|
112
|
+
# This is a hook to allow consumers to disable some warnings if they don't
|
113
|
+
# want them to block creating the syntax tree.
|
114
|
+
def valid_warning?(warning)
|
115
|
+
true
|
116
|
+
end
|
117
|
+
|
118
|
+
# Build a diagnostic from the given prism parse error.
|
119
|
+
def error_diagnostic(error, offset_cache)
|
120
|
+
location = error.location
|
121
|
+
diagnostic_location = build_range(location, offset_cache)
|
122
|
+
|
123
|
+
case error.type
|
124
|
+
when :argument_block_multi
|
125
|
+
Diagnostic.new(:error, :block_and_blockarg, {}, diagnostic_location, [])
|
126
|
+
when :argument_formal_constant
|
127
|
+
Diagnostic.new(:error, :argument_const, {}, diagnostic_location, [])
|
128
|
+
when :argument_formal_class
|
129
|
+
Diagnostic.new(:error, :argument_cvar, {}, diagnostic_location, [])
|
130
|
+
when :argument_formal_global
|
131
|
+
Diagnostic.new(:error, :argument_gvar, {}, diagnostic_location, [])
|
132
|
+
when :argument_formal_ivar
|
133
|
+
Diagnostic.new(:error, :argument_ivar, {}, diagnostic_location, [])
|
134
|
+
when :argument_no_forwarding_amp
|
135
|
+
Diagnostic.new(:error, :no_anonymous_blockarg, {}, diagnostic_location, [])
|
136
|
+
when :argument_no_forwarding_star
|
137
|
+
Diagnostic.new(:error, :no_anonymous_restarg, {}, diagnostic_location, [])
|
138
|
+
when :argument_no_forwarding_star_star
|
139
|
+
Diagnostic.new(:error, :no_anonymous_kwrestarg, {}, diagnostic_location, [])
|
140
|
+
when :begin_lonely_else
|
141
|
+
location = location.copy(length: 4)
|
142
|
+
diagnostic_location = build_range(location, offset_cache)
|
143
|
+
Diagnostic.new(:error, :useless_else, {}, diagnostic_location, [])
|
144
|
+
when :class_name, :module_name
|
145
|
+
Diagnostic.new(:error, :module_name_const, {}, diagnostic_location, [])
|
146
|
+
when :class_in_method
|
147
|
+
Diagnostic.new(:error, :class_in_def, {}, diagnostic_location, [])
|
148
|
+
when :def_endless_setter
|
149
|
+
Diagnostic.new(:error, :endless_setter, {}, diagnostic_location, [])
|
150
|
+
when :embdoc_term
|
151
|
+
Diagnostic.new(:error, :embedded_document, {}, diagnostic_location, [])
|
152
|
+
when :incomplete_variable_class, :incomplete_variable_class_3_3_0
|
153
|
+
location = location.copy(length: location.length + 1)
|
154
|
+
diagnostic_location = build_range(location, offset_cache)
|
155
|
+
|
156
|
+
Diagnostic.new(:error, :cvar_name, { name: location.slice }, diagnostic_location, [])
|
157
|
+
when :incomplete_variable_instance, :incomplete_variable_instance_3_3_0
|
158
|
+
location = location.copy(length: location.length + 1)
|
159
|
+
diagnostic_location = build_range(location, offset_cache)
|
160
|
+
|
161
|
+
Diagnostic.new(:error, :ivar_name, { name: location.slice }, diagnostic_location, [])
|
162
|
+
when :invalid_variable_global, :invalid_variable_global_3_3_0
|
163
|
+
Diagnostic.new(:error, :gvar_name, { name: location.slice }, diagnostic_location, [])
|
164
|
+
when :module_in_method
|
165
|
+
Diagnostic.new(:error, :module_in_def, {}, diagnostic_location, [])
|
166
|
+
when :numbered_parameter_ordinary
|
167
|
+
Diagnostic.new(:error, :ordinary_param_defined, {}, diagnostic_location, [])
|
168
|
+
when :numbered_parameter_outer_scope
|
169
|
+
Diagnostic.new(:error, :numparam_used_in_outer_scope, {}, diagnostic_location, [])
|
170
|
+
when :parameter_circular
|
171
|
+
Diagnostic.new(:error, :circular_argument_reference, { var_name: location.slice }, diagnostic_location, [])
|
172
|
+
when :parameter_name_repeat
|
173
|
+
Diagnostic.new(:error, :duplicate_argument, {}, diagnostic_location, [])
|
174
|
+
when :parameter_numbered_reserved
|
175
|
+
Diagnostic.new(:error, :reserved_for_numparam, { name: location.slice }, diagnostic_location, [])
|
176
|
+
when :regexp_unknown_options
|
177
|
+
Diagnostic.new(:error, :regexp_options, { options: location.slice[1..] }, diagnostic_location, [])
|
178
|
+
when :singleton_for_literals
|
179
|
+
Diagnostic.new(:error, :singleton_literal, {}, diagnostic_location, [])
|
180
|
+
when :string_literal_eof
|
181
|
+
Diagnostic.new(:error, :string_eof, {}, diagnostic_location, [])
|
182
|
+
when :unexpected_token_ignore
|
183
|
+
Diagnostic.new(:error, :unexpected_token, { token: location.slice }, diagnostic_location, [])
|
184
|
+
when :write_target_in_method
|
185
|
+
Diagnostic.new(:error, :dynamic_const, {}, diagnostic_location, [])
|
186
|
+
else
|
187
|
+
PrismDiagnostic.new(error.message, :error, error.type, diagnostic_location)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Build a diagnostic from the given prism parse warning.
|
192
|
+
def warning_diagnostic(warning, offset_cache)
|
193
|
+
diagnostic_location = build_range(warning.location, offset_cache)
|
194
|
+
|
195
|
+
case warning.type
|
196
|
+
when :ambiguous_first_argument_plus
|
197
|
+
Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "+" }, diagnostic_location, [])
|
198
|
+
when :ambiguous_first_argument_minus
|
199
|
+
Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "-" }, diagnostic_location, [])
|
200
|
+
when :ambiguous_prefix_ampersand
|
201
|
+
Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "&" }, diagnostic_location, [])
|
202
|
+
when :ambiguous_prefix_star
|
203
|
+
Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "*" }, diagnostic_location, [])
|
204
|
+
when :ambiguous_prefix_star_star
|
205
|
+
Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "**" }, diagnostic_location, [])
|
206
|
+
when :ambiguous_slash
|
207
|
+
Diagnostic.new(:warning, :ambiguous_regexp, {}, diagnostic_location, [])
|
208
|
+
when :dot_dot_dot_eol
|
209
|
+
Diagnostic.new(:warning, :triple_dot_at_eol, {}, diagnostic_location, [])
|
210
|
+
when :duplicated_hash_key
|
211
|
+
# skip, parser does this on its own
|
212
|
+
else
|
213
|
+
PrismDiagnostic.new(warning.message, :warning, warning.type, diagnostic_location)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
109
217
|
# If there was a error generated during the parse, then raise an
|
110
218
|
# appropriate syntax error. Otherwise return the result.
|
111
219
|
def unwrap(result, offset_cache)
|
112
220
|
result.errors.each do |error|
|
113
221
|
next unless valid_error?(error)
|
222
|
+
diagnostics.process(error_diagnostic(error, offset_cache))
|
223
|
+
end
|
114
224
|
|
115
|
-
|
116
|
-
|
225
|
+
result.warnings.each do |warning|
|
226
|
+
next unless valid_warning?(warning)
|
227
|
+
diagnostic = warning_diagnostic(warning, offset_cache)
|
228
|
+
diagnostics.process(diagnostic) if diagnostic
|
117
229
|
end
|
118
230
|
|
119
231
|
result
|
@@ -156,7 +268,7 @@ module Prism
|
|
156
268
|
|
157
269
|
# Build the parser gem tokens from the prism tokens.
|
158
270
|
def build_tokens(tokens, offset_cache)
|
159
|
-
Lexer.new(source_buffer, tokens
|
271
|
+
Lexer.new(source_buffer, tokens, offset_cache).to_a
|
160
272
|
end
|
161
273
|
|
162
274
|
# Build a range from a prism location.
|
@@ -168,6 +280,18 @@ module Prism
|
|
168
280
|
)
|
169
281
|
end
|
170
282
|
|
283
|
+
# Converts the version format handled by Parser to the format handled by Prism.
|
284
|
+
def convert_for_prism(version)
|
285
|
+
case version
|
286
|
+
when 33
|
287
|
+
"3.3.0"
|
288
|
+
when 34
|
289
|
+
"3.4.0"
|
290
|
+
else
|
291
|
+
"latest"
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
171
295
|
require_relative "parser/compiler"
|
172
296
|
require_relative "parser/lexer"
|
173
297
|
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../ripper"
|
4
|
+
|
5
|
+
module Prism
|
6
|
+
module Translation
|
7
|
+
class Ripper
|
8
|
+
# This class mirrors the ::Ripper::SexpBuilder subclass of ::Ripper that
|
9
|
+
# returns the arrays of [type, *children].
|
10
|
+
class SexpBuilder < Ripper
|
11
|
+
# :stopdoc:
|
12
|
+
|
13
|
+
attr_reader :error
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def dedent_element(e, width)
|
18
|
+
if (n = dedent_string(e[1], width)) > 0
|
19
|
+
e[2][1] += n
|
20
|
+
end
|
21
|
+
e
|
22
|
+
end
|
23
|
+
|
24
|
+
def on_heredoc_dedent(val, width)
|
25
|
+
sub = proc do |cont|
|
26
|
+
cont.map! do |e|
|
27
|
+
if Array === e
|
28
|
+
case e[0]
|
29
|
+
when :@tstring_content
|
30
|
+
e = dedent_element(e, width)
|
31
|
+
when /_add\z/
|
32
|
+
e[1] = sub[e[1]]
|
33
|
+
end
|
34
|
+
elsif String === e
|
35
|
+
dedent_string(e, width)
|
36
|
+
end
|
37
|
+
e
|
38
|
+
end
|
39
|
+
end
|
40
|
+
sub[val]
|
41
|
+
val
|
42
|
+
end
|
43
|
+
|
44
|
+
events = private_instance_methods(false).grep(/\Aon_/) {$'.to_sym}
|
45
|
+
(PARSER_EVENTS - events).each do |event|
|
46
|
+
module_eval(<<-End, __FILE__, __LINE__ + 1)
|
47
|
+
def on_#{event}(*args)
|
48
|
+
args.unshift :#{event}
|
49
|
+
end
|
50
|
+
End
|
51
|
+
end
|
52
|
+
|
53
|
+
SCANNER_EVENTS.each do |event|
|
54
|
+
module_eval(<<-End, __FILE__, __LINE__ + 1)
|
55
|
+
def on_#{event}(tok)
|
56
|
+
[:@#{event}, tok, [lineno(), column()]]
|
57
|
+
end
|
58
|
+
End
|
59
|
+
end
|
60
|
+
|
61
|
+
def on_error(mesg)
|
62
|
+
@error = mesg
|
63
|
+
end
|
64
|
+
remove_method :on_parse_error
|
65
|
+
alias on_parse_error on_error
|
66
|
+
alias compile_error on_error
|
67
|
+
|
68
|
+
# :startdoc:
|
69
|
+
end
|
70
|
+
|
71
|
+
# This class mirrors the ::Ripper::SexpBuilderPP subclass of ::Ripper that
|
72
|
+
# returns the same values as ::Ripper::SexpBuilder except with a couple of
|
73
|
+
# niceties that flatten linked lists into arrays.
|
74
|
+
class SexpBuilderPP < SexpBuilder
|
75
|
+
# :stopdoc:
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def on_heredoc_dedent(val, width)
|
80
|
+
val.map! do |e|
|
81
|
+
next e if Symbol === e and /_content\z/ =~ e
|
82
|
+
if Array === e and e[0] == :@tstring_content
|
83
|
+
e = dedent_element(e, width)
|
84
|
+
elsif String === e
|
85
|
+
dedent_string(e, width)
|
86
|
+
end
|
87
|
+
e
|
88
|
+
end
|
89
|
+
val
|
90
|
+
end
|
91
|
+
|
92
|
+
def _dispatch_event_new
|
93
|
+
[]
|
94
|
+
end
|
95
|
+
|
96
|
+
def _dispatch_event_push(list, item)
|
97
|
+
list.push item
|
98
|
+
list
|
99
|
+
end
|
100
|
+
|
101
|
+
def on_mlhs_paren(list)
|
102
|
+
[:mlhs, *list]
|
103
|
+
end
|
104
|
+
|
105
|
+
def on_mlhs_add_star(list, star)
|
106
|
+
list.push([:rest_param, star])
|
107
|
+
end
|
108
|
+
|
109
|
+
def on_mlhs_add_post(list, post)
|
110
|
+
list.concat(post)
|
111
|
+
end
|
112
|
+
|
113
|
+
PARSER_EVENT_TABLE.each do |event, arity|
|
114
|
+
if /_new\z/ =~ event and arity == 0
|
115
|
+
alias_method "on_#{event}", :_dispatch_event_new
|
116
|
+
elsif /_add\z/ =~ event
|
117
|
+
alias_method "on_#{event}", :_dispatch_event_push
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# :startdoc:
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|