prism 0.24.0 → 0.25.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/BSDmakefile +58 -0
- data/CHANGELOG.md +50 -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 +2 -2
- 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 +911 -815
- 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 +8 -0
- 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 +1 -1
- data/lib/prism/dispatcher.rb +29 -0
- data/lib/prism/dot_visitor.rb +87 -16
- data/lib/prism/dsl.rb +24 -12
- data/lib/prism/ffi.rb +67 -12
- data/lib/prism/lex_compat.rb +17 -15
- data/lib/prism/mutation_compiler.rb +11 -0
- data/lib/prism/node.rb +2096 -2499
- 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 +78 -32
- data/lib/prism/pattern.rb +16 -4
- data/lib/prism/polyfill/string.rb +12 -0
- data/lib/prism/serialize.rb +439 -102
- 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 +41 -13
- data/lib/prism/translation/parser.rb +119 -7
- data/lib/prism/translation/parser33.rb +1 -1
- data/lib/prism/translation/parser34.rb +1 -1
- data/lib/prism/translation/ripper/sexp.rb +125 -0
- data/lib/prism/translation/ripper/shim.rb +5 -0
- data/lib/prism/translation/ripper.rb +3212 -462
- 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 +33 -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 +1294 -1385
- data/src/prism.c +3628 -1099
- 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 +14 -5
- data/src/util/pm_string.c +134 -5
- data/src/util/pm_string_list.c +2 -2
- metadata +35 -6
- data/docs/ripper.md +0 -36
- data/rbi/prism_static.rbi +0 -207
- data/sig/prism_static.rbs +0 -201
@@ -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
|
|
@@ -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.
|
@@ -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
|