prism 0.17.1 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +60 -1
- data/Makefile +5 -5
- data/README.md +4 -3
- data/config.yml +214 -68
- data/docs/build_system.md +6 -6
- data/docs/building.md +10 -3
- data/docs/configuration.md +11 -9
- data/docs/encoding.md +92 -88
- data/docs/heredocs.md +1 -1
- data/docs/javascript.md +29 -1
- data/docs/local_variable_depth.md +229 -0
- data/docs/ruby_api.md +16 -0
- data/docs/serialization.md +18 -13
- data/ext/prism/api_node.c +411 -240
- data/ext/prism/extconf.rb +97 -127
- data/ext/prism/extension.c +97 -33
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +377 -159
- data/include/prism/defines.h +17 -0
- data/include/prism/diagnostic.h +38 -6
- data/include/prism/{enc/pm_encoding.h → encoding.h} +126 -64
- data/include/prism/options.h +2 -2
- data/include/prism/parser.h +62 -36
- data/include/prism/regexp.h +2 -2
- data/include/prism/util/pm_buffer.h +9 -1
- data/include/prism/util/pm_memchr.h +2 -2
- data/include/prism/util/pm_strpbrk.h +3 -3
- data/include/prism/version.h +3 -3
- data/include/prism.h +13 -15
- data/lib/prism/compiler.rb +15 -3
- data/lib/prism/debug.rb +13 -4
- data/lib/prism/desugar_compiler.rb +4 -3
- data/lib/prism/dispatcher.rb +70 -14
- data/lib/prism/dot_visitor.rb +4612 -0
- data/lib/prism/dsl.rb +77 -57
- data/lib/prism/ffi.rb +19 -6
- data/lib/prism/lex_compat.rb +19 -9
- data/lib/prism/mutation_compiler.rb +26 -6
- data/lib/prism/node.rb +1314 -522
- data/lib/prism/node_ext.rb +102 -19
- data/lib/prism/parse_result.rb +58 -27
- data/lib/prism/ripper_compat.rb +49 -34
- data/lib/prism/serialize.rb +251 -227
- data/lib/prism/visitor.rb +15 -3
- data/lib/prism.rb +21 -4
- data/prism.gemspec +7 -9
- data/rbi/prism.rbi +688 -284
- data/rbi/prism_static.rbi +3 -0
- data/sig/prism.rbs +426 -156
- data/sig/prism_static.rbs +1 -0
- data/src/diagnostic.c +280 -216
- data/src/encoding.c +5137 -0
- data/src/node.c +99 -21
- data/src/options.c +21 -2
- data/src/prettyprint.c +1743 -1241
- data/src/prism.c +1774 -831
- data/src/regexp.c +15 -15
- data/src/serialize.c +261 -164
- data/src/util/pm_buffer.c +10 -1
- data/src/util/pm_memchr.c +1 -1
- data/src/util/pm_strpbrk.c +4 -4
- metadata +8 -10
- data/src/enc/pm_big5.c +0 -53
- data/src/enc/pm_euc_jp.c +0 -59
- data/src/enc/pm_gbk.c +0 -62
- data/src/enc/pm_shift_jis.c +0 -57
- data/src/enc/pm_tables.c +0 -743
- data/src/enc/pm_unicode.c +0 -2369
- data/src/enc/pm_windows_31j.c +0 -57
data/ext/prism/extconf.rb
CHANGED
@@ -1,136 +1,106 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
if ARGV.delete("--help")
|
4
|
+
print(<<~TEXT)
|
5
|
+
USAGE: ruby #{$PROGRAM_NAME} [options]
|
6
|
+
|
7
|
+
Flags that are always valid:
|
8
|
+
|
9
|
+
--enable-debug-mode-build
|
10
|
+
Enable debug mode build.
|
11
|
+
You may also use set PRISM_DEBUG_MODE_BUILD environment variable.
|
12
|
+
|
13
|
+
--help
|
14
|
+
Display this message.
|
15
|
+
|
16
|
+
Environment variables used:
|
17
|
+
|
18
|
+
PRISM_DEBUG_MODE_BUILD
|
19
|
+
Equivalent to `--enable-debug-mode-build` when set, even if nil or blank.
|
4
20
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
require "mkmf"
|
19
|
-
configure_c_extension
|
20
|
-
configure_rubyparser
|
21
|
-
|
22
|
-
create_makefile("prism/prism")
|
23
|
-
|
24
|
-
if static_link?
|
25
|
-
File.open('Makefile', 'a') do |mf|
|
26
|
-
mf.puts
|
27
|
-
mf.puts '# Automatically rebuild the extension if librubyparser.a changed'
|
28
|
-
mf.puts '$(TARGET_SO): $(LOCAL_LIBS)'
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def configure_c_extension
|
34
|
-
append_cflags("-DPRISM_DEBUG_MODE_BUILD") if debug_mode_build?
|
35
|
-
append_cflags("-fvisibility=hidden")
|
36
|
-
end
|
37
|
-
|
38
|
-
def configure_rubyparser
|
39
|
-
if static_link?
|
40
|
-
static_archive_path = File.join(build_dir, "librubyparser.a")
|
41
|
-
unless File.exist?(static_archive_path)
|
42
|
-
build_static_rubyparser
|
43
|
-
end
|
44
|
-
$LOCAL_LIBS << " #{static_archive_path}"
|
45
|
-
else
|
46
|
-
shared_library_path = File.join(build_dir, "librubyparser.#{RbConfig::CONFIG["SOEXT"]}")
|
47
|
-
unless File.exist?(shared_library_path)
|
48
|
-
build_shared_rubyparser
|
49
|
-
end
|
50
|
-
unless find_library("rubyparser", "pm_parser_init", build_dir)
|
51
|
-
raise "could not link against #{File.basename(shared_library_path)}"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
find_header("prism.h", include_dir) or raise "prism.h is required"
|
56
|
-
|
57
|
-
# Explicitly look for the extension header in the parent directory
|
58
|
-
# because we want to consistently look for prism/extension.h in our
|
59
|
-
# source files to line up with our mirroring in CRuby.
|
60
|
-
find_header("prism/extension.h", File.join(__dir__, "..")) or raise "prism/extension.h is required"
|
61
|
-
end
|
62
|
-
|
63
|
-
def build_shared_rubyparser
|
64
|
-
build_target_rubyparser "build/librubyparser.#{RbConfig::CONFIG["SOEXT"]}"
|
65
|
-
end
|
66
|
-
|
67
|
-
def build_static_rubyparser
|
68
|
-
build_target_rubyparser "build/librubyparser.a"
|
69
|
-
end
|
70
|
-
|
71
|
-
def build_target_rubyparser(target)
|
72
|
-
Dir.chdir(root_dir) do
|
73
|
-
if !File.exist?("include/prism/ast.h") && Dir.exist?(".git")
|
74
|
-
# this block only exists to support building the gem from a "git" source,
|
75
|
-
# normally we package up the configure and other files in the gem itself
|
76
|
-
system("templates/template.rb", exception: true)
|
77
|
-
end
|
78
|
-
system("make", target, exception: true)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def root_dir
|
83
|
-
File.expand_path("../..", __dir__)
|
84
|
-
end
|
85
|
-
|
86
|
-
def include_dir
|
87
|
-
File.join(root_dir, "include")
|
88
|
-
end
|
89
|
-
|
90
|
-
def build_dir
|
91
|
-
File.join(root_dir, "build")
|
92
|
-
end
|
93
|
-
|
94
|
-
def print_help
|
95
|
-
print(<<~TEXT)
|
96
|
-
USAGE: ruby #{$PROGRAM_NAME} [options]
|
97
|
-
|
98
|
-
Flags that are always valid:
|
99
|
-
|
100
|
-
--enable-static
|
101
|
-
--disable-static
|
102
|
-
Enable or disable static linking against librubyparser.
|
103
|
-
The default is to statically link.
|
104
|
-
|
105
|
-
--enable-debug-mode-build
|
106
|
-
Enable debug mode build.
|
107
|
-
You may also use set PRISM_DEBUG_MODE_BUILD environment variable.
|
108
|
-
|
109
|
-
--help
|
110
|
-
Display this message.
|
111
|
-
|
112
|
-
Environment variables used:
|
113
|
-
|
114
|
-
PRISM_DEBUG_MODE_BUILD
|
115
|
-
Equivalent to `--enable-debug-mode-build` when set, even if nil or blank.
|
116
|
-
|
117
|
-
TEXT
|
118
|
-
end
|
119
|
-
|
120
|
-
def static_link?
|
121
|
-
enable_config("static", true)
|
122
|
-
end
|
123
|
-
|
124
|
-
def debug_mode_build?
|
125
|
-
enable_config("debug-mode-build", ENV["PRISM_DEBUG_MODE_BUILD"] || false)
|
126
|
-
end
|
21
|
+
TEXT
|
22
|
+
exit!(0)
|
23
|
+
end
|
24
|
+
|
25
|
+
# If this gem is being build from a git source, then we need to run
|
26
|
+
# templating if it hasn't been run yet. In normal packaging, we would have
|
27
|
+
# shipped the templated files with the gem, so this wouldn't be necessary.
|
28
|
+
def generate_templates
|
29
|
+
Dir.chdir(File.expand_path("../..", __dir__)) do
|
30
|
+
if !File.exist?("include/prism/ast.h") && Dir.exist?(".git")
|
31
|
+
system("templates/template.rb", exception: true)
|
127
32
|
end
|
128
33
|
end
|
129
34
|
end
|
130
35
|
|
131
|
-
|
132
|
-
|
133
|
-
|
36
|
+
# Runs `make` in the root directory of the project. Note that this is the
|
37
|
+
# `Makefile` for the overall project, not the `Makefile` that is being generated
|
38
|
+
# by this script.`
|
39
|
+
def make(target)
|
40
|
+
Dir.chdir(File.expand_path("../..", __dir__)) do
|
41
|
+
system("make", target, exception: true)
|
42
|
+
end
|
134
43
|
end
|
135
44
|
|
136
|
-
|
45
|
+
require "rbconfig"
|
46
|
+
|
47
|
+
# On non-CRuby we only need the shared library since we'll interface with it
|
48
|
+
# through FFI, so we'll build only that and not the C extension. We also avoid
|
49
|
+
# `require "mkmf"` as that prepends the LLVM toolchain to PATH on TruffleRuby,
|
50
|
+
# but we want to use the native toolchain here since libprism is run natively.
|
51
|
+
if RUBY_ENGINE != "ruby"
|
52
|
+
generate_templates
|
53
|
+
make("build/libprism.#{RbConfig::CONFIG["SOEXT"]}")
|
54
|
+
File.write("Makefile", "all install clean:\n\t@#{RbConfig::CONFIG["NULLCMD"]}\n")
|
55
|
+
return
|
56
|
+
end
|
57
|
+
|
58
|
+
require "mkmf"
|
59
|
+
|
60
|
+
# First, ensure that we can find the header for the prism library.
|
61
|
+
generate_templates # Templates should be generated before find_header.
|
62
|
+
unless find_header("prism.h", File.expand_path("../../include", __dir__))
|
63
|
+
raise "prism.h is required"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Next, ensure we can find the header for the C extension. Explicitly look for
|
67
|
+
# the extension header in the parent directory because we want to consistently
|
68
|
+
# look for `prism/extension.h` in our source files to line up with our mirroring
|
69
|
+
# in CRuby.
|
70
|
+
unless find_header("prism/extension.h", File.expand_path("..", __dir__))
|
71
|
+
raise "prism/extension.h is required"
|
72
|
+
end
|
73
|
+
|
74
|
+
# If `--enable-debug-mode-build` is passed to this script or the
|
75
|
+
# `PRISM_DEBUG_MODE_BUILD` environment variable is defined, we'll build with the
|
76
|
+
# `PRISM_DEBUG_MODE_BUILD` macro defined. This causes parse functions to
|
77
|
+
# duplicate their input so that they have clearly set bounds, which is useful
|
78
|
+
# for finding bugs that cause the parser to read off the end of the input.
|
79
|
+
if enable_config("debug-mode-build", ENV["PRISM_DEBUG_MODE_BUILD"] || false)
|
80
|
+
append_cflags("-DPRISM_DEBUG_MODE_BUILD")
|
81
|
+
end
|
82
|
+
|
83
|
+
# By default, all symbols are hidden in the shared library.
|
84
|
+
append_cflags("-fvisibility=hidden")
|
85
|
+
|
86
|
+
# We need to link against the libprism.a archive, which is built by the
|
87
|
+
# project's `Makefile`. We'll build it if it doesn't exist yet, and then add it
|
88
|
+
# to `mkmf`'s list of local libraries.
|
89
|
+
archive_target = "build/libprism.a"
|
90
|
+
archive_path = File.expand_path("../../#{archive_target}", __dir__)
|
91
|
+
|
92
|
+
make(archive_target) unless File.exist?(archive_path)
|
93
|
+
$LOCAL_LIBS << " #{archive_path}"
|
94
|
+
|
95
|
+
# Finally, we'll create the `Makefile` that is going to be used to configure and
|
96
|
+
# build the C extension.
|
97
|
+
create_makefile("prism/prism")
|
98
|
+
|
99
|
+
# Now that the `Makefile` for the C extension is built, we'll append on an extra
|
100
|
+
# rule that dictates that the extension should be rebuilt if the archive is
|
101
|
+
# updated.
|
102
|
+
File.open("Makefile", "a") do |mf|
|
103
|
+
mf.puts
|
104
|
+
mf.puts("# Automatically rebuild the extension if libprism.a changed")
|
105
|
+
mf.puts("$(TARGET_SO): $(LOCAL_LIBS)")
|
106
|
+
end
|
data/ext/prism/extension.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#include "prism/extension.h"
|
2
2
|
|
3
3
|
// NOTE: this file should contain only bindings. All non-trivial logic should be
|
4
|
-
// in
|
4
|
+
// in libprism so it can be shared its the various callers.
|
5
5
|
|
6
6
|
VALUE rb_cPrism;
|
7
7
|
VALUE rb_cPrismNode;
|
@@ -12,7 +12,6 @@ VALUE rb_cPrismLocation;
|
|
12
12
|
VALUE rb_cPrismComment;
|
13
13
|
VALUE rb_cPrismInlineComment;
|
14
14
|
VALUE rb_cPrismEmbDocComment;
|
15
|
-
VALUE rb_cPrismDATAComment;
|
16
15
|
VALUE rb_cPrismMagicComment;
|
17
16
|
VALUE rb_cPrismParseError;
|
18
17
|
VALUE rb_cPrismParseWarning;
|
@@ -127,7 +126,7 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
|
|
127
126
|
} else if (key_id == rb_option_id_encoding) {
|
128
127
|
if (!NIL_P(value)) pm_options_encoding_set(options, rb_enc_name(rb_to_encoding(value)));
|
129
128
|
} else if (key_id == rb_option_id_line) {
|
130
|
-
if (!NIL_P(value)) pm_options_line_set(options,
|
129
|
+
if (!NIL_P(value)) pm_options_line_set(options, NUM2INT(value));
|
131
130
|
} else if (key_id == rb_option_id_frozen_string_literal) {
|
132
131
|
if (!NIL_P(value)) pm_options_frozen_string_literal_set(options, value == Qtrue);
|
133
132
|
} else if (key_id == rb_option_id_verbose) {
|
@@ -167,6 +166,7 @@ build_options(VALUE argument) {
|
|
167
166
|
*/
|
168
167
|
static void
|
169
168
|
extract_options(pm_options_t *options, VALUE filepath, VALUE keywords) {
|
169
|
+
options->line = 1; // default
|
170
170
|
if (!NIL_P(keywords)) {
|
171
171
|
struct build_options_data data = { .options = options, .keywords = keywords };
|
172
172
|
struct build_options_data *argument = &data;
|
@@ -316,26 +316,11 @@ parser_comments(pm_parser_t *parser, VALUE source) {
|
|
316
316
|
for (pm_comment_t *comment = (pm_comment_t *) parser->comment_list.head; comment != NULL; comment = (pm_comment_t *) comment->node.next) {
|
317
317
|
VALUE location_argv[] = {
|
318
318
|
source,
|
319
|
-
LONG2FIX(comment->start - parser->start),
|
320
|
-
LONG2FIX(comment->end - comment->start)
|
319
|
+
LONG2FIX(comment->location.start - parser->start),
|
320
|
+
LONG2FIX(comment->location.end - comment->location.start)
|
321
321
|
};
|
322
322
|
|
323
|
-
VALUE type;
|
324
|
-
switch (comment->type) {
|
325
|
-
case PM_COMMENT_INLINE:
|
326
|
-
type = rb_cPrismInlineComment;
|
327
|
-
break;
|
328
|
-
case PM_COMMENT_EMBDOC:
|
329
|
-
type = rb_cPrismEmbDocComment;
|
330
|
-
break;
|
331
|
-
case PM_COMMENT___END__:
|
332
|
-
type = rb_cPrismDATAComment;
|
333
|
-
break;
|
334
|
-
default:
|
335
|
-
type = rb_cPrismInlineComment;
|
336
|
-
break;
|
337
|
-
}
|
338
|
-
|
323
|
+
VALUE type = (comment->type == PM_COMMENT_EMBDOC) ? rb_cPrismEmbDocComment : rb_cPrismInlineComment;
|
339
324
|
VALUE comment_argv[] = { rb_class_new_instance(3, location_argv, rb_cPrismLocation) };
|
340
325
|
rb_ary_push(comments, rb_class_new_instance(1, comment_argv, type));
|
341
326
|
}
|
@@ -374,6 +359,25 @@ parser_magic_comments(pm_parser_t *parser, VALUE source) {
|
|
374
359
|
return magic_comments;
|
375
360
|
}
|
376
361
|
|
362
|
+
/**
|
363
|
+
* Extract out the data location from the parser into a Location instance if one
|
364
|
+
* exists.
|
365
|
+
*/
|
366
|
+
static VALUE
|
367
|
+
parser_data_loc(const pm_parser_t *parser, VALUE source) {
|
368
|
+
if (parser->data_loc.end == NULL) {
|
369
|
+
return Qnil;
|
370
|
+
} else {
|
371
|
+
VALUE argv[] = {
|
372
|
+
source,
|
373
|
+
LONG2FIX(parser->data_loc.start - parser->start),
|
374
|
+
LONG2FIX(parser->data_loc.end - parser->data_loc.start)
|
375
|
+
};
|
376
|
+
|
377
|
+
return rb_class_new_instance(3, argv, rb_cPrismLocation);
|
378
|
+
}
|
379
|
+
}
|
380
|
+
|
377
381
|
/**
|
378
382
|
* Extract the errors out of the parser into an array.
|
379
383
|
*/
|
@@ -385,8 +389,8 @@ parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
|
|
385
389
|
for (error = (pm_diagnostic_t *) parser->error_list.head; error != NULL; error = (pm_diagnostic_t *) error->node.next) {
|
386
390
|
VALUE location_argv[] = {
|
387
391
|
source,
|
388
|
-
LONG2FIX(error->start - parser->start),
|
389
|
-
LONG2FIX(error->end - error->start)
|
392
|
+
LONG2FIX(error->location.start - parser->start),
|
393
|
+
LONG2FIX(error->location.end - error->location.start)
|
390
394
|
};
|
391
395
|
|
392
396
|
VALUE error_argv[] = {
|
@@ -411,8 +415,8 @@ parser_warnings(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
|
|
411
415
|
for (warning = (pm_diagnostic_t *) parser->warning_list.head; warning != NULL; warning = (pm_diagnostic_t *) warning->node.next) {
|
412
416
|
VALUE location_argv[] = {
|
413
417
|
source,
|
414
|
-
LONG2FIX(warning->start - parser->start),
|
415
|
-
LONG2FIX(warning->end - warning->start)
|
418
|
+
LONG2FIX(warning->location.start - parser->start),
|
419
|
+
LONG2FIX(warning->location.end - warning->location.start)
|
416
420
|
};
|
417
421
|
|
418
422
|
VALUE warning_argv[] = {
|
@@ -465,7 +469,7 @@ parse_lex_token(void *data, pm_parser_t *parser, pm_token_t *token) {
|
|
465
469
|
static void
|
466
470
|
parse_lex_encoding_changed_callback(pm_parser_t *parser) {
|
467
471
|
parse_lex_data_t *parse_lex_data = (parse_lex_data_t *) parser->lex_callback->data;
|
468
|
-
parse_lex_data->encoding = rb_enc_find(parser->encoding
|
472
|
+
parse_lex_data->encoding = rb_enc_find(parser->encoding->name);
|
469
473
|
|
470
474
|
// Since the encoding changed, we need to go back and change the encoding of
|
471
475
|
// the tokens that were already lexed. This is only going to end up being
|
@@ -531,6 +535,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
|
|
531
535
|
value,
|
532
536
|
parser_comments(&parser, source),
|
533
537
|
parser_magic_comments(&parser, source),
|
538
|
+
parser_data_loc(&parser, source),
|
534
539
|
parser_errors(&parser, parse_lex_data.encoding, source),
|
535
540
|
parser_warnings(&parser, parse_lex_data.encoding, source),
|
536
541
|
source
|
@@ -538,7 +543,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
|
|
538
543
|
|
539
544
|
pm_node_destroy(&parser, node);
|
540
545
|
pm_parser_free(&parser);
|
541
|
-
return rb_class_new_instance(
|
546
|
+
return rb_class_new_instance(7, result_argv, rb_cPrismParseResult);
|
542
547
|
}
|
543
548
|
|
544
549
|
/**
|
@@ -594,19 +599,20 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
|
|
594
599
|
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
|
595
600
|
|
596
601
|
pm_node_t *node = pm_parse(&parser);
|
597
|
-
rb_encoding *encoding = rb_enc_find(parser.encoding
|
602
|
+
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
|
598
603
|
|
599
604
|
VALUE source = pm_source_new(&parser, encoding);
|
600
605
|
VALUE result_argv[] = {
|
601
606
|
pm_ast_new(&parser, node, encoding),
|
602
607
|
parser_comments(&parser, source),
|
603
608
|
parser_magic_comments(&parser, source),
|
609
|
+
parser_data_loc(&parser, source),
|
604
610
|
parser_errors(&parser, encoding, source),
|
605
611
|
parser_warnings(&parser, encoding, source),
|
606
612
|
source
|
607
613
|
};
|
608
614
|
|
609
|
-
VALUE result = rb_class_new_instance(
|
615
|
+
VALUE result = rb_class_new_instance(7, result_argv, rb_cPrismParseResult);
|
610
616
|
|
611
617
|
pm_node_destroy(&parser, node);
|
612
618
|
pm_parser_free(&parser);
|
@@ -687,7 +693,7 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) {
|
|
687
693
|
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
|
688
694
|
|
689
695
|
pm_node_t *node = pm_parse(&parser);
|
690
|
-
rb_encoding *encoding = rb_enc_find(parser.encoding
|
696
|
+
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
|
691
697
|
|
692
698
|
VALUE source = pm_source_new(&parser, encoding);
|
693
699
|
VALUE comments = parser_comments(&parser, source);
|
@@ -792,6 +798,63 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) {
|
|
792
798
|
return value;
|
793
799
|
}
|
794
800
|
|
801
|
+
/**
|
802
|
+
* Parse the given input and return true if it parses without errors.
|
803
|
+
*/
|
804
|
+
static VALUE
|
805
|
+
parse_input_success_p(pm_string_t *input, const pm_options_t *options) {
|
806
|
+
pm_parser_t parser;
|
807
|
+
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
|
808
|
+
|
809
|
+
pm_node_t *node = pm_parse(&parser);
|
810
|
+
pm_node_destroy(&parser, node);
|
811
|
+
|
812
|
+
VALUE result = parser.error_list.size == 0 ? Qtrue : Qfalse;
|
813
|
+
pm_parser_free(&parser);
|
814
|
+
|
815
|
+
return result;
|
816
|
+
}
|
817
|
+
|
818
|
+
/**
|
819
|
+
* call-seq:
|
820
|
+
* Prism::parse_success?(source, **options) -> Array
|
821
|
+
*
|
822
|
+
* Parse the given string and return true if it parses without errors. For
|
823
|
+
* supported options, see Prism::parse.
|
824
|
+
*/
|
825
|
+
static VALUE
|
826
|
+
parse_success_p(int argc, VALUE *argv, VALUE self) {
|
827
|
+
pm_string_t input;
|
828
|
+
pm_options_t options = { 0 };
|
829
|
+
string_options(argc, argv, &input, &options);
|
830
|
+
|
831
|
+
VALUE result = parse_input_success_p(&input, &options);
|
832
|
+
pm_string_free(&input);
|
833
|
+
pm_options_free(&options);
|
834
|
+
|
835
|
+
return result;
|
836
|
+
}
|
837
|
+
|
838
|
+
/**
|
839
|
+
* call-seq:
|
840
|
+
* Prism::parse_file_success?(filepath, **options) -> Array
|
841
|
+
*
|
842
|
+
* Parse the given file and return true if it parses without errors. For
|
843
|
+
* supported options, see Prism::parse.
|
844
|
+
*/
|
845
|
+
static VALUE
|
846
|
+
parse_file_success_p(int argc, VALUE *argv, VALUE self) {
|
847
|
+
pm_string_t input;
|
848
|
+
pm_options_t options = { 0 };
|
849
|
+
if (!file_options(argc, argv, &input, &options)) return Qnil;
|
850
|
+
|
851
|
+
VALUE result = parse_input_success_p(&input, &options);
|
852
|
+
pm_string_free(&input);
|
853
|
+
pm_options_free(&options);
|
854
|
+
|
855
|
+
return result;
|
856
|
+
}
|
857
|
+
|
795
858
|
/******************************************************************************/
|
796
859
|
/* Utility functions exposed to make testing easier */
|
797
860
|
/******************************************************************************/
|
@@ -808,7 +871,7 @@ static VALUE
|
|
808
871
|
named_captures(VALUE self, VALUE source) {
|
809
872
|
pm_string_list_t string_list = { 0 };
|
810
873
|
|
811
|
-
if (!pm_regexp_named_capture_group_names((const uint8_t *) RSTRING_PTR(source), RSTRING_LEN(source), &string_list, false,
|
874
|
+
if (!pm_regexp_named_capture_group_names((const uint8_t *) RSTRING_PTR(source), RSTRING_LEN(source), &string_list, false, PM_ENCODING_UTF_8_ENTRY)) {
|
812
875
|
pm_string_list_free(&string_list);
|
813
876
|
return Qnil;
|
814
877
|
}
|
@@ -898,7 +961,7 @@ inspect_node(VALUE self, VALUE source) {
|
|
898
961
|
|
899
962
|
pm_prettyprint(&buffer, &parser, node);
|
900
963
|
|
901
|
-
rb_encoding *encoding = rb_enc_find(parser.encoding
|
964
|
+
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
|
902
965
|
VALUE string = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding);
|
903
966
|
|
904
967
|
pm_buffer_free(&buffer);
|
@@ -938,7 +1001,6 @@ Init_prism(void) {
|
|
938
1001
|
rb_cPrismComment = rb_define_class_under(rb_cPrism, "Comment", rb_cObject);
|
939
1002
|
rb_cPrismInlineComment = rb_define_class_under(rb_cPrism, "InlineComment", rb_cPrismComment);
|
940
1003
|
rb_cPrismEmbDocComment = rb_define_class_under(rb_cPrism, "EmbDocComment", rb_cPrismComment);
|
941
|
-
rb_cPrismDATAComment = rb_define_class_under(rb_cPrism, "DATAComment", rb_cPrismComment);
|
942
1004
|
rb_cPrismMagicComment = rb_define_class_under(rb_cPrism, "MagicComment", rb_cObject);
|
943
1005
|
rb_cPrismParseError = rb_define_class_under(rb_cPrism, "ParseError", rb_cObject);
|
944
1006
|
rb_cPrismParseWarning = rb_define_class_under(rb_cPrism, "ParseWarning", rb_cObject);
|
@@ -976,6 +1038,8 @@ Init_prism(void) {
|
|
976
1038
|
rb_define_singleton_method(rb_cPrism, "parse_file_comments", parse_file_comments, -1);
|
977
1039
|
rb_define_singleton_method(rb_cPrism, "parse_lex", parse_lex, -1);
|
978
1040
|
rb_define_singleton_method(rb_cPrism, "parse_lex_file", parse_lex_file, -1);
|
1041
|
+
rb_define_singleton_method(rb_cPrism, "parse_success?", parse_success_p, -1);
|
1042
|
+
rb_define_singleton_method(rb_cPrism, "parse_file_success?", parse_file_success_p, -1);
|
979
1043
|
|
980
1044
|
// Next, the functions that will be called by the parser to perform various
|
981
1045
|
// internal tasks. We expose these to make them easier to test.
|