prism 1.5.1 → 1.6.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 +22 -1
- data/Makefile +2 -1
- data/README.md +1 -0
- data/config.yml +2 -1
- data/docs/design.md +2 -2
- data/docs/parser_translation.md +1 -1
- data/docs/releasing.md +5 -24
- data/ext/prism/extension.c +11 -2
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +31 -1
- data/include/prism/diagnostic.h +1 -0
- data/include/prism/version.h +3 -3
- data/lib/prism/ffi.rb +8 -2
- data/lib/prism/node.rb +1 -1
- data/lib/prism/polyfill/warn.rb +16 -22
- data/lib/prism/serialize.rb +3 -2
- data/lib/prism/translation/parser.rb +8 -1
- data/lib/prism/translation/ruby_parser.rb +1 -1
- data/lib/prism.rb +21 -0
- data/prism.gemspec +1 -1
- data/sig/prism.rbs +4 -0
- data/src/diagnostic.c +3 -1
- data/src/prism.c +130 -71
- data/src/util/pm_string.c +6 -8
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2ef507799374ba0281ff3d8ab78fc29f673b3fc213f695ae68c65cf0d38b4bcc
|
|
4
|
+
data.tar.gz: 7610a756cffd1aeb517f135446ae25360568cc00e6d78e748470469bd345463c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 539d064482f82c7fd85c7e8269b1c400fd576b20effbcb857636667ce8818367eea35446bc7ee2decf3cdde7171883e8aeaa154c2bf1b8d7f3c7fa5c12203f08
|
|
7
|
+
data.tar.gz: 59181adcac710bf7697b1dec0556eb306f9cf79d2b7492e0392d9698401dd3abb5a1406fc5d66d1c4d0acbd85d9ebf8e674683e9ec585d765216953f80a75297
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,25 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.6.0] - 2025-10-16
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Add support for passing `"current"` as the version option to `Prism.*` APIs.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Remove a compiler warning for a missing unsigned cast for a shift value.
|
|
18
|
+
|
|
19
|
+
## [1.5.2] - 2025-10-09
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Fix character literal forced encoding when a unicode escape sequence is used.
|
|
24
|
+
- Reject `1 if foo = bar baz`.
|
|
25
|
+
- Clear static literal flag on interpolated strings.
|
|
26
|
+
- Reject optional argument/endless method definition ambiguity.
|
|
27
|
+
|
|
9
28
|
## [1.5.1] - 2025-09-13
|
|
10
29
|
|
|
11
30
|
### Changed
|
|
@@ -676,7 +695,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
|
676
695
|
|
|
677
696
|
- 🎉 Initial release! 🎉
|
|
678
697
|
|
|
679
|
-
[unreleased]: https://github.com/ruby/prism/compare/v1.
|
|
698
|
+
[unreleased]: https://github.com/ruby/prism/compare/v1.6.0...HEAD
|
|
699
|
+
[1.6.0]: https://github.com/ruby/prism/compare/v1.5.2...v1.6.0
|
|
700
|
+
[1.5.2]: https://github.com/ruby/prism/compare/v1.5.1...v1.5.2
|
|
680
701
|
[1.5.1]: https://github.com/ruby/prism/compare/v1.5.0...v1.5.1
|
|
681
702
|
[1.5.0]: https://github.com/ruby/prism/compare/v1.4.0...v1.5.0
|
|
682
703
|
[1.4.0]: https://github.com/ruby/prism/compare/v1.3.0...v1.4.0
|
data/Makefile
CHANGED
|
@@ -15,6 +15,7 @@ CFLAGS := -g -O2 -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion
|
|
|
15
15
|
JAVA_WASM_CFLAGS := -g -Oz -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fPIC -fvisibility=hidden -Wimplicit-fallthrough $(JAVA_WASM_CFLAGS)
|
|
16
16
|
CC ?= cc
|
|
17
17
|
AR ?= ar
|
|
18
|
+
ARFLAGS ?= -r$(V0:1=v)
|
|
18
19
|
WASI_SDK_PATH := /opt/wasi-sdk
|
|
19
20
|
|
|
20
21
|
MAKEDIRS ?= mkdir -p
|
|
@@ -38,7 +39,7 @@ build/libprism.$(SOEXT): $(SHARED_OBJECTS)
|
|
|
38
39
|
|
|
39
40
|
build/libprism.a: $(STATIC_OBJECTS)
|
|
40
41
|
$(ECHO) "building $@ with $(AR)"
|
|
41
|
-
$(Q) $(AR) $(ARFLAGS) $@ $(STATIC_OBJECTS)
|
|
42
|
+
$(Q) $(AR) $(ARFLAGS) $@ $(STATIC_OBJECTS)
|
|
42
43
|
|
|
43
44
|
javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS)
|
|
44
45
|
$(ECHO) "building $@"
|
data/README.md
CHANGED
|
@@ -135,6 +135,7 @@ Prism has been integrated into the majority of Ruby runtimes, many libraries, an
|
|
|
135
135
|
* [sorbet-eraser](https://github.com/kddnewton/sorbet-eraser/pull/25)
|
|
136
136
|
* [synvert](https://github.com/xinminlabs/synvert-core-ruby)
|
|
137
137
|
* [typeprof](https://github.com/ruby/typeprof)
|
|
138
|
+
* [unparser](https://github.com/mbj/unparser) (via parser translator)
|
|
138
139
|
|
|
139
140
|
### Applications
|
|
140
141
|
|
data/config.yml
CHANGED
|
@@ -60,6 +60,7 @@ errors:
|
|
|
60
60
|
- CONDITIONAL_WHILE_PREDICATE
|
|
61
61
|
- CONSTANT_PATH_COLON_COLON_CONSTANT
|
|
62
62
|
- DEF_ENDLESS
|
|
63
|
+
- DEF_ENDLESS_PARAMETERS
|
|
63
64
|
- DEF_ENDLESS_SETTER
|
|
64
65
|
- DEF_NAME
|
|
65
66
|
- DEF_PARAMS_TERM
|
|
@@ -1800,7 +1801,7 @@ nodes:
|
|
|
1800
1801
|
Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
|
1801
1802
|
|
|
1802
1803
|
case true; when false; end
|
|
1803
|
-
|
|
1804
|
+
^^^^
|
|
1804
1805
|
- name: conditions
|
|
1805
1806
|
type: node[]
|
|
1806
1807
|
kind: WhenNode
|
data/docs/design.md
CHANGED
|
@@ -18,11 +18,11 @@ The templated files contain all of the code required to allocate and initialize
|
|
|
18
18
|
|
|
19
19
|
In order to provide the best possible error tolerance, the parser is hand-written. It is structured using Pratt parsing, a technique developed by Vaughan Pratt back in the 1970s. Below are a bunch of links to articles and papers that explain Pratt parsing in more detail.
|
|
20
20
|
|
|
21
|
-
* https://
|
|
21
|
+
* https://github.com/tdop/tdop.github.io/raw/master/original.pdf
|
|
22
22
|
* https://tdop.github.io/
|
|
23
23
|
* https://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
|
|
24
24
|
* https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
|
|
25
|
-
* https://chidiwilliams.com/
|
|
25
|
+
* https://chidiwilliams.com/posts/on-recursive-descent-and-pratt-parsing
|
|
26
26
|
|
|
27
27
|
You can find most of the functions that correspond to constructs in the Pratt parsing algorithm in `prism.c`. As a couple of examples:
|
|
28
28
|
|
data/docs/parser_translation.md
CHANGED
|
@@ -20,5 +20,5 @@ Prism::Translation::ParserCurrent.parse("puts 'Hello World!'")
|
|
|
20
20
|
|
|
21
21
|
All the parsers are autoloaded, so you don't have to worry about requiring them yourself.
|
|
22
22
|
|
|
23
|
-
If you also need to parse Ruby versions below 3.3 (which `prism`
|
|
23
|
+
If you also need to parse Ruby versions below 3.3 (for which the `prism` translation layer does not have explicit support), check out
|
|
24
24
|
[this guide](https://github.com/whitequark/parser/blob/master/doc/PRISM_TRANSLATION.md) from the `parser` gem on how to use both in conjunction.
|
data/docs/releasing.md
CHANGED
|
@@ -47,7 +47,10 @@ bundle install
|
|
|
47
47
|
* Update the version-specific lockfiles:
|
|
48
48
|
|
|
49
49
|
```sh
|
|
50
|
-
|
|
50
|
+
for VERSION in "2.7" "3.0" "3.1" "3.2" "3.3" "3.4"; do docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/$VERSION/Gemfile" "ruby:$VERSION" bundle update; done
|
|
51
|
+
docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/3.5/Gemfile" ruby:3.5.0-preview1 bundle update
|
|
52
|
+
docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/jruby/Gemfile" jruby:latest bundle update
|
|
53
|
+
BUNDLE_GEMFILE=gemfiles/truffleruby/Gemfile chruby-exec truffleruby -- bundle update
|
|
51
54
|
```
|
|
52
55
|
|
|
53
56
|
* Update the cargo lockfiles:
|
|
@@ -71,26 +74,4 @@ git push
|
|
|
71
74
|
## Publishing
|
|
72
75
|
|
|
73
76
|
* Update the GitHub release page with a copy of the latest entry in the `CHANGELOG.md` file.
|
|
74
|
-
*
|
|
75
|
-
|
|
76
|
-
```sh
|
|
77
|
-
bundle exec rake release
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
* Generate the `wasm` artifact (or download it from GitHub actions and put it in `javascript/src/prism.wasm`).
|
|
81
|
-
|
|
82
|
-
```sh
|
|
83
|
-
make wasm
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
* Publish the JavaScript package to [npmjs.com](npmjs.com). Note that you must have access to the `@ruby/prism` package to do this.
|
|
87
|
-
|
|
88
|
-
```sh
|
|
89
|
-
npm publish
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
* Publish the rust crate to [crates.io](crates.io). Note that you must have access to the `ruby-prism-sys` and `ruby-prism` crates to do this.
|
|
93
|
-
|
|
94
|
-
```sh
|
|
95
|
-
bundle exec rake cargo:publish:real
|
|
96
|
-
```
|
|
77
|
+
* Push a new tag to the GitHub repository, following the `vX.Y.Z` format.
|
data/ext/prism/extension.c
CHANGED
|
@@ -25,6 +25,7 @@ VALUE rb_cPrismLexResult;
|
|
|
25
25
|
VALUE rb_cPrismParseLexResult;
|
|
26
26
|
VALUE rb_cPrismStringQuery;
|
|
27
27
|
VALUE rb_cPrismScope;
|
|
28
|
+
VALUE rb_cPrismCurrentVersionError;
|
|
28
29
|
|
|
29
30
|
VALUE rb_cPrismDebugEncoding;
|
|
30
31
|
|
|
@@ -199,7 +200,13 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
|
|
|
199
200
|
if (!NIL_P(value)) {
|
|
200
201
|
const char *version = check_string(value);
|
|
201
202
|
|
|
202
|
-
if (
|
|
203
|
+
if (RSTRING_LEN(value) == 7 && strncmp(version, "current", 7) == 0) {
|
|
204
|
+
VALUE current_ruby_value = rb_const_get(rb_cObject, rb_intern("RUBY_VERSION"));
|
|
205
|
+
const char *current_version = RSTRING_PTR(current_ruby_value);
|
|
206
|
+
if (!pm_options_version_set(options, current_version, 3)) {
|
|
207
|
+
rb_exc_raise(rb_exc_new_str(rb_cPrismCurrentVersionError, current_ruby_value));
|
|
208
|
+
}
|
|
209
|
+
} else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
|
|
203
210
|
rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
|
|
204
211
|
}
|
|
205
212
|
}
|
|
@@ -888,7 +895,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
|
|
|
888
895
|
* version of Ruby syntax (which you can trigger with `nil` or
|
|
889
896
|
* `"latest"`). You may also restrict the syntax to a specific version of
|
|
890
897
|
* Ruby, e.g., with `"3.3.0"`. To parse with the same syntax version that
|
|
891
|
-
* the current Ruby is running use `version:
|
|
898
|
+
* the current Ruby is running use `version: "current"`. Raises
|
|
892
899
|
* ArgumentError if the version is not currently supported by Prism.
|
|
893
900
|
*/
|
|
894
901
|
static VALUE
|
|
@@ -1364,6 +1371,8 @@ Init_prism(void) {
|
|
|
1364
1371
|
rb_cPrismStringQuery = rb_define_class_under(rb_cPrism, "StringQuery", rb_cObject);
|
|
1365
1372
|
rb_cPrismScope = rb_define_class_under(rb_cPrism, "Scope", rb_cObject);
|
|
1366
1373
|
|
|
1374
|
+
rb_cPrismCurrentVersionError = rb_const_get(rb_cPrism, rb_intern("CurrentVersionError"));
|
|
1375
|
+
|
|
1367
1376
|
// Intern all of the IDs eagerly that we support so that we don't have to do
|
|
1368
1377
|
// it every time we parse.
|
|
1369
1378
|
rb_id_option_command_line = rb_intern_const("command_line");
|
data/ext/prism/extension.h
CHANGED
data/include/prism/ast.h
CHANGED
|
@@ -2638,7 +2638,7 @@ typedef struct pm_case_node {
|
|
|
2638
2638
|
* Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
|
2639
2639
|
*
|
|
2640
2640
|
* case true; when false; end
|
|
2641
|
-
*
|
|
2641
|
+
* ^^^^
|
|
2642
2642
|
*/
|
|
2643
2643
|
struct pm_node *predicate;
|
|
2644
2644
|
|
|
@@ -7990,6 +7990,8 @@ typedef enum pm_arguments_node_flags {
|
|
|
7990
7990
|
|
|
7991
7991
|
/** if the arguments contain multiple splats */
|
|
7992
7992
|
PM_ARGUMENTS_NODE_FLAGS_CONTAINS_MULTIPLE_SPLATS = 64,
|
|
7993
|
+
|
|
7994
|
+
PM_ARGUMENTS_NODE_FLAGS_LAST,
|
|
7993
7995
|
} pm_arguments_node_flags_t;
|
|
7994
7996
|
|
|
7995
7997
|
/**
|
|
@@ -7998,6 +8000,8 @@ typedef enum pm_arguments_node_flags {
|
|
|
7998
8000
|
typedef enum pm_array_node_flags {
|
|
7999
8001
|
/** if array contains splat nodes */
|
|
8000
8002
|
PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT = 4,
|
|
8003
|
+
|
|
8004
|
+
PM_ARRAY_NODE_FLAGS_LAST,
|
|
8001
8005
|
} pm_array_node_flags_t;
|
|
8002
8006
|
|
|
8003
8007
|
/**
|
|
@@ -8015,6 +8019,8 @@ typedef enum pm_call_node_flags {
|
|
|
8015
8019
|
|
|
8016
8020
|
/** a call that ignores method visibility */
|
|
8017
8021
|
PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY = 32,
|
|
8022
|
+
|
|
8023
|
+
PM_CALL_NODE_FLAGS_LAST,
|
|
8018
8024
|
} pm_call_node_flags_t;
|
|
8019
8025
|
|
|
8020
8026
|
/**
|
|
@@ -8026,6 +8032,8 @@ typedef enum pm_encoding_flags {
|
|
|
8026
8032
|
|
|
8027
8033
|
/** internal bytes forced the encoding to binary */
|
|
8028
8034
|
PM_ENCODING_FLAGS_FORCED_BINARY_ENCODING = 8,
|
|
8035
|
+
|
|
8036
|
+
PM_ENCODING_FLAGS_LAST,
|
|
8029
8037
|
} pm_encoding_flags_t;
|
|
8030
8038
|
|
|
8031
8039
|
/**
|
|
@@ -8043,6 +8051,8 @@ typedef enum pm_integer_base_flags {
|
|
|
8043
8051
|
|
|
8044
8052
|
/** 0x prefix */
|
|
8045
8053
|
PM_INTEGER_BASE_FLAGS_HEXADECIMAL = 32,
|
|
8054
|
+
|
|
8055
|
+
PM_INTEGER_BASE_FLAGS_LAST,
|
|
8046
8056
|
} pm_integer_base_flags_t;
|
|
8047
8057
|
|
|
8048
8058
|
/**
|
|
@@ -8054,6 +8064,8 @@ typedef enum pm_interpolated_string_node_flags {
|
|
|
8054
8064
|
|
|
8055
8065
|
/** mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` */
|
|
8056
8066
|
PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE = 8,
|
|
8067
|
+
|
|
8068
|
+
PM_INTERPOLATED_STRING_NODE_FLAGS_LAST,
|
|
8057
8069
|
} pm_interpolated_string_node_flags_t;
|
|
8058
8070
|
|
|
8059
8071
|
/**
|
|
@@ -8062,6 +8074,8 @@ typedef enum pm_interpolated_string_node_flags {
|
|
|
8062
8074
|
typedef enum pm_keyword_hash_node_flags {
|
|
8063
8075
|
/** a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments */
|
|
8064
8076
|
PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS = 4,
|
|
8077
|
+
|
|
8078
|
+
PM_KEYWORD_HASH_NODE_FLAGS_LAST,
|
|
8065
8079
|
} pm_keyword_hash_node_flags_t;
|
|
8066
8080
|
|
|
8067
8081
|
/**
|
|
@@ -8070,6 +8084,8 @@ typedef enum pm_keyword_hash_node_flags {
|
|
|
8070
8084
|
typedef enum pm_loop_flags {
|
|
8071
8085
|
/** a loop after a begin statement, so the body is executed first before the condition */
|
|
8072
8086
|
PM_LOOP_FLAGS_BEGIN_MODIFIER = 4,
|
|
8087
|
+
|
|
8088
|
+
PM_LOOP_FLAGS_LAST,
|
|
8073
8089
|
} pm_loop_flags_t;
|
|
8074
8090
|
|
|
8075
8091
|
/**
|
|
@@ -8078,6 +8094,8 @@ typedef enum pm_loop_flags {
|
|
|
8078
8094
|
typedef enum pm_parameter_flags {
|
|
8079
8095
|
/** a parameter name that has been repeated in the method signature */
|
|
8080
8096
|
PM_PARAMETER_FLAGS_REPEATED_PARAMETER = 4,
|
|
8097
|
+
|
|
8098
|
+
PM_PARAMETER_FLAGS_LAST,
|
|
8081
8099
|
} pm_parameter_flags_t;
|
|
8082
8100
|
|
|
8083
8101
|
/**
|
|
@@ -8086,6 +8104,8 @@ typedef enum pm_parameter_flags {
|
|
|
8086
8104
|
typedef enum pm_parentheses_node_flags {
|
|
8087
8105
|
/** parentheses that contain multiple potentially void statements */
|
|
8088
8106
|
PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS = 4,
|
|
8107
|
+
|
|
8108
|
+
PM_PARENTHESES_NODE_FLAGS_LAST,
|
|
8089
8109
|
} pm_parentheses_node_flags_t;
|
|
8090
8110
|
|
|
8091
8111
|
/**
|
|
@@ -8094,6 +8114,8 @@ typedef enum pm_parentheses_node_flags {
|
|
|
8094
8114
|
typedef enum pm_range_flags {
|
|
8095
8115
|
/** ... operator */
|
|
8096
8116
|
PM_RANGE_FLAGS_EXCLUDE_END = 4,
|
|
8117
|
+
|
|
8118
|
+
PM_RANGE_FLAGS_LAST,
|
|
8097
8119
|
} pm_range_flags_t;
|
|
8098
8120
|
|
|
8099
8121
|
/**
|
|
@@ -8132,6 +8154,8 @@ typedef enum pm_regular_expression_flags {
|
|
|
8132
8154
|
|
|
8133
8155
|
/** internal bytes forced the encoding to US-ASCII */
|
|
8134
8156
|
PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING = 4096,
|
|
8157
|
+
|
|
8158
|
+
PM_REGULAR_EXPRESSION_FLAGS_LAST,
|
|
8135
8159
|
} pm_regular_expression_flags_t;
|
|
8136
8160
|
|
|
8137
8161
|
/**
|
|
@@ -8146,6 +8170,8 @@ typedef enum pm_shareable_constant_node_flags {
|
|
|
8146
8170
|
|
|
8147
8171
|
/** constant writes that should be modified with shareable constant value experimental copy */
|
|
8148
8172
|
PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY = 16,
|
|
8173
|
+
|
|
8174
|
+
PM_SHAREABLE_CONSTANT_NODE_FLAGS_LAST,
|
|
8149
8175
|
} pm_shareable_constant_node_flags_t;
|
|
8150
8176
|
|
|
8151
8177
|
/**
|
|
@@ -8163,6 +8189,8 @@ typedef enum pm_string_flags {
|
|
|
8163
8189
|
|
|
8164
8190
|
/** mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` */
|
|
8165
8191
|
PM_STRING_FLAGS_MUTABLE = 32,
|
|
8192
|
+
|
|
8193
|
+
PM_STRING_FLAGS_LAST,
|
|
8166
8194
|
} pm_string_flags_t;
|
|
8167
8195
|
|
|
8168
8196
|
/**
|
|
@@ -8177,6 +8205,8 @@ typedef enum pm_symbol_flags {
|
|
|
8177
8205
|
|
|
8178
8206
|
/** internal bytes forced the encoding to US-ASCII */
|
|
8179
8207
|
PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING = 16,
|
|
8208
|
+
|
|
8209
|
+
PM_SYMBOL_FLAGS_LAST,
|
|
8180
8210
|
} pm_symbol_flags_t;
|
|
8181
8211
|
|
|
8182
8212
|
/**
|
data/include/prism/diagnostic.h
CHANGED
data/include/prism/version.h
CHANGED
|
@@ -14,16 +14,16 @@
|
|
|
14
14
|
/**
|
|
15
15
|
* The minor version of the Prism library as an int.
|
|
16
16
|
*/
|
|
17
|
-
#define PRISM_VERSION_MINOR
|
|
17
|
+
#define PRISM_VERSION_MINOR 6
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* The patch version of the Prism library as an int.
|
|
21
21
|
*/
|
|
22
|
-
#define PRISM_VERSION_PATCH
|
|
22
|
+
#define PRISM_VERSION_PATCH 0
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* The version of the Prism library as a constant string.
|
|
26
26
|
*/
|
|
27
|
-
#define PRISM_VERSION "1.
|
|
27
|
+
#define PRISM_VERSION "1.6.0"
|
|
28
28
|
|
|
29
29
|
#endif
|
data/lib/prism/ffi.rb
CHANGED
|
@@ -423,7 +423,9 @@ module Prism
|
|
|
423
423
|
|
|
424
424
|
# Return the value that should be dumped for the version option.
|
|
425
425
|
def dump_options_version(version)
|
|
426
|
-
|
|
426
|
+
current = version == "current"
|
|
427
|
+
|
|
428
|
+
case current ? RUBY_VERSION : version
|
|
427
429
|
when nil, "latest"
|
|
428
430
|
0 # Handled in pm_parser_init
|
|
429
431
|
when /\A3\.3(\.\d+)?\z/
|
|
@@ -433,7 +435,11 @@ module Prism
|
|
|
433
435
|
when /\A3\.5(\.\d+)?\z/
|
|
434
436
|
3
|
|
435
437
|
else
|
|
436
|
-
|
|
438
|
+
if current
|
|
439
|
+
raise CurrentVersionError, RUBY_VERSION
|
|
440
|
+
else
|
|
441
|
+
raise ArgumentError, "invalid version: #{version}"
|
|
442
|
+
end
|
|
437
443
|
end
|
|
438
444
|
end
|
|
439
445
|
|
data/lib/prism/node.rb
CHANGED
|
@@ -3732,7 +3732,7 @@ module Prism
|
|
|
3732
3732
|
# Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
|
3733
3733
|
#
|
|
3734
3734
|
# case true; when false; end
|
|
3735
|
-
#
|
|
3735
|
+
# ^^^^
|
|
3736
3736
|
attr_reader :predicate
|
|
3737
3737
|
|
|
3738
3738
|
# Represents the conditions of the case statement.
|
data/lib/prism/polyfill/warn.rb
CHANGED
|
@@ -7,17 +7,14 @@ if (method = Kernel.instance_method(:warn)).respond_to?(:parameters) ? method.pa
|
|
|
7
7
|
Kernel.prepend(
|
|
8
8
|
Module.new {
|
|
9
9
|
def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
|
|
10
|
-
uplevel
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
super(*msgs, uplevel: uplevel)
|
|
10
|
+
case uplevel
|
|
11
|
+
when nil
|
|
12
|
+
super(*msgs)
|
|
13
|
+
when Integer
|
|
14
|
+
super(*msgs, uplevel: uplevel + 1)
|
|
15
|
+
else
|
|
16
|
+
super(*msgs, uplevel: uplevel.to_int + 1)
|
|
17
|
+
end
|
|
21
18
|
end
|
|
22
19
|
}
|
|
23
20
|
)
|
|
@@ -25,17 +22,14 @@ if (method = Kernel.instance_method(:warn)).respond_to?(:parameters) ? method.pa
|
|
|
25
22
|
Object.prepend(
|
|
26
23
|
Module.new {
|
|
27
24
|
def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
|
|
28
|
-
uplevel
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
super(*msgs, uplevel: uplevel)
|
|
25
|
+
case uplevel
|
|
26
|
+
when nil
|
|
27
|
+
super(*msgs)
|
|
28
|
+
when Integer
|
|
29
|
+
super(*msgs, uplevel: uplevel + 1)
|
|
30
|
+
else
|
|
31
|
+
super(*msgs, uplevel: uplevel.to_int + 1)
|
|
32
|
+
end
|
|
39
33
|
end
|
|
40
34
|
}
|
|
41
35
|
)
|
data/lib/prism/serialize.rb
CHANGED
|
@@ -21,11 +21,11 @@ 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 =
|
|
24
|
+
MINOR_VERSION = 6
|
|
25
25
|
|
|
26
26
|
# The patch version of prism that we are expecting to find in the serialized
|
|
27
27
|
# strings.
|
|
28
|
-
PATCH_VERSION =
|
|
28
|
+
PATCH_VERSION = 0
|
|
29
29
|
|
|
30
30
|
# Deserialize the dumped output from a request to parse or parse_file.
|
|
31
31
|
#
|
|
@@ -397,6 +397,7 @@ module Prism
|
|
|
397
397
|
:conditional_while_predicate,
|
|
398
398
|
:constant_path_colon_colon_constant,
|
|
399
399
|
:def_endless,
|
|
400
|
+
:def_endless_parameters,
|
|
400
401
|
:def_endless_setter,
|
|
401
402
|
:def_name,
|
|
402
403
|
:def_params_term,
|
|
@@ -19,6 +19,13 @@ module Prism
|
|
|
19
19
|
# whitequark/parser gem's syntax tree. It inherits from the base parser for
|
|
20
20
|
# the parser gem, and overrides the parse* methods to parse with prism and
|
|
21
21
|
# then translate.
|
|
22
|
+
#
|
|
23
|
+
# Note that this version of the parser always parses using the latest
|
|
24
|
+
# version of Ruby syntax supported by Prism. If you want specific version
|
|
25
|
+
# support, use one of the version-specific subclasses, such as
|
|
26
|
+
# `Prism::Translation::Parser34`. If you want to parse using the same
|
|
27
|
+
# version of Ruby syntax as the currently running version of Ruby, use
|
|
28
|
+
# `Prism::Translation::ParserCurrent`.
|
|
22
29
|
class Parser < ::Parser::Base
|
|
23
30
|
Diagnostic = ::Parser::Diagnostic # :nodoc:
|
|
24
31
|
private_constant :Diagnostic
|
|
@@ -77,7 +84,7 @@ module Prism
|
|
|
77
84
|
end
|
|
78
85
|
|
|
79
86
|
def version # :nodoc:
|
|
80
|
-
|
|
87
|
+
35
|
|
81
88
|
end
|
|
82
89
|
|
|
83
90
|
# The default encoding for Ruby files is UTF-8.
|
data/lib/prism.rb
CHANGED
|
@@ -37,6 +37,27 @@ module Prism
|
|
|
37
37
|
private_constant :LexCompat
|
|
38
38
|
private_constant :LexRipper
|
|
39
39
|
|
|
40
|
+
# Raised when requested to parse as the currently running Ruby version but Prism has no support for it.
|
|
41
|
+
class CurrentVersionError < ArgumentError
|
|
42
|
+
# Initialize a new exception for the given ruby version string.
|
|
43
|
+
def initialize(version)
|
|
44
|
+
message = +"invalid version: Requested to parse as `version: 'current'`; "
|
|
45
|
+
gem_version =
|
|
46
|
+
begin
|
|
47
|
+
Gem::Version.new(version)
|
|
48
|
+
rescue ArgumentError
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if gem_version && gem_version < Gem::Version.new("3.3.0")
|
|
52
|
+
message << " #{version} is below the minimum supported syntax."
|
|
53
|
+
else
|
|
54
|
+
message << " #{version} is unknown. Please update the `prism` gem."
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
super(message)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
40
61
|
# :call-seq:
|
|
41
62
|
# Prism::lex_compat(source, **options) -> LexCompat::Result
|
|
42
63
|
#
|
data/prism.gemspec
CHANGED
data/sig/prism.rbs
CHANGED
data/src/diagnostic.c
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
#include "prism/diagnostic.h"
|
|
12
12
|
|
|
13
|
-
#define PM_DIAGNOSTIC_ID_MAX
|
|
13
|
+
#define PM_DIAGNOSTIC_ID_MAX 322
|
|
14
14
|
|
|
15
15
|
/** This struct holds the data for each diagnostic. */
|
|
16
16
|
typedef struct {
|
|
@@ -154,6 +154,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
|
|
|
154
154
|
[PM_ERR_CONDITIONAL_WHILE_PREDICATE] = { "expected a predicate expression for the `while` statement", PM_ERROR_LEVEL_SYNTAX },
|
|
155
155
|
[PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT] = { "expected a constant after the `::` operator", PM_ERROR_LEVEL_SYNTAX },
|
|
156
156
|
[PM_ERR_DEF_ENDLESS] = { "could not parse the endless method body", PM_ERROR_LEVEL_SYNTAX },
|
|
157
|
+
[PM_ERR_DEF_ENDLESS_PARAMETERS] = { "could not parse the endless method parameters", PM_ERROR_LEVEL_SYNTAX },
|
|
157
158
|
[PM_ERR_DEF_ENDLESS_SETTER] = { "invalid method name; a setter method cannot be defined in an endless method definition", PM_ERROR_LEVEL_SYNTAX },
|
|
158
159
|
[PM_ERR_DEF_NAME] = { "unexpected %s; expected a method name", PM_ERROR_LEVEL_SYNTAX },
|
|
159
160
|
[PM_ERR_DEF_PARAMS_TERM] = { "expected a delimiter to close the parameters", PM_ERROR_LEVEL_SYNTAX },
|
|
@@ -482,6 +483,7 @@ pm_diagnostic_id_human(pm_diagnostic_id_t diag_id) {
|
|
|
482
483
|
case PM_ERR_CONDITIONAL_WHILE_PREDICATE: return "conditional_while_predicate";
|
|
483
484
|
case PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT: return "constant_path_colon_colon_constant";
|
|
484
485
|
case PM_ERR_DEF_ENDLESS: return "def_endless";
|
|
486
|
+
case PM_ERR_DEF_ENDLESS_PARAMETERS: return "def_endless_parameters";
|
|
485
487
|
case PM_ERR_DEF_ENDLESS_SETTER: return "def_endless_setter";
|
|
486
488
|
case PM_ERR_DEF_NAME: return "def_name";
|
|
487
489
|
case PM_ERR_DEF_PARAMS_TERM: return "def_params_term";
|
data/src/prism.c
CHANGED
|
@@ -2622,10 +2622,11 @@ pm_break_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument
|
|
|
2622
2622
|
// There are certain flags that we want to use internally but don't want to
|
|
2623
2623
|
// expose because they are not relevant beyond parsing. Therefore we'll define
|
|
2624
2624
|
// them here and not define them in config.yml/a header file.
|
|
2625
|
-
static const pm_node_flags_t PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY =
|
|
2626
|
-
|
|
2627
|
-
static const pm_node_flags_t
|
|
2628
|
-
static const pm_node_flags_t
|
|
2625
|
+
static const pm_node_flags_t PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY = (1 << 2);
|
|
2626
|
+
|
|
2627
|
+
static const pm_node_flags_t PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY = ((PM_CALL_NODE_FLAGS_LAST - 1) << 1);
|
|
2628
|
+
static const pm_node_flags_t PM_CALL_NODE_FLAGS_COMPARISON = ((PM_CALL_NODE_FLAGS_LAST - 1) << 2);
|
|
2629
|
+
static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = ((PM_CALL_NODE_FLAGS_LAST - 1) << 3);
|
|
2629
2630
|
|
|
2630
2631
|
/**
|
|
2631
2632
|
* Allocate and initialize a new CallNode node. This sets everything to NULL or
|
|
@@ -5279,6 +5280,12 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_
|
|
|
5279
5280
|
|
|
5280
5281
|
switch (PM_NODE_TYPE(part)) {
|
|
5281
5282
|
case PM_STRING_NODE:
|
|
5283
|
+
// If inner string is not frozen, it stops being a static literal. We should *not* clear other flags,
|
|
5284
|
+
// because concatenating two frozen strings (`'foo' 'bar'`) is still frozen. This holds true for
|
|
5285
|
+
// as long as this interpolation only consists of other string literals.
|
|
5286
|
+
if (!PM_NODE_FLAG_P(part, PM_STRING_FLAGS_FROZEN)) {
|
|
5287
|
+
pm_node_flag_unset((pm_node_t *) node, PM_NODE_FLAG_STATIC_LITERAL);
|
|
5288
|
+
}
|
|
5282
5289
|
part->flags = (pm_node_flags_t) ((part->flags | PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN) & ~PM_STRING_FLAGS_MUTABLE);
|
|
5283
5290
|
break;
|
|
5284
5291
|
case PM_INTERPOLATED_STRING_NODE:
|
|
@@ -8584,64 +8591,64 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
|
|
|
8584
8591
|
|
|
8585
8592
|
static const uint32_t context_terminators[] = {
|
|
8586
8593
|
[PM_CONTEXT_NONE] = 0,
|
|
8587
|
-
[PM_CONTEXT_BEGIN] = (
|
|
8588
|
-
[PM_CONTEXT_BEGIN_ENSURE] = (
|
|
8589
|
-
[PM_CONTEXT_BEGIN_ELSE] = (
|
|
8590
|
-
[PM_CONTEXT_BEGIN_RESCUE] = (
|
|
8591
|
-
[PM_CONTEXT_BLOCK_BRACES] = (
|
|
8592
|
-
[PM_CONTEXT_BLOCK_KEYWORDS] = (
|
|
8593
|
-
[PM_CONTEXT_BLOCK_ENSURE] = (
|
|
8594
|
-
[PM_CONTEXT_BLOCK_ELSE] = (
|
|
8595
|
-
[PM_CONTEXT_BLOCK_RESCUE] = (
|
|
8596
|
-
[PM_CONTEXT_CASE_WHEN] = (
|
|
8597
|
-
[PM_CONTEXT_CASE_IN] = (
|
|
8598
|
-
[PM_CONTEXT_CLASS] = (
|
|
8599
|
-
[PM_CONTEXT_CLASS_ENSURE] = (
|
|
8600
|
-
[PM_CONTEXT_CLASS_ELSE] = (
|
|
8601
|
-
[PM_CONTEXT_CLASS_RESCUE] = (
|
|
8602
|
-
[PM_CONTEXT_DEF] = (
|
|
8603
|
-
[PM_CONTEXT_DEF_ENSURE] = (
|
|
8604
|
-
[PM_CONTEXT_DEF_ELSE] = (
|
|
8605
|
-
[PM_CONTEXT_DEF_RESCUE] = (
|
|
8606
|
-
[PM_CONTEXT_DEF_PARAMS] = (
|
|
8607
|
-
[PM_CONTEXT_DEFINED] = (
|
|
8608
|
-
[PM_CONTEXT_DEFAULT_PARAMS] = (
|
|
8609
|
-
[PM_CONTEXT_ELSE] = (
|
|
8610
|
-
[PM_CONTEXT_ELSIF] = (
|
|
8611
|
-
[PM_CONTEXT_EMBEXPR] = (
|
|
8612
|
-
[PM_CONTEXT_FOR] = (
|
|
8613
|
-
[PM_CONTEXT_FOR_INDEX] = (
|
|
8614
|
-
[PM_CONTEXT_IF] = (
|
|
8615
|
-
[PM_CONTEXT_LAMBDA_BRACES] = (
|
|
8616
|
-
[PM_CONTEXT_LAMBDA_DO_END] = (
|
|
8617
|
-
[PM_CONTEXT_LAMBDA_ENSURE] = (
|
|
8618
|
-
[PM_CONTEXT_LAMBDA_ELSE] = (
|
|
8619
|
-
[PM_CONTEXT_LAMBDA_RESCUE] = (
|
|
8620
|
-
[PM_CONTEXT_LOOP_PREDICATE] = (
|
|
8621
|
-
[PM_CONTEXT_MAIN] = (
|
|
8622
|
-
[PM_CONTEXT_MODULE] = (
|
|
8623
|
-
[PM_CONTEXT_MODULE_ENSURE] = (
|
|
8624
|
-
[PM_CONTEXT_MODULE_ELSE] = (
|
|
8625
|
-
[PM_CONTEXT_MODULE_RESCUE] = (
|
|
8626
|
-
[PM_CONTEXT_MULTI_TARGET] = (
|
|
8627
|
-
[PM_CONTEXT_PARENS] = (
|
|
8628
|
-
[PM_CONTEXT_POSTEXE] = (
|
|
8629
|
-
[PM_CONTEXT_PREDICATE] = (
|
|
8630
|
-
[PM_CONTEXT_PREEXE] = (
|
|
8631
|
-
[PM_CONTEXT_RESCUE_MODIFIER] = (
|
|
8632
|
-
[PM_CONTEXT_SCLASS] = (
|
|
8633
|
-
[PM_CONTEXT_SCLASS_ENSURE] = (
|
|
8634
|
-
[PM_CONTEXT_SCLASS_ELSE] = (
|
|
8635
|
-
[PM_CONTEXT_SCLASS_RESCUE] = (
|
|
8636
|
-
[PM_CONTEXT_TERNARY] = (
|
|
8637
|
-
[PM_CONTEXT_UNLESS] = (
|
|
8638
|
-
[PM_CONTEXT_UNTIL] = (
|
|
8639
|
-
[PM_CONTEXT_WHILE] = (
|
|
8594
|
+
[PM_CONTEXT_BEGIN] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8595
|
+
[PM_CONTEXT_BEGIN_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
|
|
8596
|
+
[PM_CONTEXT_BEGIN_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8597
|
+
[PM_CONTEXT_BEGIN_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8598
|
+
[PM_CONTEXT_BLOCK_BRACES] = (1U << PM_TOKEN_BRACE_RIGHT),
|
|
8599
|
+
[PM_CONTEXT_BLOCK_KEYWORDS] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
|
|
8600
|
+
[PM_CONTEXT_BLOCK_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
|
|
8601
|
+
[PM_CONTEXT_BLOCK_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8602
|
+
[PM_CONTEXT_BLOCK_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8603
|
+
[PM_CONTEXT_CASE_WHEN] = (1U << PM_TOKEN_KEYWORD_WHEN) | (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_ELSE),
|
|
8604
|
+
[PM_CONTEXT_CASE_IN] = (1U << PM_TOKEN_KEYWORD_IN) | (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_ELSE),
|
|
8605
|
+
[PM_CONTEXT_CLASS] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
|
|
8606
|
+
[PM_CONTEXT_CLASS_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
|
|
8607
|
+
[PM_CONTEXT_CLASS_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8608
|
+
[PM_CONTEXT_CLASS_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8609
|
+
[PM_CONTEXT_DEF] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
|
|
8610
|
+
[PM_CONTEXT_DEF_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
|
|
8611
|
+
[PM_CONTEXT_DEF_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8612
|
+
[PM_CONTEXT_DEF_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8613
|
+
[PM_CONTEXT_DEF_PARAMS] = (1U << PM_TOKEN_EOF),
|
|
8614
|
+
[PM_CONTEXT_DEFINED] = (1U << PM_TOKEN_EOF),
|
|
8615
|
+
[PM_CONTEXT_DEFAULT_PARAMS] = (1U << PM_TOKEN_COMMA) | (1U << PM_TOKEN_PARENTHESIS_RIGHT),
|
|
8616
|
+
[PM_CONTEXT_ELSE] = (1U << PM_TOKEN_KEYWORD_END),
|
|
8617
|
+
[PM_CONTEXT_ELSIF] = (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_ELSIF) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8618
|
+
[PM_CONTEXT_EMBEXPR] = (1U << PM_TOKEN_EMBEXPR_END),
|
|
8619
|
+
[PM_CONTEXT_FOR] = (1U << PM_TOKEN_KEYWORD_END),
|
|
8620
|
+
[PM_CONTEXT_FOR_INDEX] = (1U << PM_TOKEN_KEYWORD_IN),
|
|
8621
|
+
[PM_CONTEXT_IF] = (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_ELSIF) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8622
|
+
[PM_CONTEXT_LAMBDA_BRACES] = (1U << PM_TOKEN_BRACE_RIGHT),
|
|
8623
|
+
[PM_CONTEXT_LAMBDA_DO_END] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
|
|
8624
|
+
[PM_CONTEXT_LAMBDA_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
|
|
8625
|
+
[PM_CONTEXT_LAMBDA_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8626
|
+
[PM_CONTEXT_LAMBDA_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8627
|
+
[PM_CONTEXT_LOOP_PREDICATE] = (1U << PM_TOKEN_KEYWORD_DO) | (1U << PM_TOKEN_KEYWORD_THEN),
|
|
8628
|
+
[PM_CONTEXT_MAIN] = (1U << PM_TOKEN_EOF),
|
|
8629
|
+
[PM_CONTEXT_MODULE] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
|
|
8630
|
+
[PM_CONTEXT_MODULE_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
|
|
8631
|
+
[PM_CONTEXT_MODULE_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8632
|
+
[PM_CONTEXT_MODULE_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8633
|
+
[PM_CONTEXT_MULTI_TARGET] = (1U << PM_TOKEN_EOF),
|
|
8634
|
+
[PM_CONTEXT_PARENS] = (1U << PM_TOKEN_PARENTHESIS_RIGHT),
|
|
8635
|
+
[PM_CONTEXT_POSTEXE] = (1U << PM_TOKEN_BRACE_RIGHT),
|
|
8636
|
+
[PM_CONTEXT_PREDICATE] = (1U << PM_TOKEN_KEYWORD_THEN) | (1U << PM_TOKEN_NEWLINE) | (1U << PM_TOKEN_SEMICOLON),
|
|
8637
|
+
[PM_CONTEXT_PREEXE] = (1U << PM_TOKEN_BRACE_RIGHT),
|
|
8638
|
+
[PM_CONTEXT_RESCUE_MODIFIER] = (1U << PM_TOKEN_EOF),
|
|
8639
|
+
[PM_CONTEXT_SCLASS] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
|
|
8640
|
+
[PM_CONTEXT_SCLASS_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
|
|
8641
|
+
[PM_CONTEXT_SCLASS_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8642
|
+
[PM_CONTEXT_SCLASS_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8643
|
+
[PM_CONTEXT_TERNARY] = (1U << PM_TOKEN_EOF),
|
|
8644
|
+
[PM_CONTEXT_UNLESS] = (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
|
|
8645
|
+
[PM_CONTEXT_UNTIL] = (1U << PM_TOKEN_KEYWORD_END),
|
|
8646
|
+
[PM_CONTEXT_WHILE] = (1U << PM_TOKEN_KEYWORD_END),
|
|
8640
8647
|
};
|
|
8641
8648
|
|
|
8642
8649
|
static inline bool
|
|
8643
8650
|
context_terminator(pm_context_t context, pm_token_t *token) {
|
|
8644
|
-
return token->type < 32 && (context_terminators[context] & (
|
|
8651
|
+
return token->type < 32 && (context_terminators[context] & (1U << token->type));
|
|
8645
8652
|
}
|
|
8646
8653
|
|
|
8647
8654
|
/**
|
|
@@ -14443,6 +14450,17 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
|
14443
14450
|
if (accepted_newline) {
|
|
14444
14451
|
pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA);
|
|
14445
14452
|
}
|
|
14453
|
+
|
|
14454
|
+
// If this is a command call and an argument takes a block,
|
|
14455
|
+
// there can be no further arguments. For example,
|
|
14456
|
+
// `foo(bar 1 do end, 2)` should be rejected.
|
|
14457
|
+
if (PM_NODE_TYPE_P(argument, PM_CALL_NODE)) {
|
|
14458
|
+
pm_call_node_t *call = (pm_call_node_t *) argument;
|
|
14459
|
+
if (call->opening_loc.start == NULL && call->arguments != NULL && call->block != NULL) {
|
|
14460
|
+
pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA);
|
|
14461
|
+
break;
|
|
14462
|
+
}
|
|
14463
|
+
}
|
|
14446
14464
|
} else {
|
|
14447
14465
|
// If there is no comma at the end of the argument list then we're
|
|
14448
14466
|
// done parsing arguments and can break out of this loop.
|
|
@@ -14594,6 +14612,18 @@ update_parameter_state(pm_parser_t *parser, pm_token_t *token, pm_parameters_ord
|
|
|
14594
14612
|
return true;
|
|
14595
14613
|
}
|
|
14596
14614
|
|
|
14615
|
+
/**
|
|
14616
|
+
* Ensures that after parsing a parameter, the next token is not `=`.
|
|
14617
|
+
* Some parameters like `def(* = 1)` cannot become optional. When no parens
|
|
14618
|
+
* are present like in `def * = 1`, this creates ambiguity with endless method definitions.
|
|
14619
|
+
*/
|
|
14620
|
+
static inline void
|
|
14621
|
+
refute_optional_parameter(pm_parser_t *parser) {
|
|
14622
|
+
if (match1(parser, PM_TOKEN_EQUAL)) {
|
|
14623
|
+
pm_parser_err_previous(parser, PM_ERR_DEF_ENDLESS_PARAMETERS);
|
|
14624
|
+
}
|
|
14625
|
+
}
|
|
14626
|
+
|
|
14597
14627
|
/**
|
|
14598
14628
|
* Parse a list of parameters on a method definition.
|
|
14599
14629
|
*/
|
|
@@ -14646,6 +14676,10 @@ parse_parameters(
|
|
|
14646
14676
|
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_BLOCK;
|
|
14647
14677
|
}
|
|
14648
14678
|
|
|
14679
|
+
if (!uses_parentheses) {
|
|
14680
|
+
refute_optional_parameter(parser);
|
|
14681
|
+
}
|
|
14682
|
+
|
|
14649
14683
|
pm_block_parameter_node_t *param = pm_block_parameter_node_create(parser, &name, &operator);
|
|
14650
14684
|
if (repeated) {
|
|
14651
14685
|
pm_node_flag_set_repeated_parameter((pm_node_t *)param);
|
|
@@ -14667,6 +14701,10 @@ parse_parameters(
|
|
|
14667
14701
|
bool succeeded = update_parameter_state(parser, &parser->current, &order);
|
|
14668
14702
|
parser_lex(parser);
|
|
14669
14703
|
|
|
14704
|
+
if (!uses_parentheses) {
|
|
14705
|
+
refute_optional_parameter(parser);
|
|
14706
|
+
}
|
|
14707
|
+
|
|
14670
14708
|
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_ALL;
|
|
14671
14709
|
pm_forwarding_parameter_node_t *param = pm_forwarding_parameter_node_create(parser, &parser->previous);
|
|
14672
14710
|
|
|
@@ -14848,6 +14886,10 @@ parse_parameters(
|
|
|
14848
14886
|
context_pop(parser);
|
|
14849
14887
|
pm_parameters_node_keywords_append(params, param);
|
|
14850
14888
|
|
|
14889
|
+
if (!uses_parentheses) {
|
|
14890
|
+
refute_optional_parameter(parser);
|
|
14891
|
+
}
|
|
14892
|
+
|
|
14851
14893
|
// If parsing the value of the parameter resulted in error recovery,
|
|
14852
14894
|
// then we can put a missing node in its place and stop parsing the
|
|
14853
14895
|
// parameters entirely now.
|
|
@@ -14879,6 +14921,10 @@ parse_parameters(
|
|
|
14879
14921
|
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS;
|
|
14880
14922
|
}
|
|
14881
14923
|
|
|
14924
|
+
if (!uses_parentheses) {
|
|
14925
|
+
refute_optional_parameter(parser);
|
|
14926
|
+
}
|
|
14927
|
+
|
|
14882
14928
|
pm_node_t *param = (pm_node_t *) pm_rest_parameter_node_create(parser, &operator, &name);
|
|
14883
14929
|
if (repeated) {
|
|
14884
14930
|
pm_node_flag_set_repeated_parameter(param);
|
|
@@ -14927,6 +14973,10 @@ parse_parameters(
|
|
|
14927
14973
|
}
|
|
14928
14974
|
}
|
|
14929
14975
|
|
|
14976
|
+
if (!uses_parentheses) {
|
|
14977
|
+
refute_optional_parameter(parser);
|
|
14978
|
+
}
|
|
14979
|
+
|
|
14930
14980
|
if (params->keyword_rest == NULL) {
|
|
14931
14981
|
pm_parameters_node_keyword_rest_set(params, param);
|
|
14932
14982
|
} else {
|
|
@@ -18491,20 +18541,28 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
|
|
|
18491
18541
|
return (pm_node_t *) node;
|
|
18492
18542
|
}
|
|
18493
18543
|
case PM_TOKEN_CHARACTER_LITERAL: {
|
|
18494
|
-
parser_lex(parser);
|
|
18495
|
-
|
|
18496
|
-
pm_token_t opening = parser->previous;
|
|
18497
|
-
opening.type = PM_TOKEN_STRING_BEGIN;
|
|
18498
|
-
opening.end = opening.start + 1;
|
|
18499
|
-
|
|
18500
|
-
pm_token_t content = parser->previous;
|
|
18501
|
-
content.type = PM_TOKEN_STRING_CONTENT;
|
|
18502
|
-
content.start = content.start + 1;
|
|
18503
|
-
|
|
18504
18544
|
pm_token_t closing = not_provided(parser);
|
|
18505
|
-
pm_node_t *node = (pm_node_t *) pm_string_node_create_current_string(
|
|
18545
|
+
pm_node_t *node = (pm_node_t *) pm_string_node_create_current_string(
|
|
18546
|
+
parser,
|
|
18547
|
+
&(pm_token_t) {
|
|
18548
|
+
.type = PM_TOKEN_STRING_BEGIN,
|
|
18549
|
+
.start = parser->current.start,
|
|
18550
|
+
.end = parser->current.start + 1
|
|
18551
|
+
},
|
|
18552
|
+
&(pm_token_t) {
|
|
18553
|
+
.type = PM_TOKEN_STRING_CONTENT,
|
|
18554
|
+
.start = parser->current.start + 1,
|
|
18555
|
+
.end = parser->current.end
|
|
18556
|
+
},
|
|
18557
|
+
&closing
|
|
18558
|
+
);
|
|
18559
|
+
|
|
18506
18560
|
pm_node_flag_set(node, parse_unescaped_encoding(parser));
|
|
18507
18561
|
|
|
18562
|
+
// Skip past the character literal here, since now we have handled
|
|
18563
|
+
// parser->explicit_encoding correctly.
|
|
18564
|
+
parser_lex(parser);
|
|
18565
|
+
|
|
18508
18566
|
// Characters can be followed by strings in which case they are
|
|
18509
18567
|
// automatically concatenated.
|
|
18510
18568
|
if (match1(parser, PM_TOKEN_STRING_BEGIN)) {
|
|
@@ -20901,7 +20959,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding
|
|
|
20901
20959
|
bool permitted = true;
|
|
20902
20960
|
if (previous_binding_power != PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_USTAR)) permitted = false;
|
|
20903
20961
|
|
|
20904
|
-
pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power <
|
|
20962
|
+
pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MODIFIER, diag_id, (uint16_t) (depth + 1));
|
|
20905
20963
|
if (!permitted) pm_parser_err_node(parser, value, PM_ERR_UNEXPECTED_MULTI_WRITE);
|
|
20906
20964
|
|
|
20907
20965
|
parse_assignment_value_local(parser, value);
|
|
@@ -22498,9 +22556,10 @@ parse_program(pm_parser_t *parser) {
|
|
|
22498
22556
|
statements = wrap_statements(parser, statements);
|
|
22499
22557
|
} else {
|
|
22500
22558
|
flush_block_exits(parser, previous_block_exits);
|
|
22501
|
-
pm_node_list_free(¤t_block_exits);
|
|
22502
22559
|
}
|
|
22503
22560
|
|
|
22561
|
+
pm_node_list_free(¤t_block_exits);
|
|
22562
|
+
|
|
22504
22563
|
// If this is an empty file, then we're still going to parse all of the
|
|
22505
22564
|
// statements in order to gather up all of the comments and such. Here we'll
|
|
22506
22565
|
// correct the location information.
|
data/src/util/pm_string.c
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#include "prism/util/pm_string.h"
|
|
2
2
|
|
|
3
|
+
static const uint8_t empty_source[] = "";
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* Returns the size of the pm_string_t struct. This is necessary to allocate the
|
|
5
7
|
* correct amount of memory in the FFI backend.
|
|
@@ -133,8 +135,7 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
|
|
|
133
135
|
// the source to a constant empty string and return.
|
|
134
136
|
if (file_size == 0) {
|
|
135
137
|
pm_string_file_handle_close(&handle);
|
|
136
|
-
|
|
137
|
-
*string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
|
|
138
|
+
*string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
|
|
138
139
|
return PM_STRING_INIT_SUCCESS;
|
|
139
140
|
}
|
|
140
141
|
|
|
@@ -182,8 +183,7 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
|
|
|
182
183
|
|
|
183
184
|
if (size == 0) {
|
|
184
185
|
close(fd);
|
|
185
|
-
|
|
186
|
-
*string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
|
|
186
|
+
*string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
|
|
187
187
|
return PM_STRING_INIT_SUCCESS;
|
|
188
188
|
}
|
|
189
189
|
|
|
@@ -225,8 +225,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) {
|
|
|
225
225
|
// the source to a constant empty string and return.
|
|
226
226
|
if (file_size == 0) {
|
|
227
227
|
pm_string_file_handle_close(&handle);
|
|
228
|
-
|
|
229
|
-
*string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
|
|
228
|
+
*string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
|
|
230
229
|
return PM_STRING_INIT_SUCCESS;
|
|
231
230
|
}
|
|
232
231
|
|
|
@@ -278,8 +277,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) {
|
|
|
278
277
|
size_t size = (size_t) sb.st_size;
|
|
279
278
|
if (size == 0) {
|
|
280
279
|
close(fd);
|
|
281
|
-
|
|
282
|
-
*string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
|
|
280
|
+
*string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
|
|
283
281
|
return PM_STRING_INIT_SUCCESS;
|
|
284
282
|
}
|
|
285
283
|
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: prism
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shopify
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
12
|
email:
|
|
13
13
|
- ruby@shopify.com
|
|
@@ -189,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
189
189
|
- !ruby/object:Gem::Version
|
|
190
190
|
version: '0'
|
|
191
191
|
requirements: []
|
|
192
|
-
rubygems_version: 3.6.
|
|
192
|
+
rubygems_version: 3.6.9
|
|
193
193
|
specification_version: 4
|
|
194
194
|
summary: Prism Ruby parser
|
|
195
195
|
test_files: []
|