prism 0.18.0 → 0.19.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 +31 -1
- data/README.md +2 -1
- data/config.yml +188 -55
- data/docs/building.md +9 -2
- data/docs/configuration.md +10 -9
- data/docs/encoding.md +24 -56
- data/docs/local_variable_depth.md +229 -0
- data/docs/ruby_api.md +2 -0
- data/docs/serialization.md +18 -13
- data/ext/prism/api_node.c +337 -195
- data/ext/prism/extconf.rb +13 -7
- data/ext/prism/extension.c +96 -32
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +340 -137
- data/include/prism/defines.h +17 -0
- data/include/prism/diagnostic.h +11 -5
- data/include/prism/encoding.h +248 -0
- data/include/prism/options.h +2 -2
- data/include/prism/parser.h +62 -42
- 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 +2 -2
- data/include/prism.h +13 -15
- data/lib/prism/compiler.rb +12 -0
- data/lib/prism/debug.rb +9 -4
- data/lib/prism/desugar_compiler.rb +3 -3
- data/lib/prism/dispatcher.rb +56 -0
- data/lib/prism/dot_visitor.rb +476 -198
- data/lib/prism/dsl.rb +66 -46
- data/lib/prism/ffi.rb +16 -3
- data/lib/prism/lex_compat.rb +19 -9
- data/lib/prism/mutation_compiler.rb +20 -0
- data/lib/prism/node.rb +1173 -450
- data/lib/prism/node_ext.rb +41 -16
- data/lib/prism/parse_result.rb +12 -15
- data/lib/prism/ripper_compat.rb +49 -34
- data/lib/prism/serialize.rb +242 -212
- data/lib/prism/visitor.rb +12 -0
- data/lib/prism.rb +20 -4
- data/prism.gemspec +4 -10
- data/rbi/prism.rbi +605 -230
- data/rbi/prism_static.rbi +3 -0
- data/sig/prism.rbs +379 -124
- data/sig/prism_static.rbs +1 -0
- data/src/diagnostic.c +228 -222
- data/src/encoding.c +5137 -0
- data/src/node.c +66 -0
- data/src/options.c +21 -2
- data/src/prettyprint.c +806 -406
- data/src/prism.c +1092 -700
- data/src/regexp.c +3 -3
- data/src/serialize.c +227 -157
- 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 +5 -11
- data/include/prism/enc/pm_encoding.h +0 -227
- data/src/enc/pm_big5.c +0 -116
- data/src/enc/pm_cp51932.c +0 -57
- data/src/enc/pm_euc_jp.c +0 -69
- data/src/enc/pm_gbk.c +0 -65
- data/src/enc/pm_shift_jis.c +0 -57
- data/src/enc/pm_tables.c +0 -2073
- data/src/enc/pm_unicode.c +0 -2369
- data/src/enc/pm_windows_31j.c +0 -57
data/src/prism.c
CHANGED
@@ -40,6 +40,7 @@ debug_context(pm_context_t context) {
|
|
40
40
|
case PM_CONTEXT_DEF_PARAMS: return "DEF_PARAMS";
|
41
41
|
case PM_CONTEXT_DEFAULT_PARAMS: return "DEFAULT_PARAMS";
|
42
42
|
case PM_CONTEXT_ENSURE: return "ENSURE";
|
43
|
+
case PM_CONTEXT_ENSURE_DEF: return "ENSURE_DEF";
|
43
44
|
case PM_CONTEXT_ELSE: return "ELSE";
|
44
45
|
case PM_CONTEXT_ELSIF: return "ELSIF";
|
45
46
|
case PM_CONTEXT_EMBEXPR: return "EMBEXPR";
|
@@ -56,6 +57,8 @@ debug_context(pm_context_t context) {
|
|
56
57
|
case PM_CONTEXT_PREEXE: return "PREEXE";
|
57
58
|
case PM_CONTEXT_RESCUE: return "RESCUE";
|
58
59
|
case PM_CONTEXT_RESCUE_ELSE: return "RESCUE_ELSE";
|
60
|
+
case PM_CONTEXT_RESCUE_ELSE_DEF: return "RESCUE_ELSE_DEF";
|
61
|
+
case PM_CONTEXT_RESCUE_DEF: return "RESCUE_DEF";
|
59
62
|
case PM_CONTEXT_SCLASS: return "SCLASS";
|
60
63
|
case PM_CONTEXT_UNLESS: return "UNLESS";
|
61
64
|
case PM_CONTEXT_UNTIL: return "UNTIL";
|
@@ -272,6 +275,7 @@ lex_mode_push_list(pm_parser_t *parser, bool interpolation, uint8_t delimiter) {
|
|
272
275
|
breakpoints[index++] = incrementor;
|
273
276
|
}
|
274
277
|
|
278
|
+
parser->explicit_encoding = NULL;
|
275
279
|
return lex_mode_push(parser, lex_mode);
|
276
280
|
}
|
277
281
|
|
@@ -353,6 +357,7 @@ lex_mode_push_string(pm_parser_t *parser, bool interpolation, bool label_allowed
|
|
353
357
|
breakpoints[index++] = incrementor;
|
354
358
|
}
|
355
359
|
|
360
|
+
parser->explicit_encoding = NULL;
|
356
361
|
return lex_mode_push(parser, lex_mode);
|
357
362
|
}
|
358
363
|
|
@@ -536,7 +541,7 @@ pm_parser_err_token(pm_parser_t *parser, const pm_token_t *token, pm_diagnostic_
|
|
536
541
|
* Append an error to the list of errors on the parser using the location of the
|
537
542
|
* given token and a format string.
|
538
543
|
*/
|
539
|
-
#define PM_PARSER_ERR_TOKEN_FORMAT(parser, token, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, token
|
544
|
+
#define PM_PARSER_ERR_TOKEN_FORMAT(parser, token, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, (token).start, (token).end, diag_id, __VA_ARGS__)
|
540
545
|
|
541
546
|
/**
|
542
547
|
* Append a warning to the list of warnings on the parser.
|
@@ -776,8 +781,7 @@ pm_conditional_predicate(pm_node_t *node) {
|
|
776
781
|
* parentheses. In these cases we set the token to the "not provided" type. For
|
777
782
|
* example:
|
778
783
|
*
|
779
|
-
* pm_token_t token;
|
780
|
-
* not_provided(&token, parser->previous.end);
|
784
|
+
* pm_token_t token = not_provided(parser);
|
781
785
|
*/
|
782
786
|
static inline pm_token_t
|
783
787
|
not_provided(pm_parser_t *parser) {
|
@@ -860,6 +864,27 @@ pm_arguments_validate_block(pm_parser_t *parser, pm_arguments_t *arguments, pm_b
|
|
860
864
|
pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_UNEXPECTED_BLOCK);
|
861
865
|
}
|
862
866
|
|
867
|
+
/******************************************************************************/
|
868
|
+
/* Node flag handling functions */
|
869
|
+
/******************************************************************************/
|
870
|
+
|
871
|
+
/**
|
872
|
+
* Set the given flag on the given node.
|
873
|
+
*/
|
874
|
+
static inline void
|
875
|
+
pm_node_flag_set(pm_node_t *node, pm_node_flags_t flag) {
|
876
|
+
node->flags |= flag;
|
877
|
+
}
|
878
|
+
|
879
|
+
/**
|
880
|
+
* Remove the given flag from the given node.
|
881
|
+
*/
|
882
|
+
static inline void
|
883
|
+
pm_node_flag_unset(pm_node_t *node, pm_node_flags_t flag) {
|
884
|
+
node->flags &= (pm_node_flags_t) ~flag;
|
885
|
+
}
|
886
|
+
|
887
|
+
|
863
888
|
/******************************************************************************/
|
864
889
|
/* Node creation functions */
|
865
890
|
/******************************************************************************/
|
@@ -1148,8 +1173,12 @@ pm_array_node_elements_append(pm_array_node_t *node, pm_node_t *element) {
|
|
1148
1173
|
|
1149
1174
|
// If the element is not a static literal, then the array is not a static
|
1150
1175
|
// literal. Turn that flag off.
|
1151
|
-
if (PM_NODE_TYPE_P(element, PM_ARRAY_NODE) || PM_NODE_TYPE_P(element, PM_HASH_NODE) || PM_NODE_TYPE_P(element, PM_RANGE_NODE) || (element
|
1152
|
-
|
1176
|
+
if (PM_NODE_TYPE_P(element, PM_ARRAY_NODE) || PM_NODE_TYPE_P(element, PM_HASH_NODE) || PM_NODE_TYPE_P(element, PM_RANGE_NODE) || !PM_NODE_FLAG_P(element, PM_NODE_FLAG_STATIC_LITERAL)) {
|
1177
|
+
pm_node_flag_unset((pm_node_t *)node, PM_NODE_FLAG_STATIC_LITERAL);
|
1178
|
+
}
|
1179
|
+
|
1180
|
+
if (PM_NODE_TYPE_P(element, PM_SPLAT_NODE)) {
|
1181
|
+
pm_node_flag_set((pm_node_t *)node, PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT);
|
1153
1182
|
}
|
1154
1183
|
}
|
1155
1184
|
|
@@ -1193,7 +1222,7 @@ pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *node
|
|
1193
1222
|
for (size_t index = 0; index < nodes->size; index++) {
|
1194
1223
|
pm_node_t *child = nodes->nodes[index];
|
1195
1224
|
|
1196
|
-
if (!found_rest && PM_NODE_TYPE_P(child, PM_SPLAT_NODE)) {
|
1225
|
+
if (!found_rest && (PM_NODE_TYPE_P(child, PM_SPLAT_NODE) || PM_NODE_TYPE_P(child, PM_IMPLICIT_REST_NODE))) {
|
1197
1226
|
node->rest = child;
|
1198
1227
|
found_rest = true;
|
1199
1228
|
} else if (found_rest) {
|
@@ -1461,7 +1490,7 @@ pm_block_argument_node_create(pm_parser_t *parser, const pm_token_t *operator, p
|
|
1461
1490
|
* Allocate and initialize a new BlockNode node.
|
1462
1491
|
*/
|
1463
1492
|
static pm_block_node_t *
|
1464
|
-
pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *opening,
|
1493
|
+
pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, uint32_t locals_body_index, const pm_token_t *opening, pm_node_t *parameters, pm_node_t *body, const pm_token_t *closing) {
|
1465
1494
|
pm_block_node_t *node = PM_ALLOC_NODE(parser, pm_block_node_t);
|
1466
1495
|
|
1467
1496
|
*node = (pm_block_node_t) {
|
@@ -1470,6 +1499,7 @@ pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const p
|
|
1470
1499
|
.location = { .start = opening->start, .end = closing->end },
|
1471
1500
|
},
|
1472
1501
|
.locals = *locals,
|
1502
|
+
.locals_body_index = locals_body_index,
|
1473
1503
|
.parameters = parameters,
|
1474
1504
|
.body = body,
|
1475
1505
|
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
|
@@ -1711,7 +1741,7 @@ pm_call_node_call_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *o
|
|
1711
1741
|
node->block = arguments->block;
|
1712
1742
|
|
1713
1743
|
if (operator->type == PM_TOKEN_AMPERSAND_DOT) {
|
1714
|
-
node
|
1744
|
+
pm_node_flag_set((pm_node_t *)node, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION);
|
1715
1745
|
}
|
1716
1746
|
|
1717
1747
|
node->name = pm_parser_constant_id_token(parser, message);
|
@@ -1785,7 +1815,7 @@ pm_call_node_shorthand_create(pm_parser_t *parser, pm_node_t *receiver, pm_token
|
|
1785
1815
|
node->block = arguments->block;
|
1786
1816
|
|
1787
1817
|
if (operator->type == PM_TOKEN_AMPERSAND_DOT) {
|
1788
|
-
node
|
1818
|
+
pm_node_flag_set((pm_node_t *)node, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION);
|
1789
1819
|
}
|
1790
1820
|
|
1791
1821
|
node->name = pm_parser_constant_id_constant(parser, "call", 4);
|
@@ -1832,12 +1862,12 @@ pm_call_node_variable_call_create(pm_parser_t *parser, pm_token_t *message) {
|
|
1832
1862
|
*/
|
1833
1863
|
static inline bool
|
1834
1864
|
pm_call_node_variable_call_p(pm_call_node_t *node) {
|
1835
|
-
return node
|
1865
|
+
return PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_VARIABLE_CALL);
|
1836
1866
|
}
|
1837
1867
|
|
1838
1868
|
/**
|
1839
|
-
* Returns whether or not this call is to the [] method in the index form (as
|
1840
|
-
* opposed to `foo.[]`).
|
1869
|
+
* Returns whether or not this call is to the [] method in the index form without a block (as
|
1870
|
+
* opposed to `foo.[]` and `foo[] { }`).
|
1841
1871
|
*/
|
1842
1872
|
static inline bool
|
1843
1873
|
pm_call_node_index_p(pm_call_node_t *node) {
|
@@ -1845,7 +1875,8 @@ pm_call_node_index_p(pm_call_node_t *node) {
|
|
1845
1875
|
(node->call_operator_loc.start == NULL) &&
|
1846
1876
|
(node->message_loc.start != NULL) &&
|
1847
1877
|
(node->message_loc.start[0] == '[') &&
|
1848
|
-
(node->message_loc.end[-1] == ']')
|
1878
|
+
(node->message_loc.end[-1] == ']') &&
|
1879
|
+
(node->block == NULL || PM_NODE_TYPE_P(node->block, PM_BLOCK_ARGUMENT_NODE))
|
1849
1880
|
);
|
1850
1881
|
}
|
1851
1882
|
|
@@ -2101,6 +2132,63 @@ pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const
|
|
2101
2132
|
return node;
|
2102
2133
|
}
|
2103
2134
|
|
2135
|
+
/**
|
2136
|
+
* Allocate and initialize a new CallTargetNode node from an existing call
|
2137
|
+
* node.
|
2138
|
+
*/
|
2139
|
+
static pm_call_target_node_t *
|
2140
|
+
pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) {
|
2141
|
+
pm_call_target_node_t *node = PM_ALLOC_NODE(parser, pm_call_target_node_t);
|
2142
|
+
|
2143
|
+
*node = (pm_call_target_node_t) {
|
2144
|
+
{
|
2145
|
+
.type = PM_CALL_TARGET_NODE,
|
2146
|
+
.flags = target->base.flags,
|
2147
|
+
.location = target->base.location
|
2148
|
+
},
|
2149
|
+
.receiver = target->receiver,
|
2150
|
+
.call_operator_loc = target->call_operator_loc,
|
2151
|
+
.name = target->name,
|
2152
|
+
.message_loc = target->message_loc
|
2153
|
+
};
|
2154
|
+
|
2155
|
+
// Here we're going to free the target, since it is no longer necessary.
|
2156
|
+
// However, we don't want to call `pm_node_destroy` because we want to keep
|
2157
|
+
// around all of its children since we just reused them.
|
2158
|
+
free(target);
|
2159
|
+
|
2160
|
+
return node;
|
2161
|
+
}
|
2162
|
+
|
2163
|
+
/**
|
2164
|
+
* Allocate and initialize a new IndexTargetNode node from an existing call
|
2165
|
+
* node.
|
2166
|
+
*/
|
2167
|
+
static pm_index_target_node_t *
|
2168
|
+
pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) {
|
2169
|
+
pm_index_target_node_t *node = PM_ALLOC_NODE(parser, pm_index_target_node_t);
|
2170
|
+
|
2171
|
+
*node = (pm_index_target_node_t) {
|
2172
|
+
{
|
2173
|
+
.type = PM_INDEX_TARGET_NODE,
|
2174
|
+
.flags = target->base.flags,
|
2175
|
+
.location = target->base.location
|
2176
|
+
},
|
2177
|
+
.receiver = target->receiver,
|
2178
|
+
.opening_loc = target->opening_loc,
|
2179
|
+
.arguments = target->arguments,
|
2180
|
+
.closing_loc = target->closing_loc,
|
2181
|
+
.block = target->block
|
2182
|
+
};
|
2183
|
+
|
2184
|
+
// Here we're going to free the target, since it is no longer necessary.
|
2185
|
+
// However, we don't want to call `pm_node_destroy` because we want to keep
|
2186
|
+
// around all of its children since we just reused them.
|
2187
|
+
free(target);
|
2188
|
+
|
2189
|
+
return node;
|
2190
|
+
}
|
2191
|
+
|
2104
2192
|
/**
|
2105
2193
|
* Allocate and initialize a new CapturePatternNode node.
|
2106
2194
|
*/
|
@@ -2452,6 +2540,8 @@ pm_constant_path_or_write_node_create(pm_parser_t *parser, pm_constant_path_node
|
|
2452
2540
|
*/
|
2453
2541
|
static pm_constant_path_node_t *
|
2454
2542
|
pm_constant_path_node_create(pm_parser_t *parser, pm_node_t *parent, const pm_token_t *delimiter, pm_node_t *child) {
|
2543
|
+
pm_assert_value_expression(parser, parent);
|
2544
|
+
|
2455
2545
|
pm_constant_path_node_t *node = PM_ALLOC_NODE(parser, pm_constant_path_node_t);
|
2456
2546
|
|
2457
2547
|
*node = (pm_constant_path_node_t) {
|
@@ -2622,6 +2712,7 @@ pm_def_node_create(
|
|
2622
2712
|
pm_parameters_node_t *parameters,
|
2623
2713
|
pm_node_t *body,
|
2624
2714
|
pm_constant_id_list_t *locals,
|
2715
|
+
uint32_t locals_body_index,
|
2625
2716
|
const pm_token_t *def_keyword,
|
2626
2717
|
const pm_token_t *operator,
|
2627
2718
|
const pm_token_t *lparen,
|
@@ -2649,6 +2740,7 @@ pm_def_node_create(
|
|
2649
2740
|
.parameters = parameters,
|
2650
2741
|
.body = body,
|
2651
2742
|
.locals = *locals,
|
2743
|
+
.locals_body_index = locals_body_index,
|
2652
2744
|
.def_keyword_loc = PM_LOCATION_TOKEN_VALUE(def_keyword),
|
2653
2745
|
.operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
|
2654
2746
|
.lparen_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(lparen),
|
@@ -3256,10 +3348,16 @@ static inline void
|
|
3256
3348
|
pm_hash_node_elements_append(pm_hash_node_t *hash, pm_node_t *element) {
|
3257
3349
|
pm_node_list_append(&hash->elements, element);
|
3258
3350
|
|
3259
|
-
|
3260
|
-
|
3261
|
-
|
3262
|
-
|
3351
|
+
bool static_literal = PM_NODE_TYPE_P(element, PM_ASSOC_NODE);
|
3352
|
+
if (static_literal) {
|
3353
|
+
pm_assoc_node_t *assoc = (pm_assoc_node_t *) element;
|
3354
|
+
static_literal = !PM_NODE_TYPE_P(assoc->key, PM_ARRAY_NODE) && !PM_NODE_TYPE_P(assoc->key, PM_HASH_NODE) && !PM_NODE_TYPE_P(assoc->key, PM_RANGE_NODE);
|
3355
|
+
static_literal = static_literal && PM_NODE_FLAG_P(assoc->key, PM_NODE_FLAG_STATIC_LITERAL);
|
3356
|
+
static_literal = static_literal && PM_NODE_FLAG_P(assoc, PM_NODE_FLAG_STATIC_LITERAL);
|
3357
|
+
}
|
3358
|
+
|
3359
|
+
if (!static_literal) {
|
3360
|
+
pm_node_flag_unset((pm_node_t *)hash, PM_NODE_FLAG_STATIC_LITERAL);
|
3263
3361
|
}
|
3264
3362
|
}
|
3265
3363
|
|
@@ -3416,6 +3514,25 @@ pm_implicit_node_create(pm_parser_t *parser, pm_node_t *value) {
|
|
3416
3514
|
return node;
|
3417
3515
|
}
|
3418
3516
|
|
3517
|
+
/**
|
3518
|
+
* Allocate and initialize a new ImplicitRestNode node.
|
3519
|
+
*/
|
3520
|
+
static pm_implicit_rest_node_t *
|
3521
|
+
pm_implicit_rest_node_create(pm_parser_t *parser, const pm_token_t *token) {
|
3522
|
+
assert(token->type == PM_TOKEN_COMMA);
|
3523
|
+
|
3524
|
+
pm_implicit_rest_node_t *node = PM_ALLOC_NODE(parser, pm_implicit_rest_node_t);
|
3525
|
+
|
3526
|
+
*node = (pm_implicit_rest_node_t) {
|
3527
|
+
{
|
3528
|
+
.type = PM_IMPLICIT_REST_NODE,
|
3529
|
+
.location = PM_LOCATION_TOKEN_VALUE(token)
|
3530
|
+
}
|
3531
|
+
};
|
3532
|
+
|
3533
|
+
return node;
|
3534
|
+
}
|
3535
|
+
|
3419
3536
|
/**
|
3420
3537
|
* Allocate and initialize a new IntegerNode node.
|
3421
3538
|
*/
|
@@ -3697,7 +3814,7 @@ static inline void
|
|
3697
3814
|
pm_interpolated_regular_expression_node_closing_set(pm_interpolated_regular_expression_node_t *node, const pm_token_t *closing) {
|
3698
3815
|
node->closing_loc = PM_LOCATION_TOKEN_VALUE(closing);
|
3699
3816
|
node->base.location.end = closing->end;
|
3700
|
-
node
|
3817
|
+
pm_node_flag_set((pm_node_t *)node, pm_regular_expression_flags_create(closing));
|
3701
3818
|
}
|
3702
3819
|
|
3703
3820
|
/**
|
@@ -3831,7 +3948,8 @@ pm_keyword_hash_node_create(pm_parser_t *parser) {
|
|
3831
3948
|
*node = (pm_keyword_hash_node_t) {
|
3832
3949
|
.base = {
|
3833
3950
|
.type = PM_KEYWORD_HASH_NODE,
|
3834
|
-
.location = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
|
3951
|
+
.location = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
|
3952
|
+
.flags = PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS
|
3835
3953
|
},
|
3836
3954
|
.elements = { 0 }
|
3837
3955
|
};
|
@@ -3844,6 +3962,13 @@ pm_keyword_hash_node_create(pm_parser_t *parser) {
|
|
3844
3962
|
*/
|
3845
3963
|
static void
|
3846
3964
|
pm_keyword_hash_node_elements_append(pm_keyword_hash_node_t *hash, pm_node_t *element) {
|
3965
|
+
// If the element being added is not an AssocNode or does not have a symbol key, then
|
3966
|
+
// we want to turn the STATIC_KEYS flag off.
|
3967
|
+
// TODO: Rename the flag to SYMBOL_KEYS instead.
|
3968
|
+
if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE) || !PM_NODE_TYPE_P(((pm_assoc_node_t *) element)->key, PM_SYMBOL_NODE)) {
|
3969
|
+
pm_node_flag_unset((pm_node_t *)hash, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS);
|
3970
|
+
}
|
3971
|
+
|
3847
3972
|
pm_node_list_append(&hash->elements, element);
|
3848
3973
|
if (hash->base.location.start == NULL) {
|
3849
3974
|
hash->base.location.start = element->location.start;
|
@@ -3926,10 +4051,11 @@ static pm_lambda_node_t *
|
|
3926
4051
|
pm_lambda_node_create(
|
3927
4052
|
pm_parser_t *parser,
|
3928
4053
|
pm_constant_id_list_t *locals,
|
4054
|
+
uint32_t locals_body_index,
|
3929
4055
|
const pm_token_t *operator,
|
3930
4056
|
const pm_token_t *opening,
|
3931
4057
|
const pm_token_t *closing,
|
3932
|
-
|
4058
|
+
pm_node_t *parameters,
|
3933
4059
|
pm_node_t *body
|
3934
4060
|
) {
|
3935
4061
|
pm_lambda_node_t *node = PM_ALLOC_NODE(parser, pm_lambda_node_t);
|
@@ -3943,6 +4069,7 @@ pm_lambda_node_create(
|
|
3943
4069
|
},
|
3944
4070
|
},
|
3945
4071
|
.locals = *locals,
|
4072
|
+
.locals_body_index = locals_body_index,
|
3946
4073
|
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
|
3947
4074
|
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
|
3948
4075
|
.closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
|
@@ -4038,6 +4165,12 @@ pm_local_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, c
|
|
4038
4165
|
*/
|
4039
4166
|
static pm_local_variable_read_node_t *
|
4040
4167
|
pm_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name, uint32_t depth) {
|
4168
|
+
pm_constant_id_t name_id = pm_parser_constant_id_token(parser, name);
|
4169
|
+
|
4170
|
+
if (parser->current_param_name == name_id) {
|
4171
|
+
pm_parser_err_token(parser, name, PM_ERR_PARAMETER_CIRCULAR);
|
4172
|
+
}
|
4173
|
+
|
4041
4174
|
pm_local_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_read_node_t);
|
4042
4175
|
|
4043
4176
|
*node = (pm_local_variable_read_node_t) {
|
@@ -4045,7 +4178,7 @@ pm_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name,
|
|
4045
4178
|
.type = PM_LOCAL_VARIABLE_READ_NODE,
|
4046
4179
|
.location = PM_LOCATION_TOKEN_VALUE(name)
|
4047
4180
|
},
|
4048
|
-
.name =
|
4181
|
+
.name = name_id,
|
4049
4182
|
.depth = depth
|
4050
4183
|
};
|
4051
4184
|
|
@@ -4132,6 +4265,21 @@ pm_local_variable_target_node_create(pm_parser_t *parser, const pm_token_t *name
|
|
4132
4265
|
);
|
4133
4266
|
}
|
4134
4267
|
|
4268
|
+
/**
|
4269
|
+
* Allocate and initialize a new LocalVariableTargetNode node with the given depth.
|
4270
|
+
*/
|
4271
|
+
static pm_local_variable_target_node_t *
|
4272
|
+
pm_local_variable_target_node_create_depth(pm_parser_t *parser, const pm_token_t *name, uint32_t depth) {
|
4273
|
+
pm_refute_numbered_parameter(parser, name->start, name->end);
|
4274
|
+
|
4275
|
+
return pm_local_variable_target_node_create_values(
|
4276
|
+
parser,
|
4277
|
+
&(pm_location_t) { .start = name->start, .end = name->end },
|
4278
|
+
pm_parser_constant_id_token(parser, name),
|
4279
|
+
depth
|
4280
|
+
);
|
4281
|
+
}
|
4282
|
+
|
4135
4283
|
/**
|
4136
4284
|
* Allocate and initialize a new MatchPredicateNode node.
|
4137
4285
|
*/
|
@@ -4254,7 +4402,7 @@ pm_multi_target_node_create(pm_parser_t *parser) {
|
|
4254
4402
|
*/
|
4255
4403
|
static void
|
4256
4404
|
pm_multi_target_node_targets_append(pm_parser_t *parser, pm_multi_target_node_t *node, pm_node_t *target) {
|
4257
|
-
if (PM_NODE_TYPE_P(target, PM_SPLAT_NODE)) {
|
4405
|
+
if (PM_NODE_TYPE_P(target, PM_SPLAT_NODE) || PM_NODE_TYPE_P(target, PM_IMPLICIT_REST_NODE)) {
|
4258
4406
|
if (node->rest == NULL) {
|
4259
4407
|
node->rest = target;
|
4260
4408
|
} else {
|
@@ -4390,7 +4538,25 @@ pm_no_keywords_parameter_node_create(pm_parser_t *parser, const pm_token_t *oper
|
|
4390
4538
|
}
|
4391
4539
|
|
4392
4540
|
/**
|
4393
|
-
* Allocate a new
|
4541
|
+
* Allocate and initialize a new NumberedParametersNode node.
|
4542
|
+
*/
|
4543
|
+
static pm_numbered_parameters_node_t *
|
4544
|
+
pm_numbered_parameters_node_create(pm_parser_t *parser, const pm_location_t *location, uint8_t maximum) {
|
4545
|
+
pm_numbered_parameters_node_t *node = PM_ALLOC_NODE(parser, pm_numbered_parameters_node_t);
|
4546
|
+
|
4547
|
+
*node = (pm_numbered_parameters_node_t) {
|
4548
|
+
{
|
4549
|
+
.type = PM_NUMBERED_PARAMETERS_NODE,
|
4550
|
+
.location = *location
|
4551
|
+
},
|
4552
|
+
.maximum = maximum
|
4553
|
+
};
|
4554
|
+
|
4555
|
+
return node;
|
4556
|
+
}
|
4557
|
+
|
4558
|
+
/**
|
4559
|
+
* Allocate and initialize a new NthReferenceReadNode node.
|
4394
4560
|
*/
|
4395
4561
|
static pm_numbered_reference_read_node_t *
|
4396
4562
|
pm_numbered_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) {
|
@@ -4530,9 +4696,8 @@ pm_parameters_node_posts_append(pm_parameters_node_t *params, pm_node_t *param)
|
|
4530
4696
|
* Set the rest parameter on a ParametersNode node.
|
4531
4697
|
*/
|
4532
4698
|
static void
|
4533
|
-
pm_parameters_node_rest_set(pm_parameters_node_t *params,
|
4534
|
-
|
4535
|
-
pm_parameters_node_location_set(params, (pm_node_t *) param);
|
4699
|
+
pm_parameters_node_rest_set(pm_parameters_node_t *params, pm_node_t *param) {
|
4700
|
+
pm_parameters_node_location_set(params, param);
|
4536
4701
|
params->rest = param;
|
4537
4702
|
}
|
4538
4703
|
|
@@ -5124,7 +5289,7 @@ pm_statements_node_body_append(pm_statements_node_t *node, pm_node_t *statement)
|
|
5124
5289
|
pm_node_list_append(&node->body, statement);
|
5125
5290
|
|
5126
5291
|
// Every statement gets marked as a place where a newline can occur.
|
5127
|
-
statement
|
5292
|
+
pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE);
|
5128
5293
|
}
|
5129
5294
|
|
5130
5295
|
/**
|
@@ -5643,6 +5808,7 @@ pm_xstring_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening,
|
|
5643
5808
|
*node = (pm_x_string_node_t) {
|
5644
5809
|
{
|
5645
5810
|
.type = PM_X_STRING_NODE,
|
5811
|
+
.flags = PM_STRING_FLAGS_FROZEN,
|
5646
5812
|
.location = {
|
5647
5813
|
.start = opening->start,
|
5648
5814
|
.end = closing->end
|
@@ -5718,8 +5884,7 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) {
|
|
5718
5884
|
.previous = parser->current_scope,
|
5719
5885
|
.closed = closed,
|
5720
5886
|
.explicit_params = false,
|
5721
|
-
.
|
5722
|
-
.transparent = false
|
5887
|
+
.numbered_parameters = 0,
|
5723
5888
|
};
|
5724
5889
|
|
5725
5890
|
pm_constant_id_list_init(&scope->locals);
|
@@ -5728,27 +5893,6 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) {
|
|
5728
5893
|
return true;
|
5729
5894
|
}
|
5730
5895
|
|
5731
|
-
/**
|
5732
|
-
* Allocate and initialize a new scope. Push it onto the scope stack.
|
5733
|
-
*/
|
5734
|
-
static bool
|
5735
|
-
pm_parser_scope_push_transparent(pm_parser_t *parser) {
|
5736
|
-
pm_scope_t *scope = (pm_scope_t *) malloc(sizeof(pm_scope_t));
|
5737
|
-
if (scope == NULL) return false;
|
5738
|
-
|
5739
|
-
*scope = (pm_scope_t) {
|
5740
|
-
.previous = parser->current_scope,
|
5741
|
-
.closed = false,
|
5742
|
-
.explicit_params = false,
|
5743
|
-
.numbered_params = false,
|
5744
|
-
.transparent = true
|
5745
|
-
};
|
5746
|
-
|
5747
|
-
parser->current_scope = scope;
|
5748
|
-
|
5749
|
-
return true;
|
5750
|
-
}
|
5751
|
-
|
5752
5896
|
/**
|
5753
5897
|
* Check if any of the currently visible scopes contain a local variable
|
5754
5898
|
* described by the given constant id.
|
@@ -5759,7 +5903,7 @@ pm_parser_local_depth_constant_id(pm_parser_t *parser, pm_constant_id_t constant
|
|
5759
5903
|
int depth = 0;
|
5760
5904
|
|
5761
5905
|
while (scope != NULL) {
|
5762
|
-
if (
|
5906
|
+
if (pm_constant_id_list_includes(&scope->locals, constant_id)) return depth;
|
5763
5907
|
if (scope->closed) break;
|
5764
5908
|
|
5765
5909
|
scope = scope->previous;
|
@@ -5784,15 +5928,19 @@ pm_parser_local_depth(pm_parser_t *parser, pm_token_t *token) {
|
|
5784
5928
|
*/
|
5785
5929
|
static inline void
|
5786
5930
|
pm_parser_local_add(pm_parser_t *parser, pm_constant_id_t constant_id) {
|
5787
|
-
|
5788
|
-
|
5789
|
-
|
5790
|
-
assert(scope != NULL);
|
5791
|
-
if (!pm_constant_id_list_includes(&scope->locals, constant_id)) {
|
5792
|
-
pm_constant_id_list_append(&scope->locals, constant_id);
|
5931
|
+
if (!pm_constant_id_list_includes(&parser->current_scope->locals, constant_id)) {
|
5932
|
+
pm_constant_id_list_append(&parser->current_scope->locals, constant_id);
|
5793
5933
|
}
|
5794
5934
|
}
|
5795
5935
|
|
5936
|
+
/**
|
5937
|
+
* Set the numbered_parameters value of the current scope.
|
5938
|
+
*/
|
5939
|
+
static inline void
|
5940
|
+
pm_parser_numbered_parameters_set(pm_parser_t *parser, uint8_t numbered_parameters) {
|
5941
|
+
parser->current_scope->numbered_parameters = numbered_parameters;
|
5942
|
+
}
|
5943
|
+
|
5796
5944
|
/**
|
5797
5945
|
* Add a local variable from a location to the current scope.
|
5798
5946
|
*/
|
@@ -5869,12 +6017,12 @@ static inline size_t
|
|
5869
6017
|
char_is_identifier_start(pm_parser_t *parser, const uint8_t *b) {
|
5870
6018
|
if (parser->encoding_changed) {
|
5871
6019
|
size_t width;
|
5872
|
-
if ((width = parser->encoding
|
6020
|
+
if ((width = parser->encoding->alpha_char(b, parser->end - b)) != 0) {
|
5873
6021
|
return width;
|
5874
6022
|
} else if (*b == '_') {
|
5875
6023
|
return 1;
|
5876
6024
|
} else if (*b >= 0x80) {
|
5877
|
-
return parser->encoding
|
6025
|
+
return parser->encoding->char_width(b, parser->end - b);
|
5878
6026
|
} else {
|
5879
6027
|
return 0;
|
5880
6028
|
}
|
@@ -5885,6 +6033,19 @@ char_is_identifier_start(pm_parser_t *parser, const uint8_t *b) {
|
|
5885
6033
|
}
|
5886
6034
|
}
|
5887
6035
|
|
6036
|
+
/**
|
6037
|
+
* Similar to char_is_identifier but this function assumes that the encoding
|
6038
|
+
* has not been changed.
|
6039
|
+
*/
|
6040
|
+
static inline size_t
|
6041
|
+
char_is_identifier_utf8(const uint8_t *b, const uint8_t *end) {
|
6042
|
+
if (*b < 0x80) {
|
6043
|
+
return (*b == '_') || (pm_encoding_unicode_table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT ? 1 : 0);
|
6044
|
+
} else {
|
6045
|
+
return (size_t) (pm_encoding_utf_8_alnum_char(b, end - b) || 1u);
|
6046
|
+
}
|
6047
|
+
}
|
6048
|
+
|
5888
6049
|
/**
|
5889
6050
|
* Like the above, this function is also used extremely frequently to lex all of
|
5890
6051
|
* the identifiers in a source file once the first character has been found. So
|
@@ -5894,20 +6055,17 @@ static inline size_t
|
|
5894
6055
|
char_is_identifier(pm_parser_t *parser, const uint8_t *b) {
|
5895
6056
|
if (parser->encoding_changed) {
|
5896
6057
|
size_t width;
|
5897
|
-
if ((width = parser->encoding
|
6058
|
+
if ((width = parser->encoding->alnum_char(b, parser->end - b)) != 0) {
|
5898
6059
|
return width;
|
5899
6060
|
} else if (*b == '_') {
|
5900
6061
|
return 1;
|
5901
6062
|
} else if (*b >= 0x80) {
|
5902
|
-
return parser->encoding
|
6063
|
+
return parser->encoding->char_width(b, parser->end - b);
|
5903
6064
|
} else {
|
5904
6065
|
return 0;
|
5905
6066
|
}
|
5906
|
-
} else if (*b < 0x80) {
|
5907
|
-
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT ? 1 : 0) || (*b == '_');
|
5908
|
-
} else {
|
5909
|
-
return (size_t) (pm_encoding_utf_8_alnum_char(b, parser->end - b) || 1u);
|
5910
6067
|
}
|
6068
|
+
return char_is_identifier_utf8(b, parser->end);
|
5911
6069
|
}
|
5912
6070
|
|
5913
6071
|
// Here we're defining a perfect hash for the characters that are allowed in
|
@@ -6082,195 +6240,18 @@ next_newline(const uint8_t *cursor, ptrdiff_t length) {
|
|
6082
6240
|
*/
|
6083
6241
|
static bool
|
6084
6242
|
parser_lex_magic_comment_encoding_value(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) {
|
6085
|
-
|
6086
|
-
|
6087
|
-
// First, we're going to call out to a user-defined callback if one was
|
6088
|
-
// provided. If they return an encoding struct that we can use, then we'll
|
6089
|
-
// use that here.
|
6090
|
-
if (parser->encoding_decode_callback != NULL) {
|
6091
|
-
pm_encoding_t *encoding = parser->encoding_decode_callback(parser, start, width);
|
6243
|
+
const pm_encoding_t *encoding = pm_encoding_find(start, end);
|
6092
6244
|
|
6093
|
-
|
6094
|
-
|
6095
|
-
|
6096
|
-
}
|
6097
|
-
}
|
6098
|
-
|
6099
|
-
// Next, we're going to check for UTF-8. This is the most common encoding.
|
6100
|
-
// utf-8 can contain extra information at the end about the platform it is
|
6101
|
-
// encoded on, such as utf-8-mac or utf-8-unix. We'll ignore those suffixes.
|
6102
|
-
if ((start + 5 <= end) && (pm_strncasecmp(start, (const uint8_t *) "utf-8", 5) == 0)) {
|
6103
|
-
// We need to explicitly handle utf-8-hfs, as that one needs to switch
|
6104
|
-
// over to being utf8-mac.
|
6105
|
-
if (width == 9 && (pm_strncasecmp(start + 5, (const uint8_t *) "-hfs", 4) == 0)) {
|
6106
|
-
parser->encoding = pm_encoding_utf8_mac;
|
6245
|
+
if (encoding != NULL) {
|
6246
|
+
if (encoding != PM_ENCODING_UTF_8_ENTRY) {
|
6247
|
+
parser->encoding = encoding;
|
6107
6248
|
parser->encoding_changed = true;
|
6108
6249
|
if (parser->encoding_changed_callback != NULL) parser->encoding_changed_callback(parser);
|
6109
|
-
return true;
|
6110
6250
|
}
|
6111
6251
|
|
6112
|
-
// We don't need to do anything here because the default encoding is
|
6113
|
-
// already UTF-8. We'll just return.
|
6114
6252
|
return true;
|
6115
6253
|
}
|
6116
6254
|
|
6117
|
-
// Next, we're going to loop through each of the encodings that we handle
|
6118
|
-
// explicitly. If we found one that we understand, we'll use that value.
|
6119
|
-
#define ENCODING1(value, prebuilt) \
|
6120
|
-
if (width == sizeof(value) - 1 && start + width <= end && pm_strncasecmp(start, (const uint8_t *) value, width) == 0) { \
|
6121
|
-
parser->encoding = prebuilt; \
|
6122
|
-
parser->encoding_changed = true; \
|
6123
|
-
if (parser->encoding_changed_callback != NULL) parser->encoding_changed_callback(parser); \
|
6124
|
-
return true; \
|
6125
|
-
}
|
6126
|
-
|
6127
|
-
// A convenience macros for comparing two aliases for the same encoding.
|
6128
|
-
#define ENCODING2(value1, value2, prebuilt) ENCODING1(value1, prebuilt) ENCODING1(value2, prebuilt)
|
6129
|
-
|
6130
|
-
if (width >= 3) {
|
6131
|
-
switch (*start) {
|
6132
|
-
case 'A': case 'a':
|
6133
|
-
ENCODING1("ASCII", pm_encoding_ascii);
|
6134
|
-
ENCODING1("ASCII-8BIT", pm_encoding_ascii_8bit);
|
6135
|
-
ENCODING1("ANSI_X3.4-1968", pm_encoding_ascii);
|
6136
|
-
break;
|
6137
|
-
case 'B': case 'b':
|
6138
|
-
ENCODING1("BINARY", pm_encoding_ascii_8bit);
|
6139
|
-
ENCODING1("Big5", pm_encoding_big5);
|
6140
|
-
ENCODING1("Big5-HKSCS", pm_encoding_big5_hkscs);
|
6141
|
-
ENCODING1("Big5-UAO", pm_encoding_big5_uao);
|
6142
|
-
break;
|
6143
|
-
case 'C': case 'c':
|
6144
|
-
ENCODING1("CP437", pm_encoding_ibm437);
|
6145
|
-
ENCODING1("CP720", pm_encoding_ibm720);
|
6146
|
-
ENCODING1("CP737", pm_encoding_ibm737);
|
6147
|
-
ENCODING1("CP775", pm_encoding_ibm775);
|
6148
|
-
ENCODING1("CP850", pm_encoding_cp850);
|
6149
|
-
ENCODING1("CP852", pm_encoding_cp852);
|
6150
|
-
ENCODING1("CP855", pm_encoding_cp855);
|
6151
|
-
ENCODING1("CP857", pm_encoding_ibm857);
|
6152
|
-
ENCODING1("CP860", pm_encoding_ibm860);
|
6153
|
-
ENCODING1("CP861", pm_encoding_ibm861);
|
6154
|
-
ENCODING1("CP862", pm_encoding_ibm862);
|
6155
|
-
ENCODING1("CP864", pm_encoding_ibm864);
|
6156
|
-
ENCODING1("CP865", pm_encoding_ibm865);
|
6157
|
-
ENCODING1("CP866", pm_encoding_ibm866);
|
6158
|
-
ENCODING1("CP869", pm_encoding_ibm869);
|
6159
|
-
ENCODING1("CP874", pm_encoding_windows_874);
|
6160
|
-
ENCODING1("CP878", pm_encoding_koi8_r);
|
6161
|
-
ENCODING1("CP863", pm_encoding_ibm863);
|
6162
|
-
ENCODING2("CP932", "csWindows31J", pm_encoding_windows_31j);
|
6163
|
-
ENCODING1("CP936", pm_encoding_gbk);
|
6164
|
-
ENCODING1("CP1250", pm_encoding_windows_1250);
|
6165
|
-
ENCODING1("CP1251", pm_encoding_windows_1251);
|
6166
|
-
ENCODING1("CP1252", pm_encoding_windows_1252);
|
6167
|
-
ENCODING1("CP1253", pm_encoding_windows_1253);
|
6168
|
-
ENCODING1("CP1254", pm_encoding_windows_1254);
|
6169
|
-
ENCODING1("CP1255", pm_encoding_windows_1255);
|
6170
|
-
ENCODING1("CP1256", pm_encoding_windows_1256);
|
6171
|
-
ENCODING1("CP1257", pm_encoding_windows_1257);
|
6172
|
-
ENCODING1("CP1258", pm_encoding_windows_1258);
|
6173
|
-
ENCODING1("CP51932", pm_encoding_cp51932);
|
6174
|
-
ENCODING1("CP65001", pm_encoding_utf_8);
|
6175
|
-
break;
|
6176
|
-
case 'E': case 'e':
|
6177
|
-
ENCODING2("EUC-JP", "eucJP", pm_encoding_euc_jp);
|
6178
|
-
ENCODING1("external", pm_encoding_utf_8);
|
6179
|
-
break;
|
6180
|
-
case 'F': case 'f':
|
6181
|
-
ENCODING1("filesystem", pm_encoding_utf_8);
|
6182
|
-
break;
|
6183
|
-
case 'G': case 'g':
|
6184
|
-
ENCODING1("GB1988", pm_encoding_gb1988);
|
6185
|
-
ENCODING1("GBK", pm_encoding_gbk);
|
6186
|
-
break;
|
6187
|
-
case 'I': case 'i':
|
6188
|
-
ENCODING1("IBM437", pm_encoding_ibm437);
|
6189
|
-
ENCODING1("IBM720", pm_encoding_ibm720);
|
6190
|
-
ENCODING1("IBM737", pm_encoding_ibm737);
|
6191
|
-
ENCODING1("IBM775", pm_encoding_ibm775);
|
6192
|
-
ENCODING1("IBM850", pm_encoding_cp850);
|
6193
|
-
ENCODING1("IBM852", pm_encoding_ibm852);
|
6194
|
-
ENCODING1("IBM855", pm_encoding_ibm855);
|
6195
|
-
ENCODING1("IBM857", pm_encoding_ibm857);
|
6196
|
-
ENCODING1("IBM860", pm_encoding_ibm860);
|
6197
|
-
ENCODING1("IBM861", pm_encoding_ibm861);
|
6198
|
-
ENCODING1("IBM862", pm_encoding_ibm862);
|
6199
|
-
ENCODING1("IBM863", pm_encoding_ibm863);
|
6200
|
-
ENCODING1("IBM864", pm_encoding_ibm864);
|
6201
|
-
ENCODING1("IBM865", pm_encoding_ibm865);
|
6202
|
-
ENCODING1("IBM866", pm_encoding_ibm866);
|
6203
|
-
ENCODING1("IBM869", pm_encoding_ibm869);
|
6204
|
-
ENCODING2("ISO-8859-1", "ISO8859-1", pm_encoding_iso_8859_1);
|
6205
|
-
ENCODING2("ISO-8859-2", "ISO8859-2", pm_encoding_iso_8859_2);
|
6206
|
-
ENCODING2("ISO-8859-3", "ISO8859-3", pm_encoding_iso_8859_3);
|
6207
|
-
ENCODING2("ISO-8859-4", "ISO8859-4", pm_encoding_iso_8859_4);
|
6208
|
-
ENCODING2("ISO-8859-5", "ISO8859-5", pm_encoding_iso_8859_5);
|
6209
|
-
ENCODING2("ISO-8859-6", "ISO8859-6", pm_encoding_iso_8859_6);
|
6210
|
-
ENCODING2("ISO-8859-7", "ISO8859-7", pm_encoding_iso_8859_7);
|
6211
|
-
ENCODING2("ISO-8859-8", "ISO8859-8", pm_encoding_iso_8859_8);
|
6212
|
-
ENCODING2("ISO-8859-9", "ISO8859-9", pm_encoding_iso_8859_9);
|
6213
|
-
ENCODING2("ISO-8859-10", "ISO8859-10", pm_encoding_iso_8859_10);
|
6214
|
-
ENCODING2("ISO-8859-11", "ISO8859-11", pm_encoding_iso_8859_11);
|
6215
|
-
ENCODING2("ISO-8859-13", "ISO8859-13", pm_encoding_iso_8859_13);
|
6216
|
-
ENCODING2("ISO-8859-14", "ISO8859-14", pm_encoding_iso_8859_14);
|
6217
|
-
ENCODING2("ISO-8859-15", "ISO8859-15", pm_encoding_iso_8859_15);
|
6218
|
-
ENCODING2("ISO-8859-16", "ISO8859-16", pm_encoding_iso_8859_16);
|
6219
|
-
break;
|
6220
|
-
case 'K': case 'k':
|
6221
|
-
ENCODING1("KOI8-R", pm_encoding_koi8_r);
|
6222
|
-
break;
|
6223
|
-
case 'L': case 'l':
|
6224
|
-
ENCODING1("locale", pm_encoding_utf_8);
|
6225
|
-
break;
|
6226
|
-
case 'M': case 'm':
|
6227
|
-
ENCODING1("macCentEuro", pm_encoding_mac_cent_euro);
|
6228
|
-
ENCODING1("macCroatian", pm_encoding_mac_croatian);
|
6229
|
-
ENCODING1("macCyrillic", pm_encoding_mac_cyrillic);
|
6230
|
-
ENCODING1("macGreek", pm_encoding_mac_greek);
|
6231
|
-
ENCODING1("macIceland", pm_encoding_mac_iceland);
|
6232
|
-
ENCODING1("macRoman", pm_encoding_mac_roman);
|
6233
|
-
ENCODING1("macRomania", pm_encoding_mac_romania);
|
6234
|
-
ENCODING1("macThai", pm_encoding_mac_thai);
|
6235
|
-
ENCODING1("macTurkish", pm_encoding_mac_turkish);
|
6236
|
-
ENCODING1("macUkraine", pm_encoding_mac_ukraine);
|
6237
|
-
break;
|
6238
|
-
case 'P': case 'p':
|
6239
|
-
ENCODING1("PCK", pm_encoding_windows_31j);
|
6240
|
-
break;
|
6241
|
-
case 'S': case 's':
|
6242
|
-
ENCODING1("Shift_JIS", pm_encoding_shift_jis);
|
6243
|
-
ENCODING1("SJIS", pm_encoding_windows_31j);
|
6244
|
-
break;
|
6245
|
-
case 'T': case 't':
|
6246
|
-
ENCODING1("TIS-620", pm_encoding_tis_620);
|
6247
|
-
break;
|
6248
|
-
case 'U': case 'u':
|
6249
|
-
ENCODING1("US-ASCII", pm_encoding_ascii);
|
6250
|
-
ENCODING2("UTF8-MAC", "UTF-8-HFS", pm_encoding_utf8_mac);
|
6251
|
-
break;
|
6252
|
-
case 'W': case 'w':
|
6253
|
-
ENCODING1("Windows-31J", pm_encoding_windows_31j);
|
6254
|
-
ENCODING1("Windows-874", pm_encoding_windows_874);
|
6255
|
-
ENCODING1("Windows-1250", pm_encoding_windows_1250);
|
6256
|
-
ENCODING1("Windows-1251", pm_encoding_windows_1251);
|
6257
|
-
ENCODING1("Windows-1252", pm_encoding_windows_1252);
|
6258
|
-
ENCODING1("Windows-1253", pm_encoding_windows_1253);
|
6259
|
-
ENCODING1("Windows-1254", pm_encoding_windows_1254);
|
6260
|
-
ENCODING1("Windows-1255", pm_encoding_windows_1255);
|
6261
|
-
ENCODING1("Windows-1256", pm_encoding_windows_1256);
|
6262
|
-
ENCODING1("Windows-1257", pm_encoding_windows_1257);
|
6263
|
-
ENCODING1("Windows-1258", pm_encoding_windows_1258);
|
6264
|
-
break;
|
6265
|
-
case '6':
|
6266
|
-
ENCODING1("646", pm_encoding_ascii);
|
6267
|
-
break;
|
6268
|
-
}
|
6269
|
-
}
|
6270
|
-
|
6271
|
-
#undef ENCODING2
|
6272
|
-
#undef ENCODING1
|
6273
|
-
|
6274
6255
|
return false;
|
6275
6256
|
}
|
6276
6257
|
|
@@ -6319,7 +6300,7 @@ parser_lex_magic_comment_encoding(pm_parser_t *parser) {
|
|
6319
6300
|
}
|
6320
6301
|
|
6321
6302
|
const uint8_t *value_start = cursor;
|
6322
|
-
while ((*cursor == '-' || *cursor == '_' || parser->encoding
|
6303
|
+
while ((*cursor == '-' || *cursor == '_' || parser->encoding->alnum_char(cursor, 1)) && ++cursor < end);
|
6323
6304
|
|
6324
6305
|
if (!parser_lex_magic_comment_encoding_value(parser, value_start, cursor)) {
|
6325
6306
|
// If we were unable to parse the encoding value, then we've got an
|
@@ -6353,7 +6334,7 @@ pm_char_is_magic_comment_key_delimiter(const uint8_t b) {
|
|
6353
6334
|
*/
|
6354
6335
|
static inline const uint8_t *
|
6355
6336
|
parser_lex_magic_comment_emacs_marker(pm_parser_t *parser, const uint8_t *cursor, const uint8_t *end) {
|
6356
|
-
while ((cursor + 3 <= end) && (cursor = pm_memchr(cursor, '-', (size_t) (end - cursor), parser->encoding_changed,
|
6337
|
+
while ((cursor + 3 <= end) && (cursor = pm_memchr(cursor, '-', (size_t) (end - cursor), parser->encoding_changed, parser->encoding)) != NULL) {
|
6357
6338
|
if (cursor + 3 <= end && cursor[1] == '*' && cursor[2] == '-') {
|
6358
6339
|
return cursor;
|
6359
6340
|
}
|
@@ -6443,7 +6424,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
|
|
6443
6424
|
// underscores. We only need to do this if there _is_ a dash in the key.
|
6444
6425
|
pm_string_t key;
|
6445
6426
|
const size_t key_length = (size_t) (key_end - key_start);
|
6446
|
-
const uint8_t *dash = pm_memchr(key_start, '-', (size_t) key_length, parser->encoding_changed,
|
6427
|
+
const uint8_t *dash = pm_memchr(key_start, '-', (size_t) key_length, parser->encoding_changed, parser->encoding);
|
6447
6428
|
|
6448
6429
|
if (dash == NULL) {
|
6449
6430
|
pm_string_shared_init(&key, key_start, key_end);
|
@@ -6455,7 +6436,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
|
|
6455
6436
|
memcpy(buffer, key_start, width);
|
6456
6437
|
buffer[dash - key_start] = '_';
|
6457
6438
|
|
6458
|
-
while ((dash = pm_memchr(dash + 1, '-', (size_t) (key_end - dash - 1), parser->encoding_changed,
|
6439
|
+
while ((dash = pm_memchr(dash + 1, '-', (size_t) (key_end - dash - 1), parser->encoding_changed, parser->encoding)) != NULL) {
|
6459
6440
|
buffer[dash - key_start] = '_';
|
6460
6441
|
}
|
6461
6442
|
|
@@ -6530,6 +6511,7 @@ context_terminator(pm_context_t context, pm_token_t *token) {
|
|
6530
6511
|
case PM_CONTEXT_ELSE:
|
6531
6512
|
case PM_CONTEXT_FOR:
|
6532
6513
|
case PM_CONTEXT_ENSURE:
|
6514
|
+
case PM_CONTEXT_ENSURE_DEF:
|
6533
6515
|
return token->type == PM_TOKEN_KEYWORD_END;
|
6534
6516
|
case PM_CONTEXT_FOR_INDEX:
|
6535
6517
|
return token->type == PM_TOKEN_KEYWORD_IN;
|
@@ -6550,8 +6532,10 @@ context_terminator(pm_context_t context, pm_token_t *token) {
|
|
6550
6532
|
return token->type == PM_TOKEN_PARENTHESIS_RIGHT;
|
6551
6533
|
case PM_CONTEXT_BEGIN:
|
6552
6534
|
case PM_CONTEXT_RESCUE:
|
6535
|
+
case PM_CONTEXT_RESCUE_DEF:
|
6553
6536
|
return token->type == PM_TOKEN_KEYWORD_ENSURE || token->type == PM_TOKEN_KEYWORD_RESCUE || token->type == PM_TOKEN_KEYWORD_ELSE || token->type == PM_TOKEN_KEYWORD_END;
|
6554
6537
|
case PM_CONTEXT_RESCUE_ELSE:
|
6538
|
+
case PM_CONTEXT_RESCUE_ELSE_DEF:
|
6555
6539
|
return token->type == PM_TOKEN_KEYWORD_ENSURE || token->type == PM_TOKEN_KEYWORD_END;
|
6556
6540
|
case PM_CONTEXT_LAMBDA_BRACES:
|
6557
6541
|
return token->type == PM_TOKEN_BRACE_RIGHT;
|
@@ -6617,6 +6601,10 @@ context_def_p(pm_parser_t *parser) {
|
|
6617
6601
|
while (context_node != NULL) {
|
6618
6602
|
switch (context_node->context) {
|
6619
6603
|
case PM_CONTEXT_DEF:
|
6604
|
+
case PM_CONTEXT_DEF_PARAMS:
|
6605
|
+
case PM_CONTEXT_ENSURE_DEF:
|
6606
|
+
case PM_CONTEXT_RESCUE_DEF:
|
6607
|
+
case PM_CONTEXT_RESCUE_ELSE_DEF:
|
6620
6608
|
return true;
|
6621
6609
|
case PM_CONTEXT_CLASS:
|
6622
6610
|
case PM_CONTEXT_MODULE:
|
@@ -6979,9 +6967,16 @@ lex_identifier(pm_parser_t *parser, bool previous_command_start) {
|
|
6979
6967
|
const uint8_t *end = parser->end;
|
6980
6968
|
const uint8_t *current_start = parser->current.start;
|
6981
6969
|
const uint8_t *current_end = parser->current.end;
|
6970
|
+
bool encoding_changed = parser->encoding_changed;
|
6982
6971
|
|
6983
|
-
|
6984
|
-
current_end
|
6972
|
+
if (encoding_changed) {
|
6973
|
+
while (current_end < end && (width = char_is_identifier(parser, current_end)) > 0) {
|
6974
|
+
current_end += width;
|
6975
|
+
}
|
6976
|
+
} else {
|
6977
|
+
while (current_end < end && (width = char_is_identifier_utf8(current_end, end)) > 0) {
|
6978
|
+
current_end += width;
|
6979
|
+
}
|
6985
6980
|
}
|
6986
6981
|
parser->current.end = current_end;
|
6987
6982
|
|
@@ -7099,8 +7094,8 @@ lex_identifier(pm_parser_t *parser, bool previous_command_start) {
|
|
7099
7094
|
}
|
7100
7095
|
}
|
7101
7096
|
|
7102
|
-
if (
|
7103
|
-
return parser->encoding
|
7097
|
+
if (encoding_changed) {
|
7098
|
+
return parser->encoding->isupper_char(current_start, end - current_start) ? PM_TOKEN_CONSTANT : PM_TOKEN_IDENTIFIER;
|
7104
7099
|
}
|
7105
7100
|
return pm_encoding_utf_8_isupper_char(current_start, end - current_start) ? PM_TOKEN_CONSTANT : PM_TOKEN_IDENTIFIER;
|
7106
7101
|
}
|
@@ -7314,7 +7309,18 @@ escape_byte(uint8_t value, const uint8_t flags) {
|
|
7314
7309
|
* Write a unicode codepoint to the given buffer.
|
7315
7310
|
*/
|
7316
7311
|
static inline void
|
7317
|
-
escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t *start, const uint8_t *end, uint32_t value) {
|
7312
|
+
escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t flags, const uint8_t *start, const uint8_t *end, uint32_t value) {
|
7313
|
+
// \u escape sequences in string-like structures implicitly change the
|
7314
|
+
// encoding to UTF-8 if they are >= 0x80 or if they are used in a character
|
7315
|
+
// literal.
|
7316
|
+
if (value >= 0x80 || flags & PM_ESCAPE_FLAG_SINGLE) {
|
7317
|
+
if (parser->explicit_encoding != NULL && parser->explicit_encoding != PM_ENCODING_UTF_8_ENTRY) {
|
7318
|
+
PM_PARSER_ERR_FORMAT(parser, start, end, PM_ERR_MIXED_ENCODING, parser->explicit_encoding->name);
|
7319
|
+
}
|
7320
|
+
|
7321
|
+
parser->explicit_encoding = PM_ENCODING_UTF_8_ENTRY;
|
7322
|
+
}
|
7323
|
+
|
7318
7324
|
if (value <= 0x7F) { // 0xxxxxxx
|
7319
7325
|
pm_buffer_append_byte(buffer, (uint8_t) value);
|
7320
7326
|
} else if (value <= 0x7FF) { // 110xxxxx 10xxxxxx
|
@@ -7337,6 +7343,23 @@ escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t *st
|
|
7337
7343
|
}
|
7338
7344
|
}
|
7339
7345
|
|
7346
|
+
/**
|
7347
|
+
* When you're writing a byte to the unescape buffer, if the byte is non-ASCII
|
7348
|
+
* (i.e., the top bit is set) then it locks in the encoding.
|
7349
|
+
*/
|
7350
|
+
static inline void
|
7351
|
+
escape_write_byte_encoded(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t byte) {
|
7352
|
+
if (byte >= 0x80) {
|
7353
|
+
if (parser->explicit_encoding != NULL && parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY && parser->encoding != PM_ENCODING_UTF_8_ENTRY) {
|
7354
|
+
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_MIXED_ENCODING, parser->encoding->name);
|
7355
|
+
}
|
7356
|
+
|
7357
|
+
parser->explicit_encoding = parser->encoding;
|
7358
|
+
}
|
7359
|
+
|
7360
|
+
pm_buffer_append_byte(buffer, byte);
|
7361
|
+
}
|
7362
|
+
|
7340
7363
|
/**
|
7341
7364
|
* The regular expression engine doesn't support the same escape sequences as
|
7342
7365
|
* Ruby does. So first we have to read the escape sequence, and then we have to
|
@@ -7353,7 +7376,7 @@ escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t *st
|
|
7353
7376
|
* source so that the regular expression engine will perform its own unescaping.
|
7354
7377
|
*/
|
7355
7378
|
static inline void
|
7356
|
-
escape_write_byte(pm_buffer_t *buffer, uint8_t flags, uint8_t byte) {
|
7379
|
+
escape_write_byte(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags, uint8_t byte) {
|
7357
7380
|
if (flags & PM_ESCAPE_FLAG_REGEXP) {
|
7358
7381
|
pm_buffer_append_bytes(buffer, (const uint8_t *) "\\x", 2);
|
7359
7382
|
|
@@ -7372,7 +7395,7 @@ escape_write_byte(pm_buffer_t *buffer, uint8_t flags, uint8_t byte) {
|
|
7372
7395
|
pm_buffer_append_byte(buffer, (uint8_t) (byte2 + '0'));
|
7373
7396
|
}
|
7374
7397
|
} else {
|
7375
|
-
|
7398
|
+
escape_write_byte_encoded(parser, buffer, byte);
|
7376
7399
|
}
|
7377
7400
|
}
|
7378
7401
|
|
@@ -7384,57 +7407,57 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) {
|
|
7384
7407
|
switch (peek(parser)) {
|
7385
7408
|
case '\\': {
|
7386
7409
|
parser->current.end++;
|
7387
|
-
|
7410
|
+
escape_write_byte_encoded(parser, buffer, escape_byte('\\', flags));
|
7388
7411
|
return;
|
7389
7412
|
}
|
7390
7413
|
case '\'': {
|
7391
7414
|
parser->current.end++;
|
7392
|
-
|
7415
|
+
escape_write_byte_encoded(parser, buffer, escape_byte('\'', flags));
|
7393
7416
|
return;
|
7394
7417
|
}
|
7395
7418
|
case 'a': {
|
7396
7419
|
parser->current.end++;
|
7397
|
-
|
7420
|
+
escape_write_byte_encoded(parser, buffer, escape_byte('\a', flags));
|
7398
7421
|
return;
|
7399
7422
|
}
|
7400
7423
|
case 'b': {
|
7401
7424
|
parser->current.end++;
|
7402
|
-
|
7425
|
+
escape_write_byte_encoded(parser, buffer, escape_byte('\b', flags));
|
7403
7426
|
return;
|
7404
7427
|
}
|
7405
7428
|
case 'e': {
|
7406
7429
|
parser->current.end++;
|
7407
|
-
|
7430
|
+
escape_write_byte_encoded(parser, buffer, escape_byte('\033', flags));
|
7408
7431
|
return;
|
7409
7432
|
}
|
7410
7433
|
case 'f': {
|
7411
7434
|
parser->current.end++;
|
7412
|
-
|
7435
|
+
escape_write_byte_encoded(parser, buffer, escape_byte('\f', flags));
|
7413
7436
|
return;
|
7414
7437
|
}
|
7415
7438
|
case 'n': {
|
7416
7439
|
parser->current.end++;
|
7417
|
-
|
7440
|
+
escape_write_byte_encoded(parser, buffer, escape_byte('\n', flags));
|
7418
7441
|
return;
|
7419
7442
|
}
|
7420
7443
|
case 'r': {
|
7421
7444
|
parser->current.end++;
|
7422
|
-
|
7445
|
+
escape_write_byte_encoded(parser, buffer, escape_byte('\r', flags));
|
7423
7446
|
return;
|
7424
7447
|
}
|
7425
7448
|
case 's': {
|
7426
7449
|
parser->current.end++;
|
7427
|
-
|
7450
|
+
escape_write_byte_encoded(parser, buffer, escape_byte(' ', flags));
|
7428
7451
|
return;
|
7429
7452
|
}
|
7430
7453
|
case 't': {
|
7431
7454
|
parser->current.end++;
|
7432
|
-
|
7455
|
+
escape_write_byte_encoded(parser, buffer, escape_byte('\t', flags));
|
7433
7456
|
return;
|
7434
7457
|
}
|
7435
7458
|
case 'v': {
|
7436
7459
|
parser->current.end++;
|
7437
|
-
|
7460
|
+
escape_write_byte_encoded(parser, buffer, escape_byte('\v', flags));
|
7438
7461
|
return;
|
7439
7462
|
}
|
7440
7463
|
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': {
|
@@ -7451,7 +7474,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) {
|
|
7451
7474
|
}
|
7452
7475
|
}
|
7453
7476
|
|
7454
|
-
|
7477
|
+
escape_write_byte_encoded(parser, buffer, value);
|
7455
7478
|
return;
|
7456
7479
|
}
|
7457
7480
|
case 'x': {
|
@@ -7473,7 +7496,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) {
|
|
7473
7496
|
if (flags & PM_ESCAPE_FLAG_REGEXP) {
|
7474
7497
|
pm_buffer_append_bytes(buffer, start, (size_t) (parser->current.end - start));
|
7475
7498
|
} else {
|
7476
|
-
|
7499
|
+
escape_write_byte_encoded(parser, buffer, value);
|
7477
7500
|
}
|
7478
7501
|
} else {
|
7479
7502
|
pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_HEXADECIMAL);
|
@@ -7497,7 +7520,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) {
|
|
7497
7520
|
if (flags & PM_ESCAPE_FLAG_REGEXP) {
|
7498
7521
|
pm_buffer_append_bytes(buffer, start, (size_t) (parser->current.end + 4 - start));
|
7499
7522
|
} else {
|
7500
|
-
escape_write_unicode(parser, buffer, start, parser->current.end + 4, value);
|
7523
|
+
escape_write_unicode(parser, buffer, flags, start, parser->current.end + 4, value);
|
7501
7524
|
}
|
7502
7525
|
|
7503
7526
|
parser->current.end += 4;
|
@@ -7531,13 +7554,14 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) {
|
|
7531
7554
|
|
7532
7555
|
if (!(flags & PM_ESCAPE_FLAG_REGEXP)) {
|
7533
7556
|
uint32_t value = escape_unicode(unicode_start, hexadecimal_length);
|
7534
|
-
escape_write_unicode(parser, buffer, unicode_start, parser->current.end, value);
|
7557
|
+
escape_write_unicode(parser, buffer, flags, unicode_start, parser->current.end, value);
|
7535
7558
|
}
|
7536
7559
|
|
7537
7560
|
parser->current.end += pm_strspn_whitespace(parser->current.end, parser->end - parser->current.end);
|
7538
7561
|
}
|
7539
7562
|
|
7540
|
-
// ?\u{nnnn} character literal should contain only one codepoint
|
7563
|
+
// ?\u{nnnn} character literal should contain only one codepoint
|
7564
|
+
// and cannot be like ?\u{nnnn mmmm}.
|
7541
7565
|
if (flags & PM_ESCAPE_FLAG_SINGLE && codepoints_count > 1) {
|
7542
7566
|
pm_parser_err(parser, extra_codepoints_start, parser->current.end - 1, PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL);
|
7543
7567
|
}
|
@@ -7568,7 +7592,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) {
|
|
7568
7592
|
switch (peeked) {
|
7569
7593
|
case '?': {
|
7570
7594
|
parser->current.end++;
|
7571
|
-
escape_write_byte(buffer, flags, escape_byte(0x7f, flags));
|
7595
|
+
escape_write_byte(parser, buffer, flags, escape_byte(0x7f, flags));
|
7572
7596
|
return;
|
7573
7597
|
}
|
7574
7598
|
case '\\':
|
@@ -7586,7 +7610,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) {
|
|
7586
7610
|
}
|
7587
7611
|
|
7588
7612
|
parser->current.end++;
|
7589
|
-
escape_write_byte(buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL));
|
7613
|
+
escape_write_byte(parser, buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL));
|
7590
7614
|
return;
|
7591
7615
|
}
|
7592
7616
|
}
|
@@ -7608,7 +7632,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) {
|
|
7608
7632
|
switch (peeked) {
|
7609
7633
|
case '?': {
|
7610
7634
|
parser->current.end++;
|
7611
|
-
escape_write_byte(buffer, flags, escape_byte(0x7f, flags));
|
7635
|
+
escape_write_byte(parser, buffer, flags, escape_byte(0x7f, flags));
|
7612
7636
|
return;
|
7613
7637
|
}
|
7614
7638
|
case '\\':
|
@@ -7626,7 +7650,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) {
|
|
7626
7650
|
}
|
7627
7651
|
|
7628
7652
|
parser->current.end++;
|
7629
|
-
escape_write_byte(buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL));
|
7653
|
+
escape_write_byte(parser, buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL));
|
7630
7654
|
return;
|
7631
7655
|
}
|
7632
7656
|
}
|
@@ -7661,20 +7685,20 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t flags) {
|
|
7661
7685
|
}
|
7662
7686
|
|
7663
7687
|
parser->current.end++;
|
7664
|
-
escape_write_byte(buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_META));
|
7688
|
+
escape_write_byte(parser, buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_META));
|
7665
7689
|
return;
|
7666
7690
|
}
|
7667
7691
|
case '\r': {
|
7668
7692
|
if (peek_offset(parser, 1) == '\n') {
|
7669
7693
|
parser->current.end += 2;
|
7670
|
-
|
7694
|
+
escape_write_byte_encoded(parser, buffer, escape_byte('\n', flags));
|
7671
7695
|
return;
|
7672
7696
|
}
|
7673
7697
|
}
|
7674
7698
|
/* fallthrough */
|
7675
7699
|
default: {
|
7676
7700
|
if (parser->current.end < parser->end) {
|
7677
|
-
|
7701
|
+
escape_write_byte_encoded(parser, buffer, *parser->current.end++);
|
7678
7702
|
}
|
7679
7703
|
return;
|
7680
7704
|
}
|
@@ -7737,13 +7761,12 @@ lex_question_mark(pm_parser_t *parser) {
|
|
7737
7761
|
|
7738
7762
|
return PM_TOKEN_CHARACTER_LITERAL;
|
7739
7763
|
} else {
|
7740
|
-
size_t encoding_width = parser->encoding
|
7764
|
+
size_t encoding_width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
|
7741
7765
|
|
7742
|
-
// Ternary operators can have a ? immediately followed by an identifier
|
7743
|
-
// an underscore. We check for this case
|
7766
|
+
// Ternary operators can have a ? immediately followed by an identifier
|
7767
|
+
// which starts with an underscore. We check for this case here.
|
7744
7768
|
if (
|
7745
|
-
!(parser->encoding
|
7746
|
-
peek(parser) == '_') ||
|
7769
|
+
!(parser->encoding->alnum_char(parser->current.end, parser->end - parser->current.end) || peek(parser) == '_') ||
|
7747
7770
|
(
|
7748
7771
|
(parser->current.end + encoding_width >= parser->end) ||
|
7749
7772
|
!char_is_identifier(parser, parser->current.end + encoding_width)
|
@@ -7809,8 +7832,7 @@ parser_comment(pm_parser_t *parser, pm_comment_type_t type) {
|
|
7809
7832
|
|
7810
7833
|
*comment = (pm_comment_t) {
|
7811
7834
|
.type = type,
|
7812
|
-
.
|
7813
|
-
.end = parser->current.end
|
7835
|
+
.location = { parser->current.start, parser->current.end }
|
7814
7836
|
};
|
7815
7837
|
|
7816
7838
|
return comment;
|
@@ -7861,7 +7883,7 @@ lex_embdoc(pm_parser_t *parser) {
|
|
7861
7883
|
parser->current.type = PM_TOKEN_EMBDOC_END;
|
7862
7884
|
parser_lex_callback(parser);
|
7863
7885
|
|
7864
|
-
comment->end = parser->current.end;
|
7886
|
+
comment->location.end = parser->current.end;
|
7865
7887
|
pm_list_append(&parser->comment_list, (pm_list_node_t *) comment);
|
7866
7888
|
|
7867
7889
|
return PM_TOKEN_EMBDOC_END;
|
@@ -7884,7 +7906,7 @@ lex_embdoc(pm_parser_t *parser) {
|
|
7884
7906
|
|
7885
7907
|
pm_parser_err_current(parser, PM_ERR_EMBDOC_TERM);
|
7886
7908
|
|
7887
|
-
comment->end = parser->current.end;
|
7909
|
+
comment->location.end = parser->current.end;
|
7888
7910
|
pm_list_append(&parser->comment_list, (pm_list_node_t *) comment);
|
7889
7911
|
|
7890
7912
|
return PM_TOKEN_EOF;
|
@@ -8592,6 +8614,7 @@ parser_lex(pm_parser_t *parser) {
|
|
8592
8614
|
// TODO: handle unterminated heredoc
|
8593
8615
|
}
|
8594
8616
|
|
8617
|
+
parser->explicit_encoding = NULL;
|
8595
8618
|
lex_mode_push(parser, (pm_lex_mode_t) {
|
8596
8619
|
.mode = PM_LEX_HEREDOC,
|
8597
8620
|
.as.heredoc = {
|
@@ -8998,7 +9021,7 @@ parser_lex(pm_parser_t *parser) {
|
|
8998
9021
|
(lex_state_p(parser, PM_LEX_STATE_FITEM) && (peek(parser) == 's')) ||
|
8999
9022
|
lex_state_spcarg_p(parser, space_seen)
|
9000
9023
|
) {
|
9001
|
-
if (!parser->encoding
|
9024
|
+
if (!parser->encoding->alnum_char(parser->current.end, parser->end - parser->current.end)) {
|
9002
9025
|
if (*parser->current.end >= 0x80) {
|
9003
9026
|
pm_parser_err_current(parser, PM_ERR_INVALID_PERCENT);
|
9004
9027
|
}
|
@@ -9021,7 +9044,7 @@ parser_lex(pm_parser_t *parser) {
|
|
9021
9044
|
// Delimiters for %-literals cannot be alphanumeric. We
|
9022
9045
|
// validate that here.
|
9023
9046
|
uint8_t delimiter = peek_offset(parser, 1);
|
9024
|
-
if (delimiter >= 0x80 || parser->encoding
|
9047
|
+
if (delimiter >= 0x80 || parser->encoding->alnum_char(&delimiter, 1)) {
|
9025
9048
|
pm_parser_err_current(parser, PM_ERR_INVALID_PERCENT);
|
9026
9049
|
goto lex_next_token;
|
9027
9050
|
}
|
@@ -9207,8 +9230,8 @@ parser_lex(pm_parser_t *parser) {
|
|
9207
9230
|
parser->current.type = PM_TOKEN___END__;
|
9208
9231
|
parser_lex_callback(parser);
|
9209
9232
|
|
9210
|
-
|
9211
|
-
|
9233
|
+
parser->data_loc.start = parser->current.start;
|
9234
|
+
parser->data_loc.end = parser->current.end;
|
9212
9235
|
|
9213
9236
|
LEX(PM_TOKEN_EOF);
|
9214
9237
|
}
|
@@ -9437,7 +9460,9 @@ parser_lex(pm_parser_t *parser) {
|
|
9437
9460
|
|
9438
9461
|
// If we were unable to find a breakpoint, then this token hits the
|
9439
9462
|
// end of the file.
|
9440
|
-
|
9463
|
+
parser->current.end = parser->end;
|
9464
|
+
pm_token_buffer_flush(parser, &token_buffer);
|
9465
|
+
LEX(PM_TOKEN_STRING_CONTENT);
|
9441
9466
|
}
|
9442
9467
|
case PM_LEX_REGEXP: {
|
9443
9468
|
// First, we'll set to start of this token to be the current end.
|
@@ -9545,7 +9570,9 @@ parser_lex(pm_parser_t *parser) {
|
|
9545
9570
|
case '\r':
|
9546
9571
|
parser->current.end++;
|
9547
9572
|
if (peek(parser) != '\n') {
|
9548
|
-
|
9573
|
+
if (lex_mode->as.regexp.terminator != '\r') {
|
9574
|
+
pm_token_buffer_push(&token_buffer, '\\');
|
9575
|
+
}
|
9549
9576
|
pm_token_buffer_push(&token_buffer, '\r');
|
9550
9577
|
break;
|
9551
9578
|
}
|
@@ -9573,7 +9600,20 @@ parser_lex(pm_parser_t *parser) {
|
|
9573
9600
|
escape_read(parser, &token_buffer.buffer, PM_ESCAPE_FLAG_REGEXP);
|
9574
9601
|
break;
|
9575
9602
|
default:
|
9576
|
-
if (lex_mode->as.regexp.terminator ==
|
9603
|
+
if (lex_mode->as.regexp.terminator == peeked) {
|
9604
|
+
// Some characters when they are used as the
|
9605
|
+
// terminator also receive an escape. They are
|
9606
|
+
// enumerated here.
|
9607
|
+
switch (peeked) {
|
9608
|
+
case '$': case ')': case '*': case '+':
|
9609
|
+
case '.': case '>': case '?': case ']':
|
9610
|
+
case '^': case '|': case '}':
|
9611
|
+
pm_token_buffer_push(&token_buffer, '\\');
|
9612
|
+
break;
|
9613
|
+
default:
|
9614
|
+
break;
|
9615
|
+
}
|
9616
|
+
|
9577
9617
|
pm_token_buffer_push(&token_buffer, peeked);
|
9578
9618
|
parser->current.end++;
|
9579
9619
|
break;
|
@@ -9626,7 +9666,9 @@ parser_lex(pm_parser_t *parser) {
|
|
9626
9666
|
|
9627
9667
|
// If we were unable to find a breakpoint, then this token hits the
|
9628
9668
|
// end of the file.
|
9629
|
-
|
9669
|
+
parser->current.end = parser->end;
|
9670
|
+
pm_token_buffer_flush(parser, &token_buffer);
|
9671
|
+
LEX(PM_TOKEN_STRING_CONTENT);
|
9630
9672
|
}
|
9631
9673
|
case PM_LEX_STRING: {
|
9632
9674
|
// First, we'll set to start of this token to be the current end.
|
@@ -9830,8 +9872,10 @@ parser_lex(pm_parser_t *parser) {
|
|
9830
9872
|
}
|
9831
9873
|
|
9832
9874
|
// If we've hit the end of the string, then this is an unterminated
|
9833
|
-
// string. In that case we'll return
|
9834
|
-
|
9875
|
+
// string. In that case we'll return a string content token.
|
9876
|
+
parser->current.end = parser->end;
|
9877
|
+
pm_token_buffer_flush(parser, &token_buffer);
|
9878
|
+
LEX(PM_TOKEN_STRING_CONTENT);
|
9835
9879
|
}
|
9836
9880
|
case PM_LEX_HEREDOC: {
|
9837
9881
|
// First, we'll set to start of this token.
|
@@ -9860,24 +9904,42 @@ parser_lex(pm_parser_t *parser) {
|
|
9860
9904
|
// terminator, then we need to return the ending of the heredoc.
|
9861
9905
|
if (current_token_starts_line(parser)) {
|
9862
9906
|
const uint8_t *start = parser->current.start;
|
9863
|
-
|
9907
|
+
if (start + ident_length <= parser->end) {
|
9908
|
+
const uint8_t *newline = next_newline(start, parser->end - start);
|
9909
|
+
const uint8_t *ident_end = newline;
|
9910
|
+
const uint8_t *terminator_end = newline;
|
9911
|
+
|
9912
|
+
if (newline == NULL) {
|
9913
|
+
terminator_end = parser->end;
|
9914
|
+
ident_end = parser->end;
|
9915
|
+
} else {
|
9916
|
+
terminator_end++;
|
9917
|
+
if (newline[-1] == '\r') {
|
9918
|
+
ident_end--; // Remove \r
|
9919
|
+
}
|
9920
|
+
}
|
9864
9921
|
|
9865
|
-
|
9866
|
-
|
9867
|
-
bool at_end = false;
|
9922
|
+
const uint8_t *terminator_start = ident_end - ident_length;
|
9923
|
+
const uint8_t *cursor = start;
|
9868
9924
|
|
9869
|
-
|
9870
|
-
|
9871
|
-
|
9872
|
-
|
9873
|
-
|
9874
|
-
|
9875
|
-
|
9876
|
-
} else {
|
9877
|
-
matched = false;
|
9925
|
+
if (
|
9926
|
+
lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_DASH ||
|
9927
|
+
lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE
|
9928
|
+
) {
|
9929
|
+
while (cursor < terminator_start && pm_char_is_inline_whitespace(*cursor)) {
|
9930
|
+
cursor++;
|
9931
|
+
}
|
9878
9932
|
}
|
9879
9933
|
|
9880
|
-
if (
|
9934
|
+
if (
|
9935
|
+
(cursor == terminator_start) &&
|
9936
|
+
(memcmp(terminator_start, ident_start, ident_length) == 0)
|
9937
|
+
) {
|
9938
|
+
if (newline != NULL) {
|
9939
|
+
pm_newline_list_append(&parser->newline_list, newline);
|
9940
|
+
}
|
9941
|
+
|
9942
|
+
parser->current.end = terminator_end;
|
9881
9943
|
if (*lex_mode->as.heredoc.next_start == '\\') {
|
9882
9944
|
parser->next_start = NULL;
|
9883
9945
|
} else {
|
@@ -9885,15 +9947,12 @@ parser_lex(pm_parser_t *parser) {
|
|
9885
9947
|
parser->heredoc_end = parser->current.end;
|
9886
9948
|
}
|
9887
9949
|
|
9888
|
-
parser
|
9889
|
-
lex_mode_pop(parser);
|
9890
|
-
if (!at_end) {
|
9891
|
-
lex_state_set(parser, PM_LEX_STATE_END);
|
9892
|
-
}
|
9950
|
+
lex_state_set(parser, PM_LEX_STATE_END);
|
9893
9951
|
LEX(PM_TOKEN_HEREDOC_END);
|
9894
9952
|
}
|
9895
9953
|
}
|
9896
9954
|
|
9955
|
+
size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, lex_mode->as.heredoc.indent);
|
9897
9956
|
if (
|
9898
9957
|
lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE &&
|
9899
9958
|
(lex_mode->as.heredoc.common_whitespace > whitespace) &&
|
@@ -9937,23 +9996,35 @@ parser_lex(pm_parser_t *parser) {
|
|
9937
9996
|
// If we have a - or ~ heredoc, then we can match after
|
9938
9997
|
// some leading whitespace.
|
9939
9998
|
const uint8_t *start = breakpoint + 1;
|
9940
|
-
size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, lex_mode->as.heredoc.indent);
|
9941
9999
|
|
9942
|
-
|
9943
|
-
|
9944
|
-
|
9945
|
-
|
9946
|
-
|
9947
|
-
|
9948
|
-
|
9949
|
-
|
9950
|
-
|
9951
|
-
|
9952
|
-
|
9953
|
-
//
|
10000
|
+
if (!was_escaped_newline && (start + ident_length <= parser->end)) {
|
10001
|
+
// We want to match the terminator starting from the end of the line in case
|
10002
|
+
// there is whitespace in the ident such as <<-' DOC' or <<~' DOC'.
|
10003
|
+
const uint8_t *newline = next_newline(start, parser->end - start);
|
10004
|
+
|
10005
|
+
if (newline == NULL) {
|
10006
|
+
newline = parser->end;
|
10007
|
+
} else if (newline[-1] == '\r') {
|
10008
|
+
newline--; // Remove \r
|
10009
|
+
}
|
10010
|
+
|
10011
|
+
// Start of a possible terminator.
|
10012
|
+
const uint8_t *terminator_start = newline - ident_length;
|
10013
|
+
|
10014
|
+
// Cursor to check for the leading whitespace. We skip the
|
10015
|
+
// leading whitespace if we have a - or ~ heredoc.
|
10016
|
+
const uint8_t *cursor = start;
|
10017
|
+
|
10018
|
+
if (lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_DASH ||
|
10019
|
+
lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE) {
|
10020
|
+
while (cursor < terminator_start && pm_char_is_inline_whitespace(*cursor)) {
|
10021
|
+
cursor++;
|
10022
|
+
}
|
10023
|
+
}
|
10024
|
+
|
9954
10025
|
if (
|
9955
|
-
|
9956
|
-
|
10026
|
+
cursor == terminator_start &&
|
10027
|
+
(memcmp(terminator_start, ident_start, ident_length) == 0)
|
9957
10028
|
) {
|
9958
10029
|
parser->current.end = breakpoint + 1;
|
9959
10030
|
pm_token_buffer_flush(parser, &token_buffer);
|
@@ -9961,6 +10032,14 @@ parser_lex(pm_parser_t *parser) {
|
|
9961
10032
|
}
|
9962
10033
|
}
|
9963
10034
|
|
10035
|
+
size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, lex_mode->as.heredoc.indent);
|
10036
|
+
|
10037
|
+
// If we have hit a newline that is followed by a valid
|
10038
|
+
// terminator, then we need to return the content of the
|
10039
|
+
// heredoc here as string content. Then, the next time a
|
10040
|
+
// token is lexed, it will match again and return the
|
10041
|
+
// end of the heredoc.
|
10042
|
+
|
9964
10043
|
if (lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE) {
|
9965
10044
|
if ((lex_mode->as.heredoc.common_whitespace > whitespace) && peek_at(parser, start) != '\n') {
|
9966
10045
|
lex_mode->as.heredoc.common_whitespace = whitespace;
|
@@ -10078,8 +10157,10 @@ parser_lex(pm_parser_t *parser) {
|
|
10078
10157
|
}
|
10079
10158
|
|
10080
10159
|
// If we've hit the end of the string, then this is an unterminated
|
10081
|
-
// heredoc. In that case we'll return
|
10082
|
-
|
10160
|
+
// heredoc. In that case we'll return a string content token.
|
10161
|
+
parser->current.end = parser->end;
|
10162
|
+
pm_token_buffer_flush(parser, &token_buffer);
|
10163
|
+
LEX(PM_TOKEN_STRING_CONTENT);
|
10083
10164
|
}
|
10084
10165
|
}
|
10085
10166
|
|
@@ -10101,32 +10182,33 @@ parser_lex(pm_parser_t *parser) {
|
|
10101
10182
|
* specify their associativity by adding or subtracting one.
|
10102
10183
|
*/
|
10103
10184
|
typedef enum {
|
10104
|
-
PM_BINDING_POWER_UNSET =
|
10105
|
-
PM_BINDING_POWER_STATEMENT =
|
10106
|
-
PM_BINDING_POWER_MODIFIER =
|
10107
|
-
PM_BINDING_POWER_MODIFIER_RESCUE =
|
10108
|
-
PM_BINDING_POWER_COMPOSITION =
|
10109
|
-
PM_BINDING_POWER_NOT =
|
10110
|
-
PM_BINDING_POWER_MATCH =
|
10111
|
-
PM_BINDING_POWER_DEFINED =
|
10112
|
-
|
10113
|
-
|
10114
|
-
|
10115
|
-
|
10116
|
-
|
10117
|
-
|
10118
|
-
|
10119
|
-
|
10120
|
-
|
10121
|
-
|
10122
|
-
|
10123
|
-
|
10124
|
-
|
10125
|
-
|
10126
|
-
|
10127
|
-
|
10128
|
-
|
10129
|
-
|
10185
|
+
PM_BINDING_POWER_UNSET = 0, // used to indicate this token cannot be used as an infix operator
|
10186
|
+
PM_BINDING_POWER_STATEMENT = 2,
|
10187
|
+
PM_BINDING_POWER_MODIFIER = 4, // if unless until while
|
10188
|
+
PM_BINDING_POWER_MODIFIER_RESCUE = 6, // rescue
|
10189
|
+
PM_BINDING_POWER_COMPOSITION = 8, // and or
|
10190
|
+
PM_BINDING_POWER_NOT = 10, // not
|
10191
|
+
PM_BINDING_POWER_MATCH = 12, // => in
|
10192
|
+
PM_BINDING_POWER_DEFINED = 14, // defined?
|
10193
|
+
PM_BINDING_POWER_MULTI_ASSIGNMENT = 16, // =
|
10194
|
+
PM_BINDING_POWER_ASSIGNMENT = 18, // = += -= *= /= %= &= |= ^= &&= ||= <<= >>= **=
|
10195
|
+
PM_BINDING_POWER_TERNARY = 20, // ?:
|
10196
|
+
PM_BINDING_POWER_RANGE = 22, // .. ...
|
10197
|
+
PM_BINDING_POWER_LOGICAL_OR = 24, // ||
|
10198
|
+
PM_BINDING_POWER_LOGICAL_AND = 26, // &&
|
10199
|
+
PM_BINDING_POWER_EQUALITY = 28, // <=> == === != =~ !~
|
10200
|
+
PM_BINDING_POWER_COMPARISON = 30, // > >= < <=
|
10201
|
+
PM_BINDING_POWER_BITWISE_OR = 32, // | ^
|
10202
|
+
PM_BINDING_POWER_BITWISE_AND = 34, // &
|
10203
|
+
PM_BINDING_POWER_SHIFT = 36, // << >>
|
10204
|
+
PM_BINDING_POWER_TERM = 38, // + -
|
10205
|
+
PM_BINDING_POWER_FACTOR = 40, // * / %
|
10206
|
+
PM_BINDING_POWER_UMINUS = 42, // -@
|
10207
|
+
PM_BINDING_POWER_EXPONENT = 44, // **
|
10208
|
+
PM_BINDING_POWER_UNARY = 46, // ! ~ +@
|
10209
|
+
PM_BINDING_POWER_INDEX = 48, // [] []=
|
10210
|
+
PM_BINDING_POWER_CALL = 50, // :: .
|
10211
|
+
PM_BINDING_POWER_MAX = 52
|
10130
10212
|
} pm_binding_power_t;
|
10131
10213
|
|
10132
10214
|
/**
|
@@ -10153,7 +10235,7 @@ typedef struct {
|
|
10153
10235
|
#define BINDING_POWER_ASSIGNMENT { PM_BINDING_POWER_UNARY, PM_BINDING_POWER_ASSIGNMENT, true, false }
|
10154
10236
|
#define LEFT_ASSOCIATIVE(precedence) { precedence, precedence + 1, true, false }
|
10155
10237
|
#define RIGHT_ASSOCIATIVE(precedence) { precedence, precedence, true, false }
|
10156
|
-
#define NON_ASSOCIATIVE(precedence) { precedence
|
10238
|
+
#define NON_ASSOCIATIVE(precedence) { precedence, precedence + 1, true, true }
|
10157
10239
|
#define RIGHT_ASSOCIATIVE_UNARY(precedence) { precedence, precedence, false, false }
|
10158
10240
|
|
10159
10241
|
pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = {
|
@@ -10196,6 +10278,8 @@ pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = {
|
|
10196
10278
|
// .. ...
|
10197
10279
|
[PM_TOKEN_DOT_DOT] = NON_ASSOCIATIVE(PM_BINDING_POWER_RANGE),
|
10198
10280
|
[PM_TOKEN_DOT_DOT_DOT] = NON_ASSOCIATIVE(PM_BINDING_POWER_RANGE),
|
10281
|
+
[PM_TOKEN_UDOT_DOT] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_LOGICAL_OR),
|
10282
|
+
[PM_TOKEN_UDOT_DOT_DOT] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_LOGICAL_OR),
|
10199
10283
|
|
10200
10284
|
// ||
|
10201
10285
|
[PM_TOKEN_PIPE_PIPE] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_LOGICAL_OR),
|
@@ -10204,12 +10288,12 @@ pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = {
|
|
10204
10288
|
[PM_TOKEN_AMPERSAND_AMPERSAND] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_LOGICAL_AND),
|
10205
10289
|
|
10206
10290
|
// != !~ == === =~ <=>
|
10207
|
-
[PM_TOKEN_BANG_EQUAL] =
|
10208
|
-
[PM_TOKEN_BANG_TILDE] =
|
10209
|
-
[PM_TOKEN_EQUAL_EQUAL] =
|
10210
|
-
[PM_TOKEN_EQUAL_EQUAL_EQUAL] =
|
10211
|
-
[PM_TOKEN_EQUAL_TILDE] =
|
10212
|
-
[PM_TOKEN_LESS_EQUAL_GREATER] =
|
10291
|
+
[PM_TOKEN_BANG_EQUAL] = NON_ASSOCIATIVE(PM_BINDING_POWER_EQUALITY),
|
10292
|
+
[PM_TOKEN_BANG_TILDE] = NON_ASSOCIATIVE(PM_BINDING_POWER_EQUALITY),
|
10293
|
+
[PM_TOKEN_EQUAL_EQUAL] = NON_ASSOCIATIVE(PM_BINDING_POWER_EQUALITY),
|
10294
|
+
[PM_TOKEN_EQUAL_EQUAL_EQUAL] = NON_ASSOCIATIVE(PM_BINDING_POWER_EQUALITY),
|
10295
|
+
[PM_TOKEN_EQUAL_TILDE] = NON_ASSOCIATIVE(PM_BINDING_POWER_EQUALITY),
|
10296
|
+
[PM_TOKEN_LESS_EQUAL_GREATER] = NON_ASSOCIATIVE(PM_BINDING_POWER_EQUALITY),
|
10213
10297
|
|
10214
10298
|
// > >= < <=
|
10215
10299
|
[PM_TOKEN_GREATER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_COMPARISON),
|
@@ -10289,6 +10373,14 @@ match3(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2,
|
|
10289
10373
|
return match1(parser, type1) || match1(parser, type2) || match1(parser, type3);
|
10290
10374
|
}
|
10291
10375
|
|
10376
|
+
/**
|
10377
|
+
* Returns true if the current token is any of the four given types.
|
10378
|
+
*/
|
10379
|
+
static inline bool
|
10380
|
+
match4(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_token_type_t type3, pm_token_type_t type4) {
|
10381
|
+
return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4);
|
10382
|
+
}
|
10383
|
+
|
10292
10384
|
/**
|
10293
10385
|
* Returns true if the current token is any of the five given types.
|
10294
10386
|
*/
|
@@ -10414,14 +10506,14 @@ expect3(pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_to
|
|
10414
10506
|
}
|
10415
10507
|
|
10416
10508
|
static pm_node_t *
|
10417
|
-
parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id);
|
10509
|
+
parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id);
|
10418
10510
|
|
10419
10511
|
/**
|
10420
10512
|
* This is a wrapper of parse_expression, which also checks whether the resulting node is value expression.
|
10421
10513
|
*/
|
10422
10514
|
static pm_node_t *
|
10423
|
-
parse_value_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id) {
|
10424
|
-
pm_node_t *node = parse_expression(parser, binding_power, diag_id);
|
10515
|
+
parse_value_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) {
|
10516
|
+
pm_node_t *node = parse_expression(parser, binding_power, accepts_command_call, diag_id);
|
10425
10517
|
pm_assert_value_expression(parser, node);
|
10426
10518
|
return node;
|
10427
10519
|
}
|
@@ -10506,14 +10598,14 @@ token_begins_expression_p(pm_token_type_t type) {
|
|
10506
10598
|
* prefixed by the * operator.
|
10507
10599
|
*/
|
10508
10600
|
static pm_node_t *
|
10509
|
-
parse_starred_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id) {
|
10601
|
+
parse_starred_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) {
|
10510
10602
|
if (accept1(parser, PM_TOKEN_USTAR)) {
|
10511
10603
|
pm_token_t operator = parser->previous;
|
10512
|
-
pm_node_t *expression = parse_value_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
10604
|
+
pm_node_t *expression = parse_value_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
10513
10605
|
return (pm_node_t *) pm_splat_node_create(parser, &operator, expression);
|
10514
10606
|
}
|
10515
10607
|
|
10516
|
-
return parse_value_expression(parser, binding_power, diag_id);
|
10608
|
+
return parse_value_expression(parser, binding_power, accepts_command_call, diag_id);
|
10517
10609
|
}
|
10518
10610
|
|
10519
10611
|
/**
|
@@ -10621,7 +10713,6 @@ parse_target(pm_parser_t *parser, pm_node_t *target) {
|
|
10621
10713
|
pm_node_destroy(parser, target);
|
10622
10714
|
|
10623
10715
|
uint32_t depth = 0;
|
10624
|
-
for (pm_scope_t *scope = parser->current_scope; scope && scope->transparent; depth++, scope = scope->previous);
|
10625
10716
|
const pm_token_t name = { .type = PM_TOKEN_IDENTIFIER, .start = message.start, .end = message.end };
|
10626
10717
|
target = (pm_node_t *) pm_local_variable_read_node_create(parser, &name, depth);
|
10627
10718
|
|
@@ -10632,25 +10723,17 @@ parse_target(pm_parser_t *parser, pm_node_t *target) {
|
|
10632
10723
|
return target;
|
10633
10724
|
}
|
10634
10725
|
|
10635
|
-
if (*call->message_loc.start == '_' || parser->encoding
|
10726
|
+
if (*call->message_loc.start == '_' || parser->encoding->alnum_char(call->message_loc.start, call->message_loc.end - call->message_loc.start)) {
|
10636
10727
|
parse_write_name(parser, &call->name);
|
10637
|
-
return (pm_node_t *) call;
|
10728
|
+
return (pm_node_t *) pm_call_target_node_create(parser, call);
|
10638
10729
|
}
|
10639
10730
|
}
|
10640
10731
|
|
10641
10732
|
// If there is no call operator and the message is "[]" then this is
|
10642
10733
|
// an aref expression, and we can transform it into an aset
|
10643
10734
|
// expression.
|
10644
|
-
if (
|
10645
|
-
(
|
10646
|
-
(call->message_loc.start != NULL) &&
|
10647
|
-
(call->message_loc.start[0] == '[') &&
|
10648
|
-
(call->message_loc.end[-1] == ']') &&
|
10649
|
-
(call->block == NULL)
|
10650
|
-
) {
|
10651
|
-
// Replace the name with "[]=".
|
10652
|
-
call->name = pm_parser_constant_id_constant(parser, "[]=", 3);
|
10653
|
-
return target;
|
10735
|
+
if (pm_call_node_index_p(call)) {
|
10736
|
+
return (pm_node_t *) pm_index_target_node_create(parser, call);
|
10654
10737
|
}
|
10655
10738
|
}
|
10656
10739
|
/* fallthrough */
|
@@ -10690,6 +10773,7 @@ static pm_node_t *
|
|
10690
10773
|
parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_node_t *value) {
|
10691
10774
|
switch (PM_NODE_TYPE(target)) {
|
10692
10775
|
case PM_MISSING_NODE:
|
10776
|
+
pm_node_destroy(parser, value);
|
10693
10777
|
return target;
|
10694
10778
|
case PM_CLASS_VARIABLE_READ_NODE: {
|
10695
10779
|
pm_class_variable_write_node_t *node = pm_class_variable_write_node_create(parser, (pm_class_variable_read_node_t *) target, operator, value);
|
@@ -10700,6 +10784,9 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
|
|
10700
10784
|
return (pm_node_t *) pm_constant_path_write_node_create(parser, (pm_constant_path_node_t *) target, operator, value);
|
10701
10785
|
case PM_CONSTANT_READ_NODE: {
|
10702
10786
|
pm_constant_write_node_t *node = pm_constant_write_node_create(parser, (pm_constant_read_node_t *) target, operator, value);
|
10787
|
+
if (context_def_p(parser)) {
|
10788
|
+
pm_parser_err_node(parser, (pm_node_t *) node, PM_ERR_WRITE_TARGET_IN_METHOD);
|
10789
|
+
}
|
10703
10790
|
pm_node_destroy(parser, target);
|
10704
10791
|
return (pm_node_t *) node;
|
10705
10792
|
}
|
@@ -10779,7 +10866,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
|
|
10779
10866
|
return target;
|
10780
10867
|
}
|
10781
10868
|
|
10782
|
-
if (*call->message_loc.start == '_' || parser->encoding
|
10869
|
+
if (*call->message_loc.start == '_' || parser->encoding->alnum_char(call->message_loc.start, call->message_loc.end - call->message_loc.start)) {
|
10783
10870
|
// When we get here, we have a method call, because it was
|
10784
10871
|
// previously marked as a method call but now we have an =. This
|
10785
10872
|
// looks like:
|
@@ -10797,6 +10884,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
|
|
10797
10884
|
call->base.location.end = arguments->base.location.end;
|
10798
10885
|
|
10799
10886
|
parse_write_name(parser, &call->name);
|
10887
|
+
pm_node_flag_set((pm_node_t *) call, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE);
|
10800
10888
|
return (pm_node_t *) call;
|
10801
10889
|
}
|
10802
10890
|
}
|
@@ -10804,13 +10892,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
|
|
10804
10892
|
// If there is no call operator and the message is "[]" then this is
|
10805
10893
|
// an aref expression, and we can transform it into an aset
|
10806
10894
|
// expression.
|
10807
|
-
if (
|
10808
|
-
(call->call_operator_loc.start == NULL) &&
|
10809
|
-
(call->message_loc.start != NULL) &&
|
10810
|
-
(call->message_loc.start[0] == '[') &&
|
10811
|
-
(call->message_loc.end[-1] == ']') &&
|
10812
|
-
(call->block == NULL)
|
10813
|
-
) {
|
10895
|
+
if (pm_call_node_index_p(call)) {
|
10814
10896
|
if (call->arguments == NULL) {
|
10815
10897
|
call->arguments = pm_arguments_node_create(parser);
|
10816
10898
|
}
|
@@ -10820,6 +10902,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
|
|
10820
10902
|
|
10821
10903
|
// Replace the name with "[]=".
|
10822
10904
|
call->name = pm_parser_constant_id_constant(parser, "[]=", 3);
|
10905
|
+
pm_node_flag_set((pm_node_t *) call, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE);
|
10823
10906
|
return target;
|
10824
10907
|
}
|
10825
10908
|
|
@@ -10852,7 +10935,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
|
|
10852
10935
|
*/
|
10853
10936
|
static pm_node_t *
|
10854
10937
|
parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t binding_power) {
|
10855
|
-
bool
|
10938
|
+
bool has_rest = PM_NODE_TYPE_P(first_target, PM_SPLAT_NODE);
|
10856
10939
|
|
10857
10940
|
pm_multi_target_node_t *result = pm_multi_target_node_create(parser);
|
10858
10941
|
pm_multi_target_node_targets_append(parser, result, parse_target(parser, first_target));
|
@@ -10862,7 +10945,7 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b
|
|
10862
10945
|
// Here we have a splat operator. It can have a name or be
|
10863
10946
|
// anonymous. It can be the final target or be in the middle if
|
10864
10947
|
// there haven't been any others yet.
|
10865
|
-
if (
|
10948
|
+
if (has_rest) {
|
10866
10949
|
pm_parser_err_previous(parser, PM_ERR_MULTI_ASSIGN_MULTI_SPLATS);
|
10867
10950
|
}
|
10868
10951
|
|
@@ -10870,24 +10953,23 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b
|
|
10870
10953
|
pm_node_t *name = NULL;
|
10871
10954
|
|
10872
10955
|
if (token_begins_expression_p(parser->current.type)) {
|
10873
|
-
name = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
10956
|
+
name = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
10874
10957
|
name = parse_target(parser, name);
|
10875
10958
|
}
|
10876
10959
|
|
10877
10960
|
pm_node_t *splat = (pm_node_t *) pm_splat_node_create(parser, &star_operator, name);
|
10878
10961
|
pm_multi_target_node_targets_append(parser, result, splat);
|
10879
|
-
|
10962
|
+
has_rest = true;
|
10880
10963
|
} else if (token_begins_expression_p(parser->current.type)) {
|
10881
|
-
pm_node_t *target = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA);
|
10964
|
+
pm_node_t *target = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA);
|
10882
10965
|
target = parse_target(parser, target);
|
10883
10966
|
|
10884
10967
|
pm_multi_target_node_targets_append(parser, result, target);
|
10885
10968
|
} else if (!match1(parser, PM_TOKEN_EOF)) {
|
10886
10969
|
// If we get here, then we have a trailing , in a multi target node.
|
10887
|
-
// We
|
10888
|
-
|
10889
|
-
|
10890
|
-
pm_multi_target_node_targets_append(parser, result, splat);
|
10970
|
+
// We'll set the implicit rest flag to indicate this.
|
10971
|
+
pm_node_t *rest = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
|
10972
|
+
pm_multi_target_node_targets_append(parser, result, rest);
|
10891
10973
|
break;
|
10892
10974
|
}
|
10893
10975
|
}
|
@@ -10930,7 +11012,7 @@ parse_statements(pm_parser_t *parser, pm_context_t context) {
|
|
10930
11012
|
context_push(parser, context);
|
10931
11013
|
|
10932
11014
|
while (true) {
|
10933
|
-
pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, PM_ERR_CANNOT_PARSE_EXPRESSION);
|
11015
|
+
pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_CANNOT_PARSE_EXPRESSION);
|
10934
11016
|
pm_statements_node_body_append(statements, node);
|
10935
11017
|
|
10936
11018
|
// If we're recovering from a syntax error, then we need to stop parsing the
|
@@ -10984,7 +11066,7 @@ parse_statements(pm_parser_t *parser, pm_context_t context) {
|
|
10984
11066
|
}
|
10985
11067
|
|
10986
11068
|
/**
|
10987
|
-
* Parse all of the elements of a hash.
|
11069
|
+
* Parse all of the elements of a hash. returns true if a double splat was found.
|
10988
11070
|
*/
|
10989
11071
|
static bool
|
10990
11072
|
parse_assocs(pm_parser_t *parser, pm_node_t *node) {
|
@@ -11001,7 +11083,7 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) {
|
|
11001
11083
|
pm_node_t *value = NULL;
|
11002
11084
|
|
11003
11085
|
if (token_begins_expression_p(parser->current.type)) {
|
11004
|
-
value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
|
11086
|
+
value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
|
11005
11087
|
} else if (pm_parser_local_depth(parser, &operator) == -1) {
|
11006
11088
|
pm_parser_err_token(parser, &operator, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
|
11007
11089
|
}
|
@@ -11019,9 +11101,9 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) {
|
|
11019
11101
|
pm_node_t *value = NULL;
|
11020
11102
|
|
11021
11103
|
if (token_begins_expression_p(parser->current.type)) {
|
11022
|
-
value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_HASH_EXPRESSION_AFTER_LABEL);
|
11104
|
+
value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_EXPRESSION_AFTER_LABEL);
|
11023
11105
|
} else {
|
11024
|
-
if (parser->encoding
|
11106
|
+
if (parser->encoding->isupper_char(label.start, (label.end - 1) - label.start)) {
|
11025
11107
|
pm_token_t constant = { .type = PM_TOKEN_CONSTANT, .start = label.start, .end = label.end - 1 };
|
11026
11108
|
value = (pm_node_t *) pm_constant_read_node_create(parser, &constant);
|
11027
11109
|
} else {
|
@@ -11043,7 +11125,7 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) {
|
|
11043
11125
|
break;
|
11044
11126
|
}
|
11045
11127
|
default: {
|
11046
|
-
pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_HASH_KEY);
|
11128
|
+
pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_KEY);
|
11047
11129
|
pm_token_t operator;
|
11048
11130
|
|
11049
11131
|
if (pm_symbol_node_label_p(key)) {
|
@@ -11053,7 +11135,7 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) {
|
|
11053
11135
|
operator = parser->previous;
|
11054
11136
|
}
|
11055
11137
|
|
11056
|
-
pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_HASH_VALUE);
|
11138
|
+
pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_VALUE);
|
11057
11139
|
element = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value);
|
11058
11140
|
break;
|
11059
11141
|
}
|
@@ -11136,15 +11218,11 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
11136
11218
|
pm_keyword_hash_node_t *hash = pm_keyword_hash_node_create(parser);
|
11137
11219
|
argument = (pm_node_t *) hash;
|
11138
11220
|
|
11139
|
-
bool contains_keyword_splat =
|
11140
|
-
if (!match7(parser, terminator, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_KEYWORD_DO, PM_TOKEN_PARENTHESIS_RIGHT)) {
|
11141
|
-
contains_keyword_splat = parse_assocs(parser, (pm_node_t *) hash);
|
11142
|
-
}
|
11143
|
-
|
11221
|
+
bool contains_keyword_splat = parse_assocs(parser, (pm_node_t *) hash);
|
11144
11222
|
parsed_bare_hash = true;
|
11145
11223
|
parse_arguments_append(parser, arguments, argument);
|
11146
11224
|
if (contains_keyword_splat) {
|
11147
|
-
arguments->arguments
|
11225
|
+
pm_node_flag_set((pm_node_t *)arguments->arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT);
|
11148
11226
|
}
|
11149
11227
|
break;
|
11150
11228
|
}
|
@@ -11154,9 +11232,15 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
11154
11232
|
pm_node_t *expression = NULL;
|
11155
11233
|
|
11156
11234
|
if (token_begins_expression_p(parser->current.type)) {
|
11157
|
-
expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_EXPECT_ARGUMENT);
|
11158
|
-
} else
|
11159
|
-
|
11235
|
+
expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_ARGUMENT);
|
11236
|
+
} else {
|
11237
|
+
if (pm_parser_local_depth(parser, &operator) == -1) {
|
11238
|
+
// A block forwarding in a method having `...` parameter (e.g. `def foo(...); bar(&); end`) is available.
|
11239
|
+
pm_constant_id_t ellipsis_id = pm_parser_constant_id_constant(parser, "...", 3);
|
11240
|
+
if (pm_parser_local_depth_constant_id(parser, ellipsis_id) == -1) {
|
11241
|
+
pm_parser_err_token(parser, &operator, PM_ERR_ARGUMENT_NO_FORWARDING_AMP);
|
11242
|
+
}
|
11243
|
+
}
|
11160
11244
|
}
|
11161
11245
|
|
11162
11246
|
argument = (pm_node_t *) pm_block_argument_node_create(parser, &operator, expression);
|
@@ -11173,14 +11257,14 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
11173
11257
|
parser_lex(parser);
|
11174
11258
|
pm_token_t operator = parser->previous;
|
11175
11259
|
|
11176
|
-
if (
|
11260
|
+
if (match4(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_COMMA, PM_TOKEN_SEMICOLON, PM_TOKEN_BRACKET_RIGHT)) {
|
11177
11261
|
if (pm_parser_local_depth(parser, &parser->previous) == -1) {
|
11178
11262
|
pm_parser_err_token(parser, &operator, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
|
11179
11263
|
}
|
11180
11264
|
|
11181
11265
|
argument = (pm_node_t *) pm_splat_node_create(parser, &operator, NULL);
|
11182
11266
|
} else {
|
11183
|
-
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT);
|
11267
|
+
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT);
|
11184
11268
|
|
11185
11269
|
if (parsed_bare_hash) {
|
11186
11270
|
pm_parser_err(parser, operator.start, expression->location.end, PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT);
|
@@ -11200,7 +11284,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
11200
11284
|
// If the token begins an expression then this ... was not actually
|
11201
11285
|
// argument forwarding but was instead a range.
|
11202
11286
|
pm_token_t operator = parser->previous;
|
11203
|
-
pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
11287
|
+
pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
11204
11288
|
argument = (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
|
11205
11289
|
} else {
|
11206
11290
|
if (pm_parser_local_depth(parser, &parser->previous) == -1) {
|
@@ -11220,7 +11304,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
11220
11304
|
/* fallthrough */
|
11221
11305
|
default: {
|
11222
11306
|
if (argument == NULL) {
|
11223
|
-
argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_EXPECT_ARGUMENT);
|
11307
|
+
argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, !parsed_first_argument, PM_ERR_EXPECT_ARGUMENT);
|
11224
11308
|
}
|
11225
11309
|
|
11226
11310
|
bool contains_keyword_splat = false;
|
@@ -11239,7 +11323,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
11239
11323
|
pm_keyword_hash_node_t *bare_hash = pm_keyword_hash_node_create(parser);
|
11240
11324
|
|
11241
11325
|
// Finish parsing the one we are part way through
|
11242
|
-
pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_HASH_VALUE);
|
11326
|
+
pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_VALUE);
|
11243
11327
|
|
11244
11328
|
argument = (pm_node_t *) pm_assoc_node_create(parser, argument, &operator, value);
|
11245
11329
|
pm_keyword_hash_node_elements_append(bare_hash, argument);
|
@@ -11258,7 +11342,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|
11258
11342
|
|
11259
11343
|
parse_arguments_append(parser, arguments, argument);
|
11260
11344
|
if (contains_keyword_splat) {
|
11261
|
-
arguments->arguments
|
11345
|
+
pm_node_flag_set((pm_node_t *)arguments->arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT);
|
11262
11346
|
}
|
11263
11347
|
break;
|
11264
11348
|
}
|
@@ -11310,11 +11394,14 @@ parse_required_destructured_parameter(pm_parser_t *parser) {
|
|
11310
11394
|
do {
|
11311
11395
|
pm_node_t *param;
|
11312
11396
|
|
11313
|
-
// If we get here then we have a trailing comma
|
11314
|
-
//
|
11397
|
+
// If we get here then we have a trailing comma, which isn't allowed in
|
11398
|
+
// the grammar. In other places, multi targets _do_ allow trailing
|
11399
|
+
// commas, so here we'll assume this is a mistake of the user not
|
11400
|
+
// knowing it's not allowed here.
|
11315
11401
|
if (node->lefts.size > 0 && match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
|
11316
|
-
param = (pm_node_t *)
|
11402
|
+
param = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
|
11317
11403
|
pm_multi_target_node_targets_append(parser, node, param);
|
11404
|
+
pm_parser_err_current(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA);
|
11318
11405
|
break;
|
11319
11406
|
}
|
11320
11407
|
|
@@ -11545,10 +11632,14 @@ parse_parameters(
|
|
11545
11632
|
if (accept1(parser, PM_TOKEN_EQUAL)) {
|
11546
11633
|
pm_token_t operator = parser->previous;
|
11547
11634
|
context_push(parser, PM_CONTEXT_DEFAULT_PARAMS);
|
11548
|
-
|
11635
|
+
pm_constant_id_t old_param_name = parser->current_param_name;
|
11636
|
+
parser->current_param_name = pm_parser_constant_id_token(parser, &name);
|
11637
|
+
pm_node_t *value = parse_value_expression(parser, binding_power, false, PM_ERR_PARAMETER_NO_DEFAULT);
|
11549
11638
|
|
11550
11639
|
pm_optional_parameter_node_t *param = pm_optional_parameter_node_create(parser, &name, &operator, value);
|
11551
11640
|
pm_parameters_node_optionals_append(params, param);
|
11641
|
+
|
11642
|
+
parser->current_param_name = old_param_name;
|
11552
11643
|
context_pop(parser);
|
11553
11644
|
|
11554
11645
|
// If parsing the value of the parameter resulted in error recovery,
|
@@ -11604,7 +11695,10 @@ parse_parameters(
|
|
11604
11695
|
|
11605
11696
|
if (token_begins_expression_p(parser->current.type)) {
|
11606
11697
|
context_push(parser, PM_CONTEXT_DEFAULT_PARAMS);
|
11607
|
-
|
11698
|
+
pm_constant_id_t old_param_name = parser->current_param_name;
|
11699
|
+
parser->current_param_name = pm_parser_constant_id_token(parser, &local);
|
11700
|
+
pm_node_t *value = parse_value_expression(parser, binding_power, false, PM_ERR_PARAMETER_NO_DEFAULT_KW);
|
11701
|
+
parser->current_param_name = old_param_name;
|
11608
11702
|
context_pop(parser);
|
11609
11703
|
param = (pm_node_t *) pm_optional_keyword_parameter_node_create(parser, &name, value);
|
11610
11704
|
}
|
@@ -11647,12 +11741,12 @@ parse_parameters(
|
|
11647
11741
|
}
|
11648
11742
|
}
|
11649
11743
|
|
11650
|
-
|
11744
|
+
pm_node_t *param = (pm_node_t *) pm_rest_parameter_node_create(parser, &operator, &name);
|
11651
11745
|
if (params->rest == NULL) {
|
11652
11746
|
pm_parameters_node_rest_set(params, param);
|
11653
11747
|
} else {
|
11654
|
-
pm_parser_err_node(parser,
|
11655
|
-
pm_parameters_node_posts_append(params,
|
11748
|
+
pm_parser_err_node(parser, param, PM_ERR_PARAMETER_SPLAT_MULTI);
|
11749
|
+
pm_parameters_node_posts_append(params, param);
|
11656
11750
|
}
|
11657
11751
|
|
11658
11752
|
break;
|
@@ -11697,11 +11791,9 @@ parse_parameters(
|
|
11697
11791
|
default:
|
11698
11792
|
if (parser->previous.type == PM_TOKEN_COMMA) {
|
11699
11793
|
if (allows_trailing_comma) {
|
11700
|
-
// If we get here, then we have a trailing comma in a
|
11701
|
-
// parameter list.
|
11702
|
-
|
11703
|
-
pm_token_t name = not_provided(parser);
|
11704
|
-
pm_rest_parameter_node_t *param = pm_rest_parameter_node_create(parser, &parser->previous, &name);
|
11794
|
+
// If we get here, then we have a trailing comma in a
|
11795
|
+
// block parameter list.
|
11796
|
+
pm_node_t *param = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
|
11705
11797
|
|
11706
11798
|
if (params->rest == NULL) {
|
11707
11799
|
pm_parameters_node_rest_set(params, param);
|
@@ -11739,7 +11831,7 @@ parse_parameters(
|
|
11739
11831
|
* nodes pointing to each other from the top.
|
11740
11832
|
*/
|
11741
11833
|
static inline void
|
11742
|
-
parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) {
|
11834
|
+
parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, bool def_p) {
|
11743
11835
|
pm_rescue_node_t *current = NULL;
|
11744
11836
|
|
11745
11837
|
while (accept1(parser, PM_TOKEN_KEYWORD_RESCUE)) {
|
@@ -11753,7 +11845,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) {
|
|
11753
11845
|
parser_lex(parser);
|
11754
11846
|
pm_rescue_node_operator_set(rescue, &parser->previous);
|
11755
11847
|
|
11756
|
-
pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, PM_ERR_RESCUE_VARIABLE);
|
11848
|
+
pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_RESCUE_VARIABLE);
|
11757
11849
|
reference = parse_target(parser, reference);
|
11758
11850
|
|
11759
11851
|
pm_rescue_node_reference_set(rescue, reference);
|
@@ -11771,7 +11863,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) {
|
|
11771
11863
|
// we'll attempt to parse it here and any others delimited by commas.
|
11772
11864
|
|
11773
11865
|
do {
|
11774
|
-
pm_node_t *expression = parse_starred_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_RESCUE_EXPRESSION);
|
11866
|
+
pm_node_t *expression = parse_starred_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_RESCUE_EXPRESSION);
|
11775
11867
|
pm_rescue_node_exceptions_append(rescue, expression);
|
11776
11868
|
|
11777
11869
|
// If we hit a newline, then this is the end of the rescue expression. We
|
@@ -11783,7 +11875,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) {
|
|
11783
11875
|
if (accept1(parser, PM_TOKEN_EQUAL_GREATER)) {
|
11784
11876
|
pm_rescue_node_operator_set(rescue, &parser->previous);
|
11785
11877
|
|
11786
|
-
pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, PM_ERR_RESCUE_VARIABLE);
|
11878
|
+
pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_RESCUE_VARIABLE);
|
11787
11879
|
reference = parse_target(parser, reference);
|
11788
11880
|
|
11789
11881
|
pm_rescue_node_reference_set(rescue, reference);
|
@@ -11802,7 +11894,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) {
|
|
11802
11894
|
|
11803
11895
|
if (!match3(parser, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) {
|
11804
11896
|
pm_accepts_block_stack_push(parser, true);
|
11805
|
-
pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_RESCUE);
|
11897
|
+
pm_statements_node_t *statements = parse_statements(parser, def_p ? PM_CONTEXT_RESCUE_DEF : PM_CONTEXT_RESCUE);
|
11806
11898
|
if (statements) {
|
11807
11899
|
pm_rescue_node_statements_set(rescue, statements);
|
11808
11900
|
}
|
@@ -11838,7 +11930,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) {
|
|
11838
11930
|
pm_statements_node_t *else_statements = NULL;
|
11839
11931
|
if (!match2(parser, PM_TOKEN_KEYWORD_END, PM_TOKEN_KEYWORD_ENSURE)) {
|
11840
11932
|
pm_accepts_block_stack_push(parser, true);
|
11841
|
-
else_statements = parse_statements(parser, PM_CONTEXT_RESCUE_ELSE);
|
11933
|
+
else_statements = parse_statements(parser, def_p ? PM_CONTEXT_RESCUE_ELSE_DEF : PM_CONTEXT_RESCUE_ELSE);
|
11842
11934
|
pm_accepts_block_stack_pop(parser);
|
11843
11935
|
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
|
11844
11936
|
}
|
@@ -11854,7 +11946,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) {
|
|
11854
11946
|
pm_statements_node_t *ensure_statements = NULL;
|
11855
11947
|
if (!match1(parser, PM_TOKEN_KEYWORD_END)) {
|
11856
11948
|
pm_accepts_block_stack_push(parser, true);
|
11857
|
-
ensure_statements = parse_statements(parser, PM_CONTEXT_ENSURE);
|
11949
|
+
ensure_statements = parse_statements(parser, def_p ? PM_CONTEXT_ENSURE_DEF : PM_CONTEXT_ENSURE);
|
11858
11950
|
pm_accepts_block_stack_pop(parser);
|
11859
11951
|
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
|
11860
11952
|
}
|
@@ -11872,10 +11964,10 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node) {
|
|
11872
11964
|
}
|
11873
11965
|
|
11874
11966
|
static inline pm_begin_node_t *
|
11875
|
-
parse_rescues_as_begin(pm_parser_t *parser, pm_statements_node_t *statements) {
|
11967
|
+
parse_rescues_as_begin(pm_parser_t *parser, pm_statements_node_t *statements, bool def_p) {
|
11876
11968
|
pm_token_t no_begin_token = not_provided(parser);
|
11877
11969
|
pm_begin_node_t *begin_node = pm_begin_node_create(parser, &no_begin_token, statements);
|
11878
|
-
parse_rescues(parser, begin_node);
|
11970
|
+
parse_rescues(parser, begin_node, def_p);
|
11879
11971
|
|
11880
11972
|
// All nodes within a begin node are optional, so we look
|
11881
11973
|
// for the earliest possible node that we can use to set
|
@@ -11941,24 +12033,30 @@ parse_block(pm_parser_t *parser) {
|
|
11941
12033
|
|
11942
12034
|
pm_accepts_block_stack_push(parser, true);
|
11943
12035
|
pm_parser_scope_push(parser, false);
|
11944
|
-
pm_block_parameters_node_t *
|
12036
|
+
pm_block_parameters_node_t *block_parameters = NULL;
|
11945
12037
|
|
11946
12038
|
if (accept1(parser, PM_TOKEN_PIPE)) {
|
11947
12039
|
parser->current_scope->explicit_params = true;
|
11948
12040
|
pm_token_t block_parameters_opening = parser->previous;
|
11949
12041
|
|
11950
12042
|
if (match1(parser, PM_TOKEN_PIPE)) {
|
11951
|
-
|
12043
|
+
block_parameters = pm_block_parameters_node_create(parser, NULL, &block_parameters_opening);
|
11952
12044
|
parser->command_start = true;
|
11953
12045
|
parser_lex(parser);
|
11954
12046
|
} else {
|
11955
|
-
|
12047
|
+
block_parameters = parse_block_parameters(parser, true, &block_parameters_opening, false);
|
11956
12048
|
accept1(parser, PM_TOKEN_NEWLINE);
|
11957
12049
|
parser->command_start = true;
|
11958
12050
|
expect1(parser, PM_TOKEN_PIPE, PM_ERR_BLOCK_PARAM_PIPE_TERM);
|
11959
12051
|
}
|
11960
12052
|
|
11961
|
-
pm_block_parameters_node_closing_set(
|
12053
|
+
pm_block_parameters_node_closing_set(block_parameters, &parser->previous);
|
12054
|
+
}
|
12055
|
+
|
12056
|
+
uint32_t locals_body_index = 0;
|
12057
|
+
|
12058
|
+
if (block_parameters) {
|
12059
|
+
locals_body_index = (uint32_t) parser->current_scope->locals.size;
|
11962
12060
|
}
|
11963
12061
|
|
11964
12062
|
accept1(parser, PM_TOKEN_NEWLINE);
|
@@ -11980,17 +12078,25 @@ parse_block(pm_parser_t *parser) {
|
|
11980
12078
|
|
11981
12079
|
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
|
11982
12080
|
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
|
11983
|
-
statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements);
|
12081
|
+
statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false);
|
11984
12082
|
}
|
11985
12083
|
}
|
11986
12084
|
|
11987
12085
|
expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BLOCK_TERM_END);
|
11988
12086
|
}
|
11989
12087
|
|
12088
|
+
pm_node_t *parameters = (pm_node_t *) block_parameters;
|
12089
|
+
uint8_t maximum = parser->current_scope->numbered_parameters;
|
12090
|
+
|
12091
|
+
if (parameters == NULL && (maximum > 0)) {
|
12092
|
+
parameters = (pm_node_t *) pm_numbered_parameters_node_create(parser, &(pm_location_t) { .start = opening.start, .end = parser->previous.end }, maximum);
|
12093
|
+
locals_body_index = maximum;
|
12094
|
+
}
|
12095
|
+
|
11990
12096
|
pm_constant_id_list_t locals = parser->current_scope->locals;
|
11991
12097
|
pm_parser_scope_pop(parser);
|
11992
12098
|
pm_accepts_block_stack_pop(parser);
|
11993
|
-
return pm_block_node_create(parser, &locals, &opening, parameters, statements, &parser->previous);
|
12099
|
+
return pm_block_node_create(parser, &locals, locals_body_index, &opening, parameters, statements, &parser->previous);
|
11994
12100
|
}
|
11995
12101
|
|
11996
12102
|
/**
|
@@ -11999,7 +12105,7 @@ parse_block(pm_parser_t *parser) {
|
|
11999
12105
|
* arguments, or blocks).
|
12000
12106
|
*/
|
12001
12107
|
static bool
|
12002
|
-
parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block) {
|
12108
|
+
parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block, bool accepts_command_call) {
|
12003
12109
|
bool found = false;
|
12004
12110
|
|
12005
12111
|
if (accept1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
|
@@ -12016,7 +12122,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
|
|
12016
12122
|
|
12017
12123
|
arguments->closing_loc = PM_LOCATION_TOKEN_VALUE(&parser->previous);
|
12018
12124
|
}
|
12019
|
-
} else if ((token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR, PM_TOKEN_UAMPERSAND)) && !match1(parser, PM_TOKEN_BRACE_LEFT)) {
|
12125
|
+
} else if (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR, PM_TOKEN_UAMPERSAND)) && !match1(parser, PM_TOKEN_BRACE_LEFT)) {
|
12020
12126
|
found |= true;
|
12021
12127
|
pm_accepts_block_stack_push(parser, false);
|
12022
12128
|
|
@@ -12071,7 +12177,7 @@ static inline pm_node_t *
|
|
12071
12177
|
parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_context_t context, pm_token_t *then_keyword) {
|
12072
12178
|
context_push(parser, PM_CONTEXT_PREDICATE);
|
12073
12179
|
pm_diagnostic_id_t error_id = context == PM_CONTEXT_IF ? PM_ERR_CONDITIONAL_IF_PREDICATE : PM_ERR_CONDITIONAL_UNLESS_PREDICATE;
|
12074
|
-
pm_node_t *predicate = parse_value_expression(parser, binding_power, error_id);
|
12180
|
+
pm_node_t *predicate = parse_value_expression(parser, binding_power, true, error_id);
|
12075
12181
|
|
12076
12182
|
// Predicates are closed by a term, a "then", or a term and then a "then".
|
12077
12183
|
bool predicate_closed = accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
|
@@ -12266,6 +12372,26 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) {
|
|
12266
12372
|
case PM_INSTANCE_VARIABLE_READ_NODE: case PM_MULTI_TARGET_NODE: case PM_BACK_REFERENCE_READ_NODE: \
|
12267
12373
|
case PM_NUMBERED_REFERENCE_READ_NODE
|
12268
12374
|
|
12375
|
+
// Assert here that the flags are the same so that we can safely switch the type
|
12376
|
+
// of the node without having to move the flags.
|
12377
|
+
PM_STATIC_ASSERT(__LINE__, ((int) PM_STRING_FLAGS_FORCED_UTF8_ENCODING) == ((int) PM_ENCODING_FLAGS_FORCED_UTF8_ENCODING), "Expected the flags to match.");
|
12378
|
+
|
12379
|
+
/**
|
12380
|
+
* If the encoding was explicitly set through the lexing process, then we need
|
12381
|
+
* to potentially mark the string's flags to indicate how to encode it.
|
12382
|
+
*/
|
12383
|
+
static inline pm_node_flags_t
|
12384
|
+
parse_unescaped_encoding(const pm_parser_t *parser) {
|
12385
|
+
if (parser->explicit_encoding != NULL) {
|
12386
|
+
if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) {
|
12387
|
+
return PM_STRING_FLAGS_FORCED_UTF8_ENCODING;
|
12388
|
+
} else if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) {
|
12389
|
+
return PM_STRING_FLAGS_FORCED_BINARY_ENCODING;
|
12390
|
+
}
|
12391
|
+
}
|
12392
|
+
return 0;
|
12393
|
+
}
|
12394
|
+
|
12269
12395
|
/**
|
12270
12396
|
* Parse a node that is part of a string. If the subsequent tokens cannot be
|
12271
12397
|
* parsed as a string part, then NULL is returned.
|
@@ -12282,7 +12408,9 @@ parse_string_part(pm_parser_t *parser) {
|
|
12282
12408
|
case PM_TOKEN_STRING_CONTENT: {
|
12283
12409
|
pm_token_t opening = not_provided(parser);
|
12284
12410
|
pm_token_t closing = not_provided(parser);
|
12411
|
+
|
12285
12412
|
pm_node_t *node = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->current, &closing);
|
12413
|
+
pm_node_flag_set(node, parse_unescaped_encoding(parser));
|
12286
12414
|
|
12287
12415
|
parser_lex(parser);
|
12288
12416
|
return node;
|
@@ -12451,7 +12579,11 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
|
|
12451
12579
|
}
|
12452
12580
|
|
12453
12581
|
if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state);
|
12454
|
-
|
12582
|
+
if (match1(parser, PM_TOKEN_EOF)) {
|
12583
|
+
pm_parser_err_token(parser, &opening, PM_ERR_SYMBOL_TERM_INTERPOLATED);
|
12584
|
+
} else {
|
12585
|
+
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_SYMBOL_TERM_INTERPOLATED);
|
12586
|
+
}
|
12455
12587
|
|
12456
12588
|
return (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &node_list, &parser->previous);
|
12457
12589
|
}
|
@@ -12463,6 +12595,34 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
|
|
12463
12595
|
content = parser->current;
|
12464
12596
|
unescaped = parser->current_string;
|
12465
12597
|
parser_lex(parser);
|
12598
|
+
|
12599
|
+
// If we have two string contents in a row, then the content of this
|
12600
|
+
// symbol is split because of heredoc contents. This looks like:
|
12601
|
+
//
|
12602
|
+
// <<A; :'a
|
12603
|
+
// A
|
12604
|
+
// b'
|
12605
|
+
//
|
12606
|
+
// In this case, the best way we have to represent this is as an
|
12607
|
+
// interpolated string node, so that's what we'll do here.
|
12608
|
+
if (match1(parser, PM_TOKEN_STRING_CONTENT)) {
|
12609
|
+
pm_node_list_t parts = { 0 };
|
12610
|
+
pm_token_t bounds = not_provided(parser);
|
12611
|
+
|
12612
|
+
pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &unescaped);
|
12613
|
+
pm_node_list_append(&parts, part);
|
12614
|
+
|
12615
|
+
part = (pm_node_t *) pm_string_node_create_unescaped(parser, &bounds, &parser->current, &bounds, &parser->current_string);
|
12616
|
+
pm_node_list_append(&parts, part);
|
12617
|
+
|
12618
|
+
if (next_state != PM_LEX_STATE_NONE) {
|
12619
|
+
lex_state_set(parser, next_state);
|
12620
|
+
}
|
12621
|
+
|
12622
|
+
parser_lex(parser);
|
12623
|
+
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_SYMBOL_TERM_DYNAMIC);
|
12624
|
+
return (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous);
|
12625
|
+
}
|
12466
12626
|
} else {
|
12467
12627
|
content = (pm_token_t) { .type = PM_TOKEN_STRING_CONTENT, .start = parser->previous.end, .end = parser->previous.end };
|
12468
12628
|
pm_string_shared_init(&unescaped, content.start, content.end);
|
@@ -12472,7 +12632,11 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
|
|
12472
12632
|
lex_state_set(parser, next_state);
|
12473
12633
|
}
|
12474
12634
|
|
12475
|
-
|
12635
|
+
if (match1(parser, PM_TOKEN_EOF)) {
|
12636
|
+
pm_parser_err_token(parser, &opening, PM_ERR_SYMBOL_TERM_DYNAMIC);
|
12637
|
+
} else {
|
12638
|
+
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_SYMBOL_TERM_DYNAMIC);
|
12639
|
+
}
|
12476
12640
|
return (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
|
12477
12641
|
}
|
12478
12642
|
|
@@ -12561,9 +12725,9 @@ parse_alias_argument(pm_parser_t *parser, bool first) {
|
|
12561
12725
|
* numbered parameters.
|
12562
12726
|
*/
|
12563
12727
|
static bool
|
12564
|
-
|
12728
|
+
outer_scope_using_numbered_parameters_p(pm_parser_t *parser) {
|
12565
12729
|
for (pm_scope_t *scope = parser->current_scope->previous; scope != NULL && !scope->closed; scope = scope->previous) {
|
12566
|
-
if (scope->
|
12730
|
+
if (scope->numbered_parameters) return true;
|
12567
12731
|
}
|
12568
12732
|
|
12569
12733
|
return false;
|
@@ -12583,25 +12747,32 @@ parse_variable_call(pm_parser_t *parser) {
|
|
12583
12747
|
}
|
12584
12748
|
|
12585
12749
|
if (!parser->current_scope->closed && pm_token_is_numbered_parameter(parser->previous.start, parser->previous.end)) {
|
12586
|
-
// Indicate that this scope is using numbered params so that child
|
12587
|
-
// scopes cannot.
|
12588
|
-
parser->current_scope->numbered_params = true;
|
12589
|
-
|
12590
12750
|
// Now that we know we have a numbered parameter, we need to check
|
12591
12751
|
// if it's allowed in this context. If it is, then we will create a
|
12592
12752
|
// local variable read. If it's not, then we'll create a normal call
|
12593
12753
|
// node but add an error.
|
12594
12754
|
if (parser->current_scope->explicit_params) {
|
12595
12755
|
pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED);
|
12596
|
-
} else if (
|
12756
|
+
} else if (outer_scope_using_numbered_parameters_p(parser)) {
|
12597
12757
|
pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE);
|
12598
12758
|
} else {
|
12759
|
+
// Indicate that this scope is using numbered params so that child
|
12760
|
+
// scopes cannot.
|
12761
|
+
uint8_t number = parser->previous.start[1];
|
12762
|
+
|
12763
|
+
// We subtract the value for the character '0' to get the actual
|
12764
|
+
// integer value of the number (only _1 through _9 are valid)
|
12765
|
+
uint8_t numbered_parameters = (uint8_t) (number - '0');
|
12766
|
+
if (numbered_parameters > parser->current_scope->numbered_parameters) {
|
12767
|
+
parser->current_scope->numbered_parameters = numbered_parameters;
|
12768
|
+
pm_parser_numbered_parameters_set(parser, numbered_parameters);
|
12769
|
+
}
|
12770
|
+
|
12599
12771
|
// When you use a numbered parameter, it implies the existence
|
12600
12772
|
// of all of the locals that exist before it. For example,
|
12601
12773
|
// referencing _2 means that _1 must exist. Therefore here we
|
12602
12774
|
// loop through all of the possibilities and add them into the
|
12603
12775
|
// constant pool.
|
12604
|
-
uint8_t number = parser->previous.start[1];
|
12605
12776
|
uint8_t current = '1';
|
12606
12777
|
uint8_t *value;
|
12607
12778
|
|
@@ -12624,7 +12795,7 @@ parse_variable_call(pm_parser_t *parser) {
|
|
12624
12795
|
}
|
12625
12796
|
|
12626
12797
|
pm_call_node_t *node = pm_call_node_variable_call_create(parser, &parser->previous);
|
12627
|
-
node
|
12798
|
+
pm_node_flag_set((pm_node_t *)node, flags);
|
12628
12799
|
|
12629
12800
|
return (pm_node_t *) node;
|
12630
12801
|
}
|
@@ -12803,7 +12974,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_node_t *node) {
|
|
12803
12974
|
case PM_ARRAY_PATTERN_NODE: {
|
12804
12975
|
pm_array_pattern_node_t *pattern_node = (pm_array_pattern_node_t *) inner;
|
12805
12976
|
|
12806
|
-
if (pattern_node->constant == NULL) {
|
12977
|
+
if (pattern_node->constant == NULL && pattern_node->opening_loc.start == NULL) {
|
12807
12978
|
pattern_node->base.location.start = node->location.start;
|
12808
12979
|
pattern_node->base.location.end = closing.end;
|
12809
12980
|
|
@@ -12819,7 +12990,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_node_t *node) {
|
|
12819
12990
|
case PM_FIND_PATTERN_NODE: {
|
12820
12991
|
pm_find_pattern_node_t *pattern_node = (pm_find_pattern_node_t *) inner;
|
12821
12992
|
|
12822
|
-
if (pattern_node->constant == NULL) {
|
12993
|
+
if (pattern_node->constant == NULL && pattern_node->opening_loc.start == NULL) {
|
12823
12994
|
pattern_node->base.location.start = node->location.start;
|
12824
12995
|
pattern_node->base.location.end = closing.end;
|
12825
12996
|
|
@@ -12835,7 +13006,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_node_t *node) {
|
|
12835
13006
|
case PM_HASH_PATTERN_NODE: {
|
12836
13007
|
pm_hash_pattern_node_t *pattern_node = (pm_hash_pattern_node_t *) inner;
|
12837
13008
|
|
12838
|
-
if (pattern_node->constant == NULL) {
|
13009
|
+
if (pattern_node->constant == NULL && pattern_node->opening_loc.start == NULL) {
|
12839
13010
|
pattern_node->base.location.start = node->location.start;
|
12840
13011
|
pattern_node->base.location.end = closing.end;
|
12841
13012
|
|
@@ -12951,10 +13122,15 @@ parse_pattern_hash(pm_parser_t *parser, pm_node_t *first_assoc) {
|
|
12951
13122
|
break;
|
12952
13123
|
}
|
12953
13124
|
|
12954
|
-
pm_node_t *assoc;
|
12955
|
-
|
12956
13125
|
if (match1(parser, PM_TOKEN_USTAR_STAR)) {
|
12957
|
-
assoc = parse_pattern_keyword_rest(parser);
|
13126
|
+
pm_node_t *assoc = parse_pattern_keyword_rest(parser);
|
13127
|
+
|
13128
|
+
if (rest == NULL) {
|
13129
|
+
rest = assoc;
|
13130
|
+
} else {
|
13131
|
+
pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST);
|
13132
|
+
pm_node_list_append(&assocs, assoc);
|
13133
|
+
}
|
12958
13134
|
} else {
|
12959
13135
|
expect1(parser, PM_TOKEN_LABEL, PM_ERR_PATTERN_LABEL_AFTER_COMMA);
|
12960
13136
|
pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous);
|
@@ -12968,10 +13144,14 @@ parse_pattern_hash(pm_parser_t *parser, pm_node_t *first_assoc) {
|
|
12968
13144
|
}
|
12969
13145
|
|
12970
13146
|
pm_token_t operator = not_provided(parser);
|
12971
|
-
assoc = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value);
|
12972
|
-
|
13147
|
+
pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value);
|
13148
|
+
|
13149
|
+
if (rest != NULL) {
|
13150
|
+
pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST);
|
13151
|
+
}
|
12973
13152
|
|
12974
|
-
|
13153
|
+
pm_node_list_append(&assocs, assoc);
|
13154
|
+
}
|
12975
13155
|
}
|
12976
13156
|
|
12977
13157
|
pm_hash_pattern_node_t *node = pm_hash_pattern_node_node_list_create(parser, &assocs, rest);
|
@@ -12989,8 +13169,13 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
|
|
12989
13169
|
case PM_TOKEN_IDENTIFIER:
|
12990
13170
|
case PM_TOKEN_METHOD_NAME: {
|
12991
13171
|
parser_lex(parser);
|
12992
|
-
|
12993
|
-
|
13172
|
+
pm_token_t name = parser->previous;
|
13173
|
+
int depth = pm_parser_local_depth(parser, &name);
|
13174
|
+
if (depth < 0) {
|
13175
|
+
depth = 0;
|
13176
|
+
pm_parser_local_add_token(parser, &name);
|
13177
|
+
}
|
13178
|
+
return (pm_node_t *) pm_local_variable_target_node_create_depth(parser, &name, (uint32_t) depth);
|
12994
13179
|
}
|
12995
13180
|
case PM_TOKEN_BRACKET_LEFT_ARRAY: {
|
12996
13181
|
pm_token_t opening = parser->current;
|
@@ -13077,7 +13262,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
|
|
13077
13262
|
first_assoc = parse_pattern_keyword_rest(parser);
|
13078
13263
|
break;
|
13079
13264
|
case PM_TOKEN_STRING_BEGIN: {
|
13080
|
-
pm_node_t *key = parse_expression(parser, PM_BINDING_POWER_MAX, PM_ERR_PATTERN_HASH_KEY);
|
13265
|
+
pm_node_t *key = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_HASH_KEY);
|
13081
13266
|
pm_token_t operator = not_provided(parser);
|
13082
13267
|
|
13083
13268
|
if (!pm_symbol_node_label_p(key)) {
|
@@ -13124,7 +13309,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
|
|
13124
13309
|
// expression as the right side of the range.
|
13125
13310
|
switch (parser->current.type) {
|
13126
13311
|
case PM_CASE_PRIMITIVE: {
|
13127
|
-
pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE);
|
13312
|
+
pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE);
|
13128
13313
|
return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
|
13129
13314
|
}
|
13130
13315
|
default: {
|
@@ -13135,7 +13320,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
|
|
13135
13320
|
}
|
13136
13321
|
}
|
13137
13322
|
case PM_CASE_PRIMITIVE: {
|
13138
|
-
pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_MAX, diag_id);
|
13323
|
+
pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_MAX, false, diag_id);
|
13139
13324
|
|
13140
13325
|
// Now that we have a primitive, we need to check if it's part of a range.
|
13141
13326
|
if (accept2(parser, PM_TOKEN_DOT_DOT, PM_TOKEN_DOT_DOT_DOT)) {
|
@@ -13146,7 +13331,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
|
|
13146
13331
|
// node. Otherwise, we'll create an endless range.
|
13147
13332
|
switch (parser->current.type) {
|
13148
13333
|
case PM_CASE_PRIMITIVE: {
|
13149
|
-
pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE);
|
13334
|
+
pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE);
|
13150
13335
|
return (pm_node_t *) pm_range_node_create(parser, node, &operator, right);
|
13151
13336
|
}
|
13152
13337
|
default:
|
@@ -13206,7 +13391,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
|
|
13206
13391
|
pm_token_t lparen = parser->current;
|
13207
13392
|
parser_lex(parser);
|
13208
13393
|
|
13209
|
-
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN);
|
13394
|
+
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN);
|
13210
13395
|
parser->pattern_matching_newlines = previous_pattern_matching_newlines;
|
13211
13396
|
|
13212
13397
|
accept1(parser, PM_TOKEN_NEWLINE);
|
@@ -13307,9 +13492,13 @@ parse_pattern_primitives(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
|
|
13307
13492
|
|
13308
13493
|
expect1(parser, PM_TOKEN_IDENTIFIER, PM_ERR_PATTERN_IDENT_AFTER_HROCKET);
|
13309
13494
|
pm_token_t identifier = parser->previous;
|
13310
|
-
|
13495
|
+
int depth = pm_parser_local_depth(parser, &identifier);
|
13496
|
+
if (depth < 0) {
|
13497
|
+
depth = 0;
|
13498
|
+
pm_parser_local_add_token(parser, &identifier);
|
13499
|
+
}
|
13311
13500
|
|
13312
|
-
pm_node_t *target = (pm_node_t *)
|
13501
|
+
pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create_depth(parser, &identifier, (uint32_t) depth);
|
13313
13502
|
node = (pm_node_t *) pm_capture_pattern_node_create(parser, node, target, &operator);
|
13314
13503
|
}
|
13315
13504
|
|
@@ -13370,6 +13559,8 @@ parse_pattern(pm_parser_t *parser, bool top_pattern, pm_diagnostic_id_t diag_id)
|
|
13370
13559
|
while (accept1(parser, PM_TOKEN_COMMA)) {
|
13371
13560
|
// Break early here in case we have a trailing comma.
|
13372
13561
|
if (match5(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) {
|
13562
|
+
node = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
|
13563
|
+
pm_node_list_append(&nodes, node);
|
13373
13564
|
break;
|
13374
13565
|
}
|
13375
13566
|
|
@@ -13460,13 +13651,15 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
|
|
13460
13651
|
|
13461
13652
|
// Here we have found a string literal. We'll parse it and add it to
|
13462
13653
|
// the list of strings.
|
13463
|
-
|
13464
|
-
|
13654
|
+
const pm_lex_mode_t *lex_mode = parser->lex_modes.current;
|
13655
|
+
assert(lex_mode->mode == PM_LEX_STRING);
|
13656
|
+
bool lex_interpolation = lex_mode->as.string.interpolation;
|
13465
13657
|
|
13466
13658
|
pm_token_t opening = parser->current;
|
13467
13659
|
parser_lex(parser);
|
13468
13660
|
|
13469
|
-
if (
|
13661
|
+
if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
|
13662
|
+
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_TERM);
|
13470
13663
|
// If we get here, then we have an end immediately after a
|
13471
13664
|
// start. In that case we'll create an empty content token and
|
13472
13665
|
// return an uninterpolated string.
|
@@ -13489,15 +13682,16 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
|
|
13489
13682
|
// If we don't accept interpolation then we expect the string to
|
13490
13683
|
// start with a single string content node.
|
13491
13684
|
pm_string_t unescaped;
|
13685
|
+
pm_token_t content;
|
13492
13686
|
if (match1(parser, PM_TOKEN_EOF)) {
|
13493
13687
|
unescaped = PM_STRING_EMPTY;
|
13688
|
+
content = not_provided(parser);
|
13494
13689
|
} else {
|
13495
13690
|
unescaped = parser->current_string;
|
13691
|
+
expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_EXPECT_STRING_CONTENT);
|
13692
|
+
content = parser->previous;
|
13496
13693
|
}
|
13497
13694
|
|
13498
|
-
expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_EXPECT_STRING_CONTENT);
|
13499
|
-
pm_token_t content = parser->previous;
|
13500
|
-
|
13501
13695
|
// It is unfortunately possible to have multiple string content
|
13502
13696
|
// nodes in a row in the case that there's heredoc content in
|
13503
13697
|
// the middle of the string, like this cursed example:
|
@@ -13526,6 +13720,9 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
|
|
13526
13720
|
node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous);
|
13527
13721
|
} else if (accept1(parser, PM_TOKEN_LABEL_END) && !state_is_arg_labeled) {
|
13528
13722
|
node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
|
13723
|
+
} else if (match1(parser, PM_TOKEN_EOF)) {
|
13724
|
+
pm_parser_err_token(parser, &opening, PM_ERR_STRING_LITERAL_TERM);
|
13725
|
+
node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
|
13529
13726
|
} else {
|
13530
13727
|
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_TERM);
|
13531
13728
|
node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
|
@@ -13539,9 +13736,10 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
|
|
13539
13736
|
pm_string_t unescaped = parser->current_string;
|
13540
13737
|
parser_lex(parser);
|
13541
13738
|
|
13542
|
-
if (
|
13739
|
+
if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
|
13543
13740
|
node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
|
13544
|
-
|
13741
|
+
pm_node_flag_set(node, parse_unescaped_encoding(parser));
|
13742
|
+
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_TERM);
|
13545
13743
|
} else if (accept1(parser, PM_TOKEN_LABEL_END)) {
|
13546
13744
|
node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
|
13547
13745
|
} else {
|
@@ -13552,6 +13750,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
|
|
13552
13750
|
pm_token_t string_closing = not_provided(parser);
|
13553
13751
|
|
13554
13752
|
pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &string_opening, &parser->previous, &string_closing, &unescaped);
|
13753
|
+
pm_node_flag_set(part, parse_unescaped_encoding(parser));
|
13555
13754
|
pm_node_list_append(&parts, part);
|
13556
13755
|
|
13557
13756
|
while (!match3(parser, PM_TOKEN_STRING_END, PM_TOKEN_LABEL_END, PM_TOKEN_EOF)) {
|
@@ -13562,6 +13761,9 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
|
|
13562
13761
|
|
13563
13762
|
if (accept1(parser, PM_TOKEN_LABEL_END) && !state_is_arg_labeled) {
|
13564
13763
|
node = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous);
|
13764
|
+
} else if (match1(parser, PM_TOKEN_EOF)) {
|
13765
|
+
pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM);
|
13766
|
+
node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current);
|
13565
13767
|
} else {
|
13566
13768
|
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM);
|
13567
13769
|
node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous);
|
@@ -13582,6 +13784,9 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
|
|
13582
13784
|
|
13583
13785
|
if (accept1(parser, PM_TOKEN_LABEL_END)) {
|
13584
13786
|
node = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous);
|
13787
|
+
} else if (match1(parser, PM_TOKEN_EOF)) {
|
13788
|
+
pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM);
|
13789
|
+
node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current);
|
13585
13790
|
} else {
|
13586
13791
|
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM);
|
13587
13792
|
node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous);
|
@@ -13629,7 +13834,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
|
|
13629
13834
|
* Parse an expression that begins with the previous node that we just lexed.
|
13630
13835
|
*/
|
13631
13836
|
static inline pm_node_t *
|
13632
|
-
parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
13837
|
+
parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call) {
|
13633
13838
|
switch (parser->current.type) {
|
13634
13839
|
case PM_TOKEN_BRACKET_LEFT_ARRAY: {
|
13635
13840
|
parser_lex(parser);
|
@@ -13665,7 +13870,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13665
13870
|
pm_parser_err_token(parser, &operator, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
|
13666
13871
|
}
|
13667
13872
|
} else {
|
13668
|
-
expression =
|
13873
|
+
expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR);
|
13669
13874
|
}
|
13670
13875
|
|
13671
13876
|
element = (pm_node_t *) pm_splat_node_create(parser, &operator, expression);
|
@@ -13683,7 +13888,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13683
13888
|
|
13684
13889
|
parsed_bare_hash = true;
|
13685
13890
|
} else {
|
13686
|
-
element =
|
13891
|
+
element = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_ARRAY_EXPRESSION);
|
13687
13892
|
|
13688
13893
|
if (pm_symbol_node_label_p(element) || accept1(parser, PM_TOKEN_EQUAL_GREATER)) {
|
13689
13894
|
if (parsed_bare_hash) {
|
@@ -13699,7 +13904,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13699
13904
|
operator = not_provided(parser);
|
13700
13905
|
}
|
13701
13906
|
|
13702
|
-
pm_node_t *value =
|
13907
|
+
pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_VALUE);
|
13703
13908
|
pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, element, &operator, value);
|
13704
13909
|
pm_keyword_hash_node_elements_append(hash, assoc);
|
13705
13910
|
|
@@ -13740,7 +13945,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13740
13945
|
// of statements within the parentheses.
|
13741
13946
|
pm_accepts_block_stack_push(parser, true);
|
13742
13947
|
context_push(parser, PM_CONTEXT_PARENS);
|
13743
|
-
pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT, PM_ERR_CANNOT_PARSE_EXPRESSION);
|
13948
|
+
pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_CANNOT_PARSE_EXPRESSION);
|
13744
13949
|
context_pop(parser);
|
13745
13950
|
|
13746
13951
|
// Determine if this statement is followed by a terminator. In the
|
@@ -13816,7 +14021,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13816
14021
|
|
13817
14022
|
// Parse each statement within the parentheses.
|
13818
14023
|
while (true) {
|
13819
|
-
pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, PM_ERR_CANNOT_PARSE_EXPRESSION);
|
14024
|
+
pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_CANNOT_PARSE_EXPRESSION);
|
13820
14025
|
pm_statements_node_body_append(statements, node);
|
13821
14026
|
|
13822
14027
|
// If we're recovering from a syntax error, then we need to stop
|
@@ -13879,6 +14084,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13879
14084
|
|
13880
14085
|
pm_token_t closing = not_provided(parser);
|
13881
14086
|
pm_node_t *node = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &content, &closing);
|
14087
|
+
pm_node_flag_set(node, parse_unescaped_encoding(parser));
|
13882
14088
|
|
13883
14089
|
// Characters can be followed by strings in which case they are
|
13884
14090
|
// automatically concatenated.
|
@@ -13906,11 +14112,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13906
14112
|
// fact a method call, not a constant read.
|
13907
14113
|
if (
|
13908
14114
|
match1(parser, PM_TOKEN_PARENTHESIS_LEFT) ||
|
13909
|
-
(
|
14115
|
+
(accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) ||
|
13910
14116
|
(pm_accepts_block_stack_p(parser) && match2(parser, PM_TOKEN_KEYWORD_DO, PM_TOKEN_BRACE_LEFT))
|
13911
14117
|
) {
|
13912
14118
|
pm_arguments_t arguments = { 0 };
|
13913
|
-
parse_arguments_list(parser, &arguments, true);
|
14119
|
+
parse_arguments_list(parser, &arguments, true, accepts_command_call);
|
13914
14120
|
return (pm_node_t *) pm_call_node_fcall_create(parser, &constant, &arguments);
|
13915
14121
|
}
|
13916
14122
|
|
@@ -13944,7 +14150,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
13944
14150
|
pm_token_t operator = parser->current;
|
13945
14151
|
parser_lex(parser);
|
13946
14152
|
|
13947
|
-
pm_node_t *right = parse_expression(parser,
|
14153
|
+
pm_node_t *right = parse_expression(parser, pm_binding_powers[operator.type].left, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
13948
14154
|
return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
|
13949
14155
|
}
|
13950
14156
|
case PM_TOKEN_FLOAT:
|
@@ -14003,10 +14209,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14003
14209
|
pm_call_node_t *call = (pm_call_node_t *) node;
|
14004
14210
|
pm_arguments_t arguments = { 0 };
|
14005
14211
|
|
14006
|
-
if (parse_arguments_list(parser, &arguments, true)) {
|
14212
|
+
if (parse_arguments_list(parser, &arguments, true, accepts_command_call)) {
|
14007
14213
|
// Since we found arguments, we need to turn off the
|
14008
14214
|
// variable call bit in the flags.
|
14009
|
-
|
14215
|
+
pm_node_flag_unset((pm_node_t *)call, PM_CALL_NODE_FLAGS_VARIABLE_CALL);
|
14010
14216
|
|
14011
14217
|
call->opening_loc = arguments.opening_loc;
|
14012
14218
|
call->arguments = arguments.arguments;
|
@@ -14030,11 +14236,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14030
14236
|
// can still be a method call if it is followed by arguments or
|
14031
14237
|
// a block, so we need to check for that here.
|
14032
14238
|
if (
|
14033
|
-
(
|
14239
|
+
(accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) ||
|
14034
14240
|
(pm_accepts_block_stack_p(parser) && match2(parser, PM_TOKEN_KEYWORD_DO, PM_TOKEN_BRACE_LEFT))
|
14035
14241
|
) {
|
14036
14242
|
pm_arguments_t arguments = { 0 };
|
14037
|
-
parse_arguments_list(parser, &arguments, true);
|
14243
|
+
parse_arguments_list(parser, &arguments, true, accepts_command_call);
|
14038
14244
|
|
14039
14245
|
pm_call_node_t *fcall = pm_call_node_fcall_create(parser, &identifier, &arguments);
|
14040
14246
|
pm_node_destroy(parser, node);
|
@@ -14065,7 +14271,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14065
14271
|
if (match2(parser, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) {
|
14066
14272
|
// If we get here, then we have an empty heredoc. We'll create
|
14067
14273
|
// an empty content token and return an empty string node.
|
14068
|
-
|
14274
|
+
lex_mode_pop(parser);
|
14069
14275
|
expect1(parser, PM_TOKEN_HEREDOC_END, PM_ERR_HEREDOC_TERM);
|
14070
14276
|
pm_token_t content = parse_strings_empty_content(parser->previous.start);
|
14071
14277
|
|
@@ -14086,6 +14292,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14086
14292
|
// content and we're at the end of the heredoc, so we can return
|
14087
14293
|
// just a string node with the heredoc opening and closing as
|
14088
14294
|
// its opening and closing.
|
14295
|
+
pm_node_flag_set(part, parse_unescaped_encoding(parser));
|
14089
14296
|
pm_string_node_t *cast = (pm_string_node_t *) part;
|
14090
14297
|
|
14091
14298
|
cast->opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
|
@@ -14097,13 +14304,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14097
14304
|
cast->base.type = PM_X_STRING_NODE;
|
14098
14305
|
}
|
14099
14306
|
|
14100
|
-
size_t common_whitespace =
|
14307
|
+
size_t common_whitespace = lex_mode->as.heredoc.common_whitespace;
|
14101
14308
|
if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) {
|
14102
14309
|
parse_heredoc_dedent_string(&cast->unescaped, common_whitespace);
|
14103
14310
|
}
|
14104
14311
|
|
14105
14312
|
node = (pm_node_t *) cast;
|
14106
|
-
|
14313
|
+
lex_mode_pop(parser);
|
14107
14314
|
expect1(parser, PM_TOKEN_HEREDOC_END, PM_ERR_HEREDOC_TERM);
|
14108
14315
|
} else {
|
14109
14316
|
// If we get here, then we have multiple parts in the heredoc,
|
@@ -14118,13 +14325,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14118
14325
|
}
|
14119
14326
|
}
|
14120
14327
|
|
14328
|
+
size_t common_whitespace = lex_mode->as.heredoc.common_whitespace;
|
14329
|
+
|
14121
14330
|
// Now that we have all of the parts, create the correct type of
|
14122
14331
|
// interpolated node.
|
14123
14332
|
if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
|
14124
14333
|
pm_interpolated_x_string_node_t *cast = pm_interpolated_xstring_node_create(parser, &opening, &opening);
|
14125
14334
|
cast->parts = parts;
|
14126
14335
|
|
14127
|
-
|
14336
|
+
lex_mode_pop(parser);
|
14128
14337
|
expect1(parser, PM_TOKEN_HEREDOC_END, PM_ERR_HEREDOC_TERM);
|
14129
14338
|
|
14130
14339
|
pm_interpolated_xstring_node_closing_set(cast, &parser->previous);
|
@@ -14133,7 +14342,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14133
14342
|
} else {
|
14134
14343
|
pm_interpolated_string_node_t *cast = pm_interpolated_string_node_create(parser, &opening, &parts, &opening);
|
14135
14344
|
|
14136
|
-
|
14345
|
+
lex_mode_pop(parser);
|
14137
14346
|
expect1(parser, PM_TOKEN_HEREDOC_END, PM_ERR_HEREDOC_TERM);
|
14138
14347
|
|
14139
14348
|
pm_interpolated_string_node_closing_set(cast, &parser->previous);
|
@@ -14143,7 +14352,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14143
14352
|
|
14144
14353
|
// If this is a heredoc that is indented with a ~, then we need
|
14145
14354
|
// to dedent each line by the common leading whitespace.
|
14146
|
-
size_t common_whitespace = parser->current_string_common_whitespace;
|
14147
14355
|
if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) {
|
14148
14356
|
pm_node_list_t *nodes;
|
14149
14357
|
if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
|
@@ -14202,6 +14410,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14202
14410
|
parser_lex(parser);
|
14203
14411
|
return (pm_node_t *) pm_source_line_node_create(parser, &parser->previous);
|
14204
14412
|
case PM_TOKEN_KEYWORD_ALIAS: {
|
14413
|
+
if (binding_power != PM_BINDING_POWER_STATEMENT) {
|
14414
|
+
pm_parser_err_current(parser, PM_ERR_STATEMENT_ALIAS);
|
14415
|
+
}
|
14416
|
+
|
14205
14417
|
parser_lex(parser);
|
14206
14418
|
pm_token_t keyword = parser->previous;
|
14207
14419
|
|
@@ -14246,7 +14458,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14246
14458
|
} else if (!token_begins_expression_p(parser->current.type)) {
|
14247
14459
|
predicate = NULL;
|
14248
14460
|
} else {
|
14249
|
-
predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_CASE_EXPRESSION_AFTER_CASE);
|
14461
|
+
predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CASE_EXPRESSION_AFTER_CASE);
|
14250
14462
|
while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON));
|
14251
14463
|
}
|
14252
14464
|
|
@@ -14273,14 +14485,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14273
14485
|
do {
|
14274
14486
|
if (accept1(parser, PM_TOKEN_USTAR)) {
|
14275
14487
|
pm_token_t operator = parser->previous;
|
14276
|
-
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
14488
|
+
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
14277
14489
|
|
14278
14490
|
pm_splat_node_t *splat_node = pm_splat_node_create(parser, &operator, expression);
|
14279
14491
|
pm_when_node_conditions_append(when_node, (pm_node_t *) splat_node);
|
14280
14492
|
|
14281
14493
|
if (PM_NODE_TYPE_P(expression, PM_MISSING_NODE)) break;
|
14282
14494
|
} else {
|
14283
|
-
pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_CASE_EXPRESSION_AFTER_WHEN);
|
14495
|
+
pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_CASE_EXPRESSION_AFTER_WHEN);
|
14284
14496
|
pm_when_node_conditions_append(when_node, condition);
|
14285
14497
|
|
14286
14498
|
if (PM_NODE_TYPE_P(condition, PM_MISSING_NODE)) break;
|
@@ -14337,11 +14549,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14337
14549
|
// for guard clauses in the form of `if` or `unless` statements.
|
14338
14550
|
if (accept1(parser, PM_TOKEN_KEYWORD_IF_MODIFIER)) {
|
14339
14551
|
pm_token_t keyword = parser->previous;
|
14340
|
-
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_CONDITIONAL_IF_PREDICATE);
|
14552
|
+
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, true, PM_ERR_CONDITIONAL_IF_PREDICATE);
|
14341
14553
|
pattern = (pm_node_t *) pm_if_node_modifier_create(parser, pattern, &keyword, predicate);
|
14342
14554
|
} else if (accept1(parser, PM_TOKEN_KEYWORD_UNLESS_MODIFIER)) {
|
14343
14555
|
pm_token_t keyword = parser->previous;
|
14344
|
-
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_CONDITIONAL_UNLESS_PREDICATE);
|
14556
|
+
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, true, PM_ERR_CONDITIONAL_UNLESS_PREDICATE);
|
14345
14557
|
pattern = (pm_node_t *) pm_unless_node_modifier_create(parser, pattern, &keyword, predicate);
|
14346
14558
|
}
|
14347
14559
|
|
@@ -14426,7 +14638,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14426
14638
|
}
|
14427
14639
|
|
14428
14640
|
pm_begin_node_t *begin_node = pm_begin_node_create(parser, &begin_keyword, begin_statements);
|
14429
|
-
parse_rescues(parser, begin_node);
|
14641
|
+
parse_rescues(parser, begin_node, false);
|
14430
14642
|
|
14431
14643
|
expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BEGIN_TERM);
|
14432
14644
|
begin_node->base.location.end = parser->previous.end;
|
@@ -14439,6 +14651,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14439
14651
|
return (pm_node_t *) begin_node;
|
14440
14652
|
}
|
14441
14653
|
case PM_TOKEN_KEYWORD_BEGIN_UPCASE: {
|
14654
|
+
if (binding_power != PM_BINDING_POWER_STATEMENT) {
|
14655
|
+
pm_parser_err_current(parser, PM_ERR_STATEMENT_PREEXE_BEGIN);
|
14656
|
+
}
|
14657
|
+
|
14442
14658
|
parser_lex(parser);
|
14443
14659
|
pm_token_t keyword = parser->previous;
|
14444
14660
|
|
@@ -14496,7 +14712,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14496
14712
|
|
14497
14713
|
pm_token_t keyword = parser->previous;
|
14498
14714
|
pm_arguments_t arguments = { 0 };
|
14499
|
-
parse_arguments_list(parser, &arguments, true);
|
14715
|
+
parse_arguments_list(parser, &arguments, true, accepts_command_call);
|
14500
14716
|
|
14501
14717
|
if (
|
14502
14718
|
arguments.opening_loc.start == NULL &&
|
@@ -14513,7 +14729,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14513
14729
|
|
14514
14730
|
pm_token_t keyword = parser->previous;
|
14515
14731
|
pm_arguments_t arguments = { 0 };
|
14516
|
-
parse_arguments_list(parser, &arguments, false);
|
14732
|
+
parse_arguments_list(parser, &arguments, false, accepts_command_call);
|
14517
14733
|
|
14518
14734
|
return (pm_node_t *) pm_yield_node_create(parser, &keyword, &arguments.opening_loc, arguments.arguments, &arguments.closing_loc);
|
14519
14735
|
}
|
@@ -14524,8 +14740,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14524
14740
|
|
14525
14741
|
if (accept1(parser, PM_TOKEN_LESS_LESS)) {
|
14526
14742
|
pm_token_t operator = parser->previous;
|
14527
|
-
pm_node_t *expression =
|
14743
|
+
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_NOT, true, PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS);
|
14528
14744
|
|
14745
|
+
pm_constant_id_t old_param_name = parser->current_param_name;
|
14746
|
+
parser->current_param_name = 0;
|
14529
14747
|
pm_parser_scope_push(parser, true);
|
14530
14748
|
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
|
14531
14749
|
|
@@ -14538,18 +14756,19 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14538
14756
|
|
14539
14757
|
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
|
14540
14758
|
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
|
14541
|
-
statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements);
|
14759
|
+
statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false);
|
14542
14760
|
}
|
14543
14761
|
|
14544
14762
|
expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM);
|
14545
14763
|
|
14546
14764
|
pm_constant_id_list_t locals = parser->current_scope->locals;
|
14547
14765
|
pm_parser_scope_pop(parser);
|
14766
|
+
parser->current_param_name = old_param_name;
|
14548
14767
|
pm_do_loop_stack_pop(parser);
|
14549
14768
|
return (pm_node_t *) pm_singleton_class_node_create(parser, &locals, &class_keyword, &operator, expression, statements, &parser->previous);
|
14550
14769
|
}
|
14551
14770
|
|
14552
|
-
pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, PM_ERR_CLASS_NAME);
|
14771
|
+
pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_CLASS_NAME);
|
14553
14772
|
pm_token_t name = parser->previous;
|
14554
14773
|
if (name.type != PM_TOKEN_CONSTANT) {
|
14555
14774
|
pm_parser_err_token(parser, &name, PM_ERR_CLASS_NAME);
|
@@ -14565,12 +14784,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14565
14784
|
parser->command_start = true;
|
14566
14785
|
parser_lex(parser);
|
14567
14786
|
|
14568
|
-
superclass = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_CLASS_SUPERCLASS);
|
14787
|
+
superclass = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CLASS_SUPERCLASS);
|
14569
14788
|
} else {
|
14570
14789
|
inheritance_operator = not_provided(parser);
|
14571
14790
|
superclass = NULL;
|
14572
14791
|
}
|
14573
14792
|
|
14793
|
+
pm_constant_id_t old_param_name = parser->current_param_name;
|
14794
|
+
parser->current_param_name = 0;
|
14574
14795
|
pm_parser_scope_push(parser, true);
|
14575
14796
|
if (inheritance_operator.type != PM_TOKEN_NOT_PROVIDED) {
|
14576
14797
|
expect2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CLASS_UNEXPECTED_END);
|
@@ -14587,7 +14808,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14587
14808
|
|
14588
14809
|
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
|
14589
14810
|
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
|
14590
|
-
statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements);
|
14811
|
+
statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false);
|
14591
14812
|
}
|
14592
14813
|
|
14593
14814
|
expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM);
|
@@ -14598,6 +14819,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14598
14819
|
|
14599
14820
|
pm_constant_id_list_t locals = parser->current_scope->locals;
|
14600
14821
|
pm_parser_scope_pop(parser);
|
14822
|
+
parser->current_param_name = old_param_name;
|
14601
14823
|
pm_do_loop_stack_pop(parser);
|
14602
14824
|
|
14603
14825
|
if (!PM_NODE_TYPE_P(constant_path, PM_CONSTANT_PATH_NODE) && !(PM_NODE_TYPE_P(constant_path, PM_CONSTANT_READ_NODE))) {
|
@@ -14613,12 +14835,16 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14613
14835
|
pm_token_t operator = not_provided(parser);
|
14614
14836
|
pm_token_t name = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = def_keyword.end, .end = def_keyword.end };
|
14615
14837
|
|
14838
|
+
// This context is necessary for lexing `...` in a bare params correctly.
|
14839
|
+
// It must be pushed before lexing the first param, so it is here.
|
14616
14840
|
context_push(parser, PM_CONTEXT_DEF_PARAMS);
|
14617
14841
|
parser_lex(parser);
|
14842
|
+
pm_constant_id_t old_param_name = parser->current_param_name;
|
14618
14843
|
|
14619
14844
|
switch (parser->current.type) {
|
14620
14845
|
case PM_CASE_OPERATOR:
|
14621
14846
|
pm_parser_scope_push(parser, true);
|
14847
|
+
parser->current_param_name = 0;
|
14622
14848
|
lex_state_set(parser, PM_LEX_STATE_ENDFN);
|
14623
14849
|
parser_lex(parser);
|
14624
14850
|
name = parser->previous;
|
@@ -14630,6 +14856,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14630
14856
|
receiver = parse_variable_call(parser);
|
14631
14857
|
|
14632
14858
|
pm_parser_scope_push(parser, true);
|
14859
|
+
parser->current_param_name = 0;
|
14633
14860
|
lex_state_set(parser, PM_LEX_STATE_FNAME);
|
14634
14861
|
parser_lex(parser);
|
14635
14862
|
|
@@ -14638,6 +14865,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14638
14865
|
} else {
|
14639
14866
|
pm_refute_numbered_parameter(parser, parser->previous.start, parser->previous.end);
|
14640
14867
|
pm_parser_scope_push(parser, true);
|
14868
|
+
parser->current_param_name = 0;
|
14641
14869
|
name = parser->previous;
|
14642
14870
|
}
|
14643
14871
|
|
@@ -14655,6 +14883,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14655
14883
|
case PM_TOKEN_KEYWORD___LINE__:
|
14656
14884
|
case PM_TOKEN_KEYWORD___ENCODING__: {
|
14657
14885
|
pm_parser_scope_push(parser, true);
|
14886
|
+
parser->current_param_name = 0;
|
14658
14887
|
parser_lex(parser);
|
14659
14888
|
pm_token_t identifier = parser->previous;
|
14660
14889
|
|
@@ -14708,9 +14937,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14708
14937
|
break;
|
14709
14938
|
}
|
14710
14939
|
case PM_TOKEN_PARENTHESIS_LEFT: {
|
14940
|
+
// The current context is `PM_CONTEXT_DEF_PARAMS`, however the inner expression
|
14941
|
+
// of this parenthesis should not be processed under this context.
|
14942
|
+
// Thus, the context is popped here.
|
14943
|
+
context_pop(parser);
|
14711
14944
|
parser_lex(parser);
|
14945
|
+
|
14712
14946
|
pm_token_t lparen = parser->previous;
|
14713
|
-
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, PM_ERR_DEF_RECEIVER);
|
14947
|
+
pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_DEF_RECEIVER);
|
14714
14948
|
|
14715
14949
|
expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN);
|
14716
14950
|
pm_token_t rparen = parser->previous;
|
@@ -14722,11 +14956,16 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14722
14956
|
receiver = (pm_node_t *) pm_parentheses_node_create(parser, &lparen, expression, &rparen);
|
14723
14957
|
|
14724
14958
|
pm_parser_scope_push(parser, true);
|
14959
|
+
parser->current_param_name = 0;
|
14960
|
+
|
14961
|
+
// To push `PM_CONTEXT_DEF_PARAMS` again is for the same reason as described the above.
|
14962
|
+
context_push(parser, PM_CONTEXT_DEF_PARAMS);
|
14725
14963
|
name = parse_method_definition_name(parser);
|
14726
14964
|
break;
|
14727
14965
|
}
|
14728
14966
|
default:
|
14729
14967
|
pm_parser_scope_push(parser, true);
|
14968
|
+
parser->current_param_name = 0;
|
14730
14969
|
name = parse_method_definition_name(parser);
|
14731
14970
|
break;
|
14732
14971
|
}
|
@@ -14779,6 +15018,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14779
15018
|
}
|
14780
15019
|
}
|
14781
15020
|
|
15021
|
+
uint32_t locals_body_index = (uint32_t) parser->current_scope->locals.size;
|
15022
|
+
|
14782
15023
|
context_pop(parser);
|
14783
15024
|
pm_node_t *statements = NULL;
|
14784
15025
|
pm_token_t equal;
|
@@ -14794,11 +15035,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14794
15035
|
pm_do_loop_stack_push(parser, false);
|
14795
15036
|
statements = (pm_node_t *) pm_statements_node_create(parser);
|
14796
15037
|
|
14797
|
-
pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, PM_ERR_DEF_ENDLESS);
|
15038
|
+
pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, binding_power < PM_BINDING_POWER_COMPOSITION, PM_ERR_DEF_ENDLESS);
|
14798
15039
|
|
14799
15040
|
if (accept1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) {
|
14800
15041
|
pm_token_t rescue_keyword = parser->previous;
|
14801
|
-
pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_RESCUE_MODIFIER_VALUE);
|
15042
|
+
pm_node_t *value = parse_expression(parser, binding_power, false, PM_ERR_RESCUE_MODIFIER_VALUE);
|
14802
15043
|
pm_rescue_modifier_node_t *rescue_node = pm_rescue_modifier_node_create(parser, statement, &rescue_keyword, value);
|
14803
15044
|
statement = (pm_node_t *)rescue_node;
|
14804
15045
|
}
|
@@ -14829,7 +15070,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14829
15070
|
|
14830
15071
|
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
|
14831
15072
|
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
|
14832
|
-
statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements);
|
15073
|
+
statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, true);
|
14833
15074
|
}
|
14834
15075
|
|
14835
15076
|
pm_accepts_block_stack_pop(parser);
|
@@ -14839,6 +15080,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14839
15080
|
}
|
14840
15081
|
|
14841
15082
|
pm_constant_id_list_t locals = parser->current_scope->locals;
|
15083
|
+
parser->current_param_name = old_param_name;
|
14842
15084
|
pm_parser_scope_pop(parser);
|
14843
15085
|
|
14844
15086
|
return (pm_node_t *) pm_def_node_create(
|
@@ -14848,6 +15090,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14848
15090
|
params,
|
14849
15091
|
statements,
|
14850
15092
|
&locals,
|
15093
|
+
locals_body_index,
|
14851
15094
|
&def_keyword,
|
14852
15095
|
&operator,
|
14853
15096
|
&lparen,
|
@@ -14866,18 +15109,19 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14866
15109
|
|
14867
15110
|
if (accept1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
|
14868
15111
|
lparen = parser->previous;
|
14869
|
-
expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_DEFINED_EXPRESSION);
|
15112
|
+
expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_DEFINED_EXPRESSION);
|
14870
15113
|
|
14871
15114
|
if (parser->recovering) {
|
14872
15115
|
rparen = not_provided(parser);
|
14873
15116
|
} else {
|
15117
|
+
accept1(parser, PM_TOKEN_NEWLINE);
|
14874
15118
|
expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN);
|
14875
15119
|
rparen = parser->previous;
|
14876
15120
|
}
|
14877
15121
|
} else {
|
14878
15122
|
lparen = not_provided(parser);
|
14879
15123
|
rparen = not_provided(parser);
|
14880
|
-
expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_DEFINED_EXPRESSION);
|
15124
|
+
expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_DEFINED_EXPRESSION);
|
14881
15125
|
}
|
14882
15126
|
|
14883
15127
|
return (pm_node_t *) pm_defined_node_create(
|
@@ -14889,6 +15133,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14889
15133
|
);
|
14890
15134
|
}
|
14891
15135
|
case PM_TOKEN_KEYWORD_END_UPCASE: {
|
15136
|
+
if (binding_power != PM_BINDING_POWER_STATEMENT) {
|
15137
|
+
pm_parser_err_current(parser, PM_ERR_STATEMENT_POSTEXE_END);
|
15138
|
+
}
|
15139
|
+
|
14892
15140
|
parser_lex(parser);
|
14893
15141
|
pm_token_t keyword = parser->previous;
|
14894
15142
|
|
@@ -14911,7 +15159,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14911
15159
|
pm_token_t for_keyword = parser->previous;
|
14912
15160
|
pm_node_t *index;
|
14913
15161
|
|
14914
|
-
pm_parser_scope_push_transparent(parser);
|
14915
15162
|
context_push(parser, PM_CONTEXT_FOR_INDEX);
|
14916
15163
|
|
14917
15164
|
// First, parse out the first index expression.
|
@@ -14920,12 +15167,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14920
15167
|
pm_node_t *name = NULL;
|
14921
15168
|
|
14922
15169
|
if (token_begins_expression_p(parser->current.type)) {
|
14923
|
-
name = parse_expression(parser, PM_BINDING_POWER_INDEX, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
15170
|
+
name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
14924
15171
|
}
|
14925
15172
|
|
14926
15173
|
index = (pm_node_t *) pm_splat_node_create(parser, &star_operator, name);
|
14927
15174
|
} else if (token_begins_expression_p(parser->current.type)) {
|
14928
|
-
index = parse_expression(parser, PM_BINDING_POWER_INDEX, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA);
|
15175
|
+
index = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA);
|
14929
15176
|
} else {
|
14930
15177
|
pm_parser_err_token(parser, &for_keyword, PM_ERR_FOR_INDEX);
|
14931
15178
|
index = (pm_node_t *) pm_missing_node_create(parser, for_keyword.start, for_keyword.end);
|
@@ -14939,13 +15186,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14939
15186
|
}
|
14940
15187
|
|
14941
15188
|
context_pop(parser);
|
14942
|
-
pm_parser_scope_pop(parser);
|
14943
15189
|
pm_do_loop_stack_push(parser, true);
|
14944
15190
|
|
14945
15191
|
expect1(parser, PM_TOKEN_KEYWORD_IN, PM_ERR_FOR_IN);
|
14946
15192
|
pm_token_t in_keyword = parser->previous;
|
14947
15193
|
|
14948
|
-
pm_node_t *collection = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_FOR_COLLECTION);
|
15194
|
+
pm_node_t *collection = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_FOR_COLLECTION);
|
14949
15195
|
pm_do_loop_stack_pop(parser);
|
14950
15196
|
|
14951
15197
|
pm_token_t do_keyword;
|
@@ -14959,10 +15205,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14959
15205
|
pm_statements_node_t *statements = NULL;
|
14960
15206
|
|
14961
15207
|
if (!accept1(parser, PM_TOKEN_KEYWORD_END)) {
|
14962
|
-
pm_parser_scope_push_transparent(parser);
|
14963
15208
|
statements = parse_statements(parser, PM_CONTEXT_FOR);
|
14964
15209
|
expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_FOR_TERM);
|
14965
|
-
pm_parser_scope_pop(parser);
|
14966
15210
|
}
|
14967
15211
|
|
14968
15212
|
return (pm_node_t *) pm_for_node_create(parser, index, collection, statements, &for_keyword, &in_keyword, &do_keyword, &parser->previous);
|
@@ -14971,6 +15215,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
14971
15215
|
parser_lex(parser);
|
14972
15216
|
return parse_conditional(parser, PM_CONTEXT_IF);
|
14973
15217
|
case PM_TOKEN_KEYWORD_UNDEF: {
|
15218
|
+
if (binding_power != PM_BINDING_POWER_STATEMENT) {
|
15219
|
+
pm_parser_err_current(parser, PM_ERR_STATEMENT_UNDEF);
|
15220
|
+
}
|
15221
|
+
|
14974
15222
|
parser_lex(parser);
|
14975
15223
|
pm_undef_node_t *undef = pm_undef_node_create(parser, &parser->previous);
|
14976
15224
|
pm_node_t *name = parse_undef_argument(parser);
|
@@ -15011,7 +15259,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15011
15259
|
if (accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
|
15012
15260
|
arguments.closing_loc = PM_LOCATION_TOKEN_VALUE(&parser->previous);
|
15013
15261
|
} else {
|
15014
|
-
receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_NOT_EXPRESSION);
|
15262
|
+
receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_NOT_EXPRESSION);
|
15015
15263
|
pm_conditional_predicate(receiver);
|
15016
15264
|
|
15017
15265
|
if (!parser->recovering) {
|
@@ -15021,7 +15269,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15021
15269
|
}
|
15022
15270
|
}
|
15023
15271
|
} else {
|
15024
|
-
receiver = parse_expression(parser,
|
15272
|
+
receiver = parse_expression(parser, PM_BINDING_POWER_NOT, true, PM_ERR_NOT_EXPRESSION);
|
15025
15273
|
pm_conditional_predicate(receiver);
|
15026
15274
|
}
|
15027
15275
|
|
@@ -15034,7 +15282,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15034
15282
|
parser_lex(parser);
|
15035
15283
|
|
15036
15284
|
pm_token_t module_keyword = parser->previous;
|
15037
|
-
pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, PM_ERR_MODULE_NAME);
|
15285
|
+
pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_MODULE_NAME);
|
15038
15286
|
pm_token_t name;
|
15039
15287
|
|
15040
15288
|
// If we can recover from a syntax error that occurred while parsing
|
@@ -15061,6 +15309,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15061
15309
|
pm_parser_err_token(parser, &name, PM_ERR_MODULE_NAME);
|
15062
15310
|
}
|
15063
15311
|
|
15312
|
+
pm_constant_id_t old_param_name = parser->current_param_name;
|
15313
|
+
parser->current_param_name = 0;
|
15064
15314
|
pm_parser_scope_push(parser, true);
|
15065
15315
|
accept2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE);
|
15066
15316
|
pm_node_t *statements = NULL;
|
@@ -15073,11 +15323,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15073
15323
|
|
15074
15324
|
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
|
15075
15325
|
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
|
15076
|
-
statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements);
|
15326
|
+
statements = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) statements, false);
|
15077
15327
|
}
|
15078
15328
|
|
15079
15329
|
pm_constant_id_list_t locals = parser->current_scope->locals;
|
15080
15330
|
pm_parser_scope_pop(parser);
|
15331
|
+
parser->current_param_name = old_param_name;
|
15081
15332
|
|
15082
15333
|
expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_MODULE_TERM);
|
15083
15334
|
|
@@ -15107,7 +15358,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15107
15358
|
parser_lex(parser);
|
15108
15359
|
pm_token_t keyword = parser->previous;
|
15109
15360
|
|
15110
|
-
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
|
15361
|
+
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
|
15111
15362
|
pm_do_loop_stack_pop(parser);
|
15112
15363
|
|
15113
15364
|
expect3(parser, PM_TOKEN_KEYWORD_DO_LOOP, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
|
@@ -15128,7 +15379,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15128
15379
|
parser_lex(parser);
|
15129
15380
|
pm_token_t keyword = parser->previous;
|
15130
15381
|
|
15131
|
-
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
|
15382
|
+
pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
|
15132
15383
|
pm_do_loop_stack_pop(parser);
|
15133
15384
|
|
15134
15385
|
expect3(parser, PM_TOKEN_KEYWORD_DO_LOOP, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
|
@@ -15146,7 +15397,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15146
15397
|
}
|
15147
15398
|
case PM_TOKEN_PERCENT_LOWER_I: {
|
15148
15399
|
parser_lex(parser);
|
15149
|
-
|
15400
|
+
pm_token_t opening = parser->previous;
|
15401
|
+
pm_array_node_t *array = pm_array_node_create(parser, &opening);
|
15150
15402
|
|
15151
15403
|
while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
|
15152
15404
|
accept1(parser, PM_TOKEN_WORDS_SEP);
|
@@ -15161,14 +15413,21 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15161
15413
|
expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_I_LOWER_ELEMENT);
|
15162
15414
|
}
|
15163
15415
|
|
15164
|
-
|
15165
|
-
|
15416
|
+
pm_token_t closing = parser->current;
|
15417
|
+
if (match1(parser, PM_TOKEN_EOF)) {
|
15418
|
+
pm_parser_err_token(parser, &opening, PM_ERR_LIST_I_LOWER_TERM);
|
15419
|
+
closing = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
|
15420
|
+
} else {
|
15421
|
+
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_LIST_I_LOWER_TERM);
|
15422
|
+
}
|
15423
|
+
pm_array_node_close_set(array, &closing);
|
15166
15424
|
|
15167
15425
|
return (pm_node_t *) array;
|
15168
15426
|
}
|
15169
15427
|
case PM_TOKEN_PERCENT_UPPER_I: {
|
15170
15428
|
parser_lex(parser);
|
15171
|
-
|
15429
|
+
pm_token_t opening = parser->previous;
|
15430
|
+
pm_array_node_t *array = pm_array_node_create(parser, &opening);
|
15172
15431
|
|
15173
15432
|
// This is the current node that we are parsing that will be added to the
|
15174
15433
|
// list of elements.
|
@@ -15308,14 +15567,21 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15308
15567
|
pm_array_node_elements_append(array, current);
|
15309
15568
|
}
|
15310
15569
|
|
15311
|
-
|
15312
|
-
|
15570
|
+
pm_token_t closing = parser->current;
|
15571
|
+
if (match1(parser, PM_TOKEN_EOF)) {
|
15572
|
+
pm_parser_err_token(parser, &opening, PM_ERR_LIST_I_UPPER_TERM);
|
15573
|
+
closing = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
|
15574
|
+
} else {
|
15575
|
+
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_LIST_I_UPPER_TERM);
|
15576
|
+
}
|
15577
|
+
pm_array_node_close_set(array, &closing);
|
15313
15578
|
|
15314
15579
|
return (pm_node_t *) array;
|
15315
15580
|
}
|
15316
15581
|
case PM_TOKEN_PERCENT_LOWER_W: {
|
15317
15582
|
parser_lex(parser);
|
15318
|
-
|
15583
|
+
pm_token_t opening = parser->previous;
|
15584
|
+
pm_array_node_t *array = pm_array_node_create(parser, &opening);
|
15319
15585
|
|
15320
15586
|
// skip all leading whitespaces
|
15321
15587
|
accept1(parser, PM_TOKEN_WORDS_SEP);
|
@@ -15335,28 +15601,40 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15335
15601
|
expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_W_LOWER_ELEMENT);
|
15336
15602
|
}
|
15337
15603
|
|
15338
|
-
|
15339
|
-
|
15604
|
+
pm_token_t closing = parser->current;
|
15605
|
+
if (match1(parser, PM_TOKEN_EOF)) {
|
15606
|
+
pm_parser_err_token(parser, &opening, PM_ERR_LIST_W_LOWER_TERM);
|
15607
|
+
closing = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
|
15608
|
+
} else {
|
15609
|
+
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_LIST_W_LOWER_TERM);
|
15610
|
+
}
|
15340
15611
|
|
15612
|
+
pm_array_node_close_set(array, &closing);
|
15341
15613
|
return (pm_node_t *) array;
|
15342
15614
|
}
|
15343
15615
|
case PM_TOKEN_PERCENT_UPPER_W: {
|
15344
15616
|
parser_lex(parser);
|
15345
|
-
|
15617
|
+
pm_token_t opening = parser->previous;
|
15618
|
+
pm_array_node_t *array = pm_array_node_create(parser, &opening);
|
15346
15619
|
|
15347
|
-
// This is the current node that we are parsing that will be added
|
15348
|
-
// list of elements.
|
15620
|
+
// This is the current node that we are parsing that will be added
|
15621
|
+
// to the list of elements.
|
15349
15622
|
pm_node_t *current = NULL;
|
15350
15623
|
|
15351
15624
|
while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
|
15352
15625
|
switch (parser->current.type) {
|
15353
15626
|
case PM_TOKEN_WORDS_SEP: {
|
15627
|
+
// Reset the explicit encoding if we hit a separator
|
15628
|
+
// since each element can have its own encoding.
|
15629
|
+
parser->explicit_encoding = NULL;
|
15630
|
+
|
15354
15631
|
if (current == NULL) {
|
15355
|
-
// If we hit a separator before we have any content,
|
15356
|
-
// need to do anything.
|
15632
|
+
// If we hit a separator before we have any content,
|
15633
|
+
// then we don't need to do anything.
|
15357
15634
|
} else {
|
15358
|
-
// If we hit a separator after we've hit content,
|
15359
|
-
// append that content to the list
|
15635
|
+
// If we hit a separator after we've hit content,
|
15636
|
+
// then we need to append that content to the list
|
15637
|
+
// and reset the current node.
|
15360
15638
|
pm_array_node_elements_append(array, current);
|
15361
15639
|
current = NULL;
|
15362
15640
|
}
|
@@ -15369,22 +15647,25 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15369
15647
|
pm_token_t closing = not_provided(parser);
|
15370
15648
|
|
15371
15649
|
pm_node_t *string = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->current, &closing);
|
15650
|
+
pm_node_flag_set(string, parse_unescaped_encoding(parser));
|
15372
15651
|
parser_lex(parser);
|
15373
15652
|
|
15374
15653
|
if (current == NULL) {
|
15375
|
-
// If we hit content and the current node is NULL,
|
15376
|
-
// the first string content we've seen.
|
15377
|
-
// to create a new string
|
15654
|
+
// If we hit content and the current node is NULL,
|
15655
|
+
// then this is the first string content we've seen.
|
15656
|
+
// In that case we're going to create a new string
|
15657
|
+
// node and set that to the current.
|
15378
15658
|
current = string;
|
15379
15659
|
} else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_STRING_NODE)) {
|
15380
|
-
// If we hit string content and the current node is
|
15381
|
-
// interpolated string, then we need to append
|
15382
|
-
// to the list of child nodes.
|
15660
|
+
// If we hit string content and the current node is
|
15661
|
+
// an interpolated string, then we need to append
|
15662
|
+
// the string content to the list of child nodes.
|
15383
15663
|
pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, string);
|
15384
15664
|
} else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) {
|
15385
|
-
// If we hit string content and the current node is
|
15386
|
-
// then we need to convert the
|
15387
|
-
//
|
15665
|
+
// If we hit string content and the current node is
|
15666
|
+
// a string node, then we need to convert the
|
15667
|
+
// current node into an interpolated string and add
|
15668
|
+
// the string content to the list of child nodes.
|
15388
15669
|
pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
|
15389
15670
|
pm_interpolated_string_node_append(interpolated, current);
|
15390
15671
|
pm_interpolated_string_node_append(interpolated, string);
|
@@ -15397,24 +15678,27 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15397
15678
|
}
|
15398
15679
|
case PM_TOKEN_EMBVAR: {
|
15399
15680
|
if (current == NULL) {
|
15400
|
-
// If we hit an embedded variable and the current
|
15401
|
-
// then this is the start of a new
|
15402
|
-
// node to a new
|
15681
|
+
// If we hit an embedded variable and the current
|
15682
|
+
// node is NULL, then this is the start of a new
|
15683
|
+
// string. We'll set the current node to a new
|
15684
|
+
// interpolated string.
|
15403
15685
|
pm_token_t opening = not_provided(parser);
|
15404
15686
|
pm_token_t closing = not_provided(parser);
|
15405
15687
|
current = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
|
15406
15688
|
} else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) {
|
15407
|
-
// If we hit an embedded variable and the current
|
15408
|
-
// node, then we'll convert the
|
15409
|
-
//
|
15689
|
+
// If we hit an embedded variable and the current
|
15690
|
+
// node is a string node, then we'll convert the
|
15691
|
+
// current into an interpolated string and add the
|
15692
|
+
// string node to the list of parts.
|
15410
15693
|
pm_token_t opening = not_provided(parser);
|
15411
15694
|
pm_token_t closing = not_provided(parser);
|
15412
15695
|
pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
|
15413
15696
|
pm_interpolated_string_node_append(interpolated, current);
|
15414
15697
|
current = (pm_node_t *) interpolated;
|
15415
15698
|
} else {
|
15416
|
-
// If we hit an embedded variable and the current
|
15417
|
-
// interpolated string, then we'll just
|
15699
|
+
// If we hit an embedded variable and the current
|
15700
|
+
// node is an interpolated string, then we'll just
|
15701
|
+
// add the embedded variable.
|
15418
15702
|
}
|
15419
15703
|
|
15420
15704
|
pm_node_t *part = parse_string_part(parser);
|
@@ -15423,25 +15707,27 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15423
15707
|
}
|
15424
15708
|
case PM_TOKEN_EMBEXPR_BEGIN: {
|
15425
15709
|
if (current == NULL) {
|
15426
|
-
// If we hit an embedded expression and the current
|
15427
|
-
// then this is the start of a new
|
15428
|
-
// node to a new
|
15710
|
+
// If we hit an embedded expression and the current
|
15711
|
+
// node is NULL, then this is the start of a new
|
15712
|
+
// string. We'll set the current node to a new
|
15713
|
+
// interpolated string.
|
15429
15714
|
pm_token_t opening = not_provided(parser);
|
15430
15715
|
pm_token_t closing = not_provided(parser);
|
15431
15716
|
current = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
|
15432
15717
|
} else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) {
|
15433
|
-
// If we hit an embedded expression and the current
|
15434
|
-
// string node, then we'll convert the
|
15435
|
-
// interpolated string and add the
|
15436
|
-
// parts.
|
15718
|
+
// If we hit an embedded expression and the current
|
15719
|
+
// node is a string node, then we'll convert the
|
15720
|
+
// current into an interpolated string and add the
|
15721
|
+
// string node to the list of parts.
|
15437
15722
|
pm_token_t opening = not_provided(parser);
|
15438
15723
|
pm_token_t closing = not_provided(parser);
|
15439
15724
|
pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
|
15440
15725
|
pm_interpolated_string_node_append(interpolated, current);
|
15441
15726
|
current = (pm_node_t *) interpolated;
|
15442
15727
|
} else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_STRING_NODE)) {
|
15443
|
-
// If we hit an embedded expression and the current
|
15444
|
-
// interpolated string, then we'll just
|
15728
|
+
// If we hit an embedded expression and the current
|
15729
|
+
// node is an interpolated string, then we'll just
|
15730
|
+
// continue on.
|
15445
15731
|
} else {
|
15446
15732
|
assert(false && "unreachable");
|
15447
15733
|
}
|
@@ -15462,9 +15748,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15462
15748
|
pm_array_node_elements_append(array, current);
|
15463
15749
|
}
|
15464
15750
|
|
15465
|
-
|
15466
|
-
|
15751
|
+
pm_token_t closing = parser->current;
|
15752
|
+
if (match1(parser, PM_TOKEN_EOF)) {
|
15753
|
+
pm_parser_err_token(parser, &opening, PM_ERR_LIST_W_UPPER_TERM);
|
15754
|
+
closing = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
|
15755
|
+
} else {
|
15756
|
+
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_LIST_W_UPPER_TERM);
|
15757
|
+
}
|
15467
15758
|
|
15759
|
+
pm_array_node_close_set(array, &closing);
|
15468
15760
|
return (pm_node_t *) array;
|
15469
15761
|
}
|
15470
15762
|
case PM_TOKEN_REGEXP_BEGIN: {
|
@@ -15527,8 +15819,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15527
15819
|
}
|
15528
15820
|
}
|
15529
15821
|
|
15530
|
-
|
15531
|
-
|
15822
|
+
pm_token_t closing = parser->current;
|
15823
|
+
if (match1(parser, PM_TOKEN_EOF)) {
|
15824
|
+
pm_parser_err_token(parser, &opening, PM_ERR_REGEXP_TERM);
|
15825
|
+
closing = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
|
15826
|
+
} else {
|
15827
|
+
expect1(parser, PM_TOKEN_REGEXP_END, PM_ERR_REGEXP_TERM);
|
15828
|
+
}
|
15829
|
+
pm_interpolated_regular_expression_node_closing_set(node, &closing);
|
15532
15830
|
|
15533
15831
|
return (pm_node_t *) node;
|
15534
15832
|
}
|
@@ -15566,8 +15864,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15566
15864
|
pm_token_t content = parser->current;
|
15567
15865
|
parser_lex(parser);
|
15568
15866
|
|
15569
|
-
if (
|
15570
|
-
|
15867
|
+
if (match1(parser, PM_TOKEN_STRING_END)) {
|
15868
|
+
pm_node_t *node = (pm_node_t *) pm_xstring_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
|
15869
|
+
pm_node_flag_set(node, parse_unescaped_encoding(parser));
|
15870
|
+
parser_lex(parser);
|
15871
|
+
return node;
|
15571
15872
|
}
|
15572
15873
|
|
15573
15874
|
// If we get here, then we have interpolation so we'll need to
|
@@ -15576,7 +15877,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15576
15877
|
|
15577
15878
|
pm_token_t opening = not_provided(parser);
|
15578
15879
|
pm_token_t closing = not_provided(parser);
|
15880
|
+
|
15579
15881
|
pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &parser->previous, &closing, &unescaped);
|
15882
|
+
pm_node_flag_set(part, parse_unescaped_encoding(parser));
|
15580
15883
|
|
15581
15884
|
pm_interpolated_xstring_node_append(node, part);
|
15582
15885
|
} else {
|
@@ -15593,8 +15896,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15593
15896
|
}
|
15594
15897
|
}
|
15595
15898
|
|
15596
|
-
|
15597
|
-
|
15899
|
+
pm_token_t closing = parser->current;
|
15900
|
+
if (match1(parser, PM_TOKEN_EOF)) {
|
15901
|
+
pm_parser_err_token(parser, &opening, PM_ERR_XSTRING_TERM);
|
15902
|
+
closing = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
|
15903
|
+
} else {
|
15904
|
+
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_XSTRING_TERM);
|
15905
|
+
}
|
15906
|
+
pm_interpolated_xstring_node_closing_set(node, &closing);
|
15907
|
+
|
15598
15908
|
return (pm_node_t *) node;
|
15599
15909
|
}
|
15600
15910
|
case PM_TOKEN_USTAR: {
|
@@ -15611,7 +15921,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15611
15921
|
pm_node_t *name = NULL;
|
15612
15922
|
|
15613
15923
|
if (token_begins_expression_p(parser->current.type)) {
|
15614
|
-
name = parse_expression(parser, PM_BINDING_POWER_INDEX, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
15924
|
+
name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
|
15615
15925
|
}
|
15616
15926
|
|
15617
15927
|
pm_node_t *splat = (pm_node_t *) pm_splat_node_create(parser, &operator, name);
|
@@ -15626,7 +15936,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15626
15936
|
parser_lex(parser);
|
15627
15937
|
|
15628
15938
|
pm_token_t operator = parser->previous;
|
15629
|
-
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, PM_ERR_UNARY_RECEIVER_BANG);
|
15939
|
+
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, binding_power < PM_BINDING_POWER_MATCH, PM_ERR_UNARY_RECEIVER_BANG);
|
15630
15940
|
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "!");
|
15631
15941
|
|
15632
15942
|
pm_conditional_predicate(receiver);
|
@@ -15636,7 +15946,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15636
15946
|
parser_lex(parser);
|
15637
15947
|
|
15638
15948
|
pm_token_t operator = parser->previous;
|
15639
|
-
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, PM_ERR_UNARY_RECEIVER_TILDE);
|
15949
|
+
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_TILDE);
|
15640
15950
|
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "~");
|
15641
15951
|
|
15642
15952
|
return (pm_node_t *) node;
|
@@ -15645,7 +15955,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15645
15955
|
parser_lex(parser);
|
15646
15956
|
|
15647
15957
|
pm_token_t operator = parser->previous;
|
15648
|
-
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, PM_ERR_UNARY_RECEIVER_MINUS);
|
15958
|
+
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_MINUS);
|
15649
15959
|
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "-@");
|
15650
15960
|
|
15651
15961
|
return (pm_node_t *) node;
|
@@ -15654,11 +15964,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15654
15964
|
parser_lex(parser);
|
15655
15965
|
|
15656
15966
|
pm_token_t operator = parser->previous;
|
15657
|
-
pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, PM_ERR_UNARY_RECEIVER_MINUS);
|
15967
|
+
pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_MINUS);
|
15658
15968
|
|
15659
15969
|
if (accept1(parser, PM_TOKEN_STAR_STAR)) {
|
15660
15970
|
pm_token_t exponent_operator = parser->previous;
|
15661
|
-
pm_node_t *exponent = parse_expression(parser, pm_binding_powers[exponent_operator.type].right, PM_ERR_EXPECT_ARGUMENT);
|
15971
|
+
pm_node_t *exponent = parse_expression(parser, pm_binding_powers[exponent_operator.type].right, false, PM_ERR_EXPECT_ARGUMENT);
|
15662
15972
|
node = (pm_node_t *) pm_call_node_binary_create(parser, node, &exponent_operator, exponent);
|
15663
15973
|
node = (pm_node_t *) pm_call_node_unary_create(parser, &operator, node, "-@");
|
15664
15974
|
} else {
|
@@ -15686,7 +15996,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15686
15996
|
|
15687
15997
|
pm_token_t operator = parser->previous;
|
15688
15998
|
pm_parser_scope_push(parser, false);
|
15689
|
-
pm_block_parameters_node_t *
|
15999
|
+
pm_block_parameters_node_t *block_parameters;
|
15690
16000
|
|
15691
16001
|
switch (parser->current.type) {
|
15692
16002
|
case PM_TOKEN_PARENTHESIS_LEFT: {
|
@@ -15695,31 +16005,37 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15695
16005
|
parser_lex(parser);
|
15696
16006
|
|
15697
16007
|
if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
|
15698
|
-
|
16008
|
+
block_parameters = pm_block_parameters_node_create(parser, NULL, &opening);
|
15699
16009
|
} else {
|
15700
|
-
|
16010
|
+
block_parameters = parse_block_parameters(parser, false, &opening, true);
|
15701
16011
|
}
|
15702
16012
|
|
15703
16013
|
accept1(parser, PM_TOKEN_NEWLINE);
|
15704
16014
|
expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN);
|
15705
16015
|
|
15706
|
-
pm_block_parameters_node_closing_set(
|
16016
|
+
pm_block_parameters_node_closing_set(block_parameters, &parser->previous);
|
15707
16017
|
break;
|
15708
16018
|
}
|
15709
16019
|
case PM_CASE_PARAMETER: {
|
15710
16020
|
parser->current_scope->explicit_params = true;
|
15711
16021
|
pm_accepts_block_stack_push(parser, false);
|
15712
16022
|
pm_token_t opening = not_provided(parser);
|
15713
|
-
|
16023
|
+
block_parameters = parse_block_parameters(parser, false, &opening, true);
|
15714
16024
|
pm_accepts_block_stack_pop(parser);
|
15715
16025
|
break;
|
15716
16026
|
}
|
15717
16027
|
default: {
|
15718
|
-
|
16028
|
+
block_parameters = NULL;
|
15719
16029
|
break;
|
15720
16030
|
}
|
15721
16031
|
}
|
15722
16032
|
|
16033
|
+
uint32_t locals_body_index = 0;
|
16034
|
+
|
16035
|
+
if (block_parameters) {
|
16036
|
+
locals_body_index = (uint32_t) parser->current_scope->locals.size;
|
16037
|
+
}
|
16038
|
+
|
15723
16039
|
pm_token_t opening;
|
15724
16040
|
pm_node_t *body = NULL;
|
15725
16041
|
parser->lambda_enclosure_nesting = previous_lambda_enclosure_nesting;
|
@@ -15743,22 +16059,30 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15743
16059
|
|
15744
16060
|
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
|
15745
16061
|
assert(body == NULL || PM_NODE_TYPE_P(body, PM_STATEMENTS_NODE));
|
15746
|
-
body = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) body);
|
16062
|
+
body = (pm_node_t *) parse_rescues_as_begin(parser, (pm_statements_node_t *) body, false);
|
15747
16063
|
}
|
15748
16064
|
|
15749
16065
|
expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_LAMBDA_TERM_END);
|
15750
16066
|
}
|
15751
16067
|
|
16068
|
+
pm_node_t *parameters = (pm_node_t *) block_parameters;
|
16069
|
+
uint8_t maximum = parser->current_scope->numbered_parameters;
|
16070
|
+
|
16071
|
+
if (parameters == NULL && (maximum > 0)) {
|
16072
|
+
parameters = (pm_node_t *) pm_numbered_parameters_node_create(parser, &(pm_location_t) { .start = operator.start, .end = parser->previous.end }, maximum);
|
16073
|
+
locals_body_index = maximum;
|
16074
|
+
}
|
16075
|
+
|
15752
16076
|
pm_constant_id_list_t locals = parser->current_scope->locals;
|
15753
16077
|
pm_parser_scope_pop(parser);
|
15754
16078
|
pm_accepts_block_stack_pop(parser);
|
15755
|
-
return (pm_node_t *) pm_lambda_node_create(parser, &locals, &operator, &opening, &parser->previous,
|
16079
|
+
return (pm_node_t *) pm_lambda_node_create(parser, &locals, locals_body_index, &operator, &opening, &parser->previous, parameters, body);
|
15756
16080
|
}
|
15757
16081
|
case PM_TOKEN_UPLUS: {
|
15758
16082
|
parser_lex(parser);
|
15759
16083
|
|
15760
16084
|
pm_token_t operator = parser->previous;
|
15761
|
-
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, PM_ERR_UNARY_RECEIVER_PLUS);
|
16085
|
+
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER_PLUS);
|
15762
16086
|
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "+@");
|
15763
16087
|
|
15764
16088
|
return (pm_node_t *) node;
|
@@ -15781,14 +16105,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
|
15781
16105
|
}
|
15782
16106
|
|
15783
16107
|
static inline pm_node_t *
|
15784
|
-
parse_assignment_value(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id) {
|
15785
|
-
pm_node_t *value = parse_value_expression(parser, binding_power, diag_id);
|
16108
|
+
parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) {
|
16109
|
+
pm_node_t *value = parse_value_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id);
|
15786
16110
|
|
15787
16111
|
// Contradicting binding powers, the right-hand-side value of rthe assignment allows the `rescue` modifier.
|
15788
16112
|
if (match1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) {
|
15789
16113
|
pm_token_t rescue = parser->current;
|
15790
16114
|
parser_lex(parser);
|
15791
|
-
pm_node_t *right = parse_expression(parser, binding_power, PM_ERR_RESCUE_MODIFIER_VALUE);
|
16115
|
+
pm_node_t *right = parse_expression(parser, binding_power, false, PM_ERR_RESCUE_MODIFIER_VALUE);
|
15792
16116
|
|
15793
16117
|
return (pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right);
|
15794
16118
|
}
|
@@ -15798,8 +16122,8 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t binding_power, pm
|
|
15798
16122
|
|
15799
16123
|
|
15800
16124
|
static inline pm_node_t *
|
15801
|
-
parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id) {
|
15802
|
-
pm_node_t *value = parse_starred_expression(parser, binding_power, diag_id);
|
16125
|
+
parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) {
|
16126
|
+
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_MATCH, diag_id);
|
15803
16127
|
|
15804
16128
|
bool is_single_value = true;
|
15805
16129
|
if (previous_binding_power == PM_BINDING_POWER_STATEMENT && (PM_NODE_TYPE_P(value, PM_SPLAT_NODE) || match1(parser, PM_TOKEN_COMMA))) {
|
@@ -15811,7 +16135,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding
|
|
15811
16135
|
value = (pm_node_t *) array;
|
15812
16136
|
|
15813
16137
|
while (accept1(parser, PM_TOKEN_COMMA)) {
|
15814
|
-
pm_node_t *element = parse_starred_expression(parser, binding_power, PM_ERR_ARRAY_ELEMENT);
|
16138
|
+
pm_node_t *element = parse_starred_expression(parser, binding_power, false, PM_ERR_ARRAY_ELEMENT);
|
15815
16139
|
pm_array_node_elements_append(array, element);
|
15816
16140
|
if (PM_NODE_TYPE_P(element, PM_MISSING_NODE)) break;
|
15817
16141
|
}
|
@@ -15821,7 +16145,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding
|
|
15821
16145
|
if (is_single_value && match1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) {
|
15822
16146
|
pm_token_t rescue = parser->current;
|
15823
16147
|
parser_lex(parser);
|
15824
|
-
pm_node_t *right = parse_expression(parser, binding_power, PM_ERR_RESCUE_MODIFIER_VALUE);
|
16148
|
+
pm_node_t *right = parse_expression(parser, binding_power, false, PM_ERR_RESCUE_MODIFIER_VALUE);
|
15825
16149
|
|
15826
16150
|
return (pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right);
|
15827
16151
|
}
|
@@ -15879,7 +16203,7 @@ parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *
|
|
15879
16203
|
pm_string_list_t named_captures = { 0 };
|
15880
16204
|
pm_node_t *result;
|
15881
16205
|
|
15882
|
-
if (pm_regexp_named_capture_group_names(pm_string_source(content), pm_string_length(content), &named_captures, parser->encoding_changed,
|
16206
|
+
if (pm_regexp_named_capture_group_names(pm_string_source(content), pm_string_length(content), &named_captures, parser->encoding_changed, parser->encoding) && (named_captures.length > 0)) {
|
15883
16207
|
// Since we should not create a MatchWriteNode when all capture names
|
15884
16208
|
// are invalid, creating a MatchWriteNode is delayed here.
|
15885
16209
|
pm_match_write_node_t *match = NULL;
|
@@ -15913,6 +16237,8 @@ parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *
|
|
15913
16237
|
if (memory == NULL) abort();
|
15914
16238
|
|
15915
16239
|
memcpy(memory, source, length);
|
16240
|
+
// This silences clang analyzer warning about leak of memory pointed by `memory`.
|
16241
|
+
// NOLINTNEXTLINE(clang-analyzer-*)
|
15916
16242
|
name = pm_parser_constant_id_owned(parser, (const uint8_t *) memory, length);
|
15917
16243
|
|
15918
16244
|
if (pm_token_is_numbered_parameter(source, source + length)) {
|
@@ -15960,7 +16286,7 @@ parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *
|
|
15960
16286
|
}
|
15961
16287
|
|
15962
16288
|
static inline pm_node_t *
|
15963
|
-
parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power) {
|
16289
|
+
parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call) {
|
15964
16290
|
pm_token_t token = parser->current;
|
15965
16291
|
|
15966
16292
|
switch (token.type) {
|
@@ -15979,7 +16305,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15979
16305
|
/* fallthrough */
|
15980
16306
|
case PM_CASE_WRITABLE: {
|
15981
16307
|
parser_lex(parser);
|
15982
|
-
pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
|
16308
|
+
pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) ? PM_BINDING_POWER_MULTI_ASSIGNMENT + 1 : binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
|
15983
16309
|
return parse_write(parser, node, &token, value);
|
15984
16310
|
}
|
15985
16311
|
case PM_SPLAT_NODE: {
|
@@ -15987,7 +16313,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
15987
16313
|
pm_multi_target_node_targets_append(parser, multi_target, node);
|
15988
16314
|
|
15989
16315
|
parser_lex(parser);
|
15990
|
-
pm_node_t *value = parse_assignment_values(parser, previous_binding_power,
|
16316
|
+
pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
|
15991
16317
|
return parse_write(parser, (pm_node_t *) multi_target, &token, value);
|
15992
16318
|
}
|
15993
16319
|
default:
|
@@ -16009,7 +16335,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16009
16335
|
case PM_GLOBAL_VARIABLE_READ_NODE: {
|
16010
16336
|
parser_lex(parser);
|
16011
16337
|
|
16012
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16338
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16013
16339
|
pm_node_t *result = (pm_node_t *) pm_global_variable_and_write_node_create(parser, node, &token, value);
|
16014
16340
|
|
16015
16341
|
pm_node_destroy(parser, node);
|
@@ -16018,7 +16344,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16018
16344
|
case PM_CLASS_VARIABLE_READ_NODE: {
|
16019
16345
|
parser_lex(parser);
|
16020
16346
|
|
16021
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16347
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16022
16348
|
pm_node_t *result = (pm_node_t *) pm_class_variable_and_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
|
16023
16349
|
|
16024
16350
|
pm_node_destroy(parser, node);
|
@@ -16027,13 +16353,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16027
16353
|
case PM_CONSTANT_PATH_NODE: {
|
16028
16354
|
parser_lex(parser);
|
16029
16355
|
|
16030
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16356
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16031
16357
|
return (pm_node_t *) pm_constant_path_and_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
|
16032
16358
|
}
|
16033
16359
|
case PM_CONSTANT_READ_NODE: {
|
16034
16360
|
parser_lex(parser);
|
16035
16361
|
|
16036
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16362
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16037
16363
|
pm_node_t *result = (pm_node_t *) pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
|
16038
16364
|
|
16039
16365
|
pm_node_destroy(parser, node);
|
@@ -16042,7 +16368,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16042
16368
|
case PM_INSTANCE_VARIABLE_READ_NODE: {
|
16043
16369
|
parser_lex(parser);
|
16044
16370
|
|
16045
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16371
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16046
16372
|
pm_node_t *result = (pm_node_t *) pm_instance_variable_and_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
|
16047
16373
|
|
16048
16374
|
pm_node_destroy(parser, node);
|
@@ -16052,7 +16378,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16052
16378
|
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
|
16053
16379
|
parser_lex(parser);
|
16054
16380
|
|
16055
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16381
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16056
16382
|
pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, node, &token, value, cast->name, cast->depth);
|
16057
16383
|
|
16058
16384
|
pm_node_destroy(parser, node);
|
@@ -16070,7 +16396,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16070
16396
|
pm_refute_numbered_parameter(parser, message_loc->start, message_loc->end);
|
16071
16397
|
|
16072
16398
|
pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end);
|
16073
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16399
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16074
16400
|
pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
|
16075
16401
|
|
16076
16402
|
pm_node_destroy(parser, (pm_node_t *) cast);
|
@@ -16081,7 +16407,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16081
16407
|
// this is an aref expression, and we can transform it into
|
16082
16408
|
// an aset expression.
|
16083
16409
|
if (pm_call_node_index_p(cast)) {
|
16084
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16410
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16085
16411
|
return (pm_node_t *) pm_index_and_write_node_create(parser, cast, &token, value);
|
16086
16412
|
}
|
16087
16413
|
|
@@ -16093,7 +16419,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16093
16419
|
}
|
16094
16420
|
|
16095
16421
|
parse_call_operator_write(parser, cast, &token);
|
16096
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16422
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
|
16097
16423
|
return (pm_node_t *) pm_call_and_write_node_create(parser, cast, &token, value);
|
16098
16424
|
}
|
16099
16425
|
case PM_MULTI_WRITE_NODE: {
|
@@ -16120,7 +16446,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16120
16446
|
case PM_GLOBAL_VARIABLE_READ_NODE: {
|
16121
16447
|
parser_lex(parser);
|
16122
16448
|
|
16123
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16449
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16124
16450
|
pm_node_t *result = (pm_node_t *) pm_global_variable_or_write_node_create(parser, node, &token, value);
|
16125
16451
|
|
16126
16452
|
pm_node_destroy(parser, node);
|
@@ -16129,7 +16455,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16129
16455
|
case PM_CLASS_VARIABLE_READ_NODE: {
|
16130
16456
|
parser_lex(parser);
|
16131
16457
|
|
16132
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16458
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16133
16459
|
pm_node_t *result = (pm_node_t *) pm_class_variable_or_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
|
16134
16460
|
|
16135
16461
|
pm_node_destroy(parser, node);
|
@@ -16138,13 +16464,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16138
16464
|
case PM_CONSTANT_PATH_NODE: {
|
16139
16465
|
parser_lex(parser);
|
16140
16466
|
|
16141
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16467
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16142
16468
|
return (pm_node_t *) pm_constant_path_or_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
|
16143
16469
|
}
|
16144
16470
|
case PM_CONSTANT_READ_NODE: {
|
16145
16471
|
parser_lex(parser);
|
16146
16472
|
|
16147
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16473
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16148
16474
|
pm_node_t *result = (pm_node_t *) pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
|
16149
16475
|
|
16150
16476
|
pm_node_destroy(parser, node);
|
@@ -16153,7 +16479,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16153
16479
|
case PM_INSTANCE_VARIABLE_READ_NODE: {
|
16154
16480
|
parser_lex(parser);
|
16155
16481
|
|
16156
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16482
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16157
16483
|
pm_node_t *result = (pm_node_t *) pm_instance_variable_or_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
|
16158
16484
|
|
16159
16485
|
pm_node_destroy(parser, node);
|
@@ -16163,7 +16489,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16163
16489
|
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
|
16164
16490
|
parser_lex(parser);
|
16165
16491
|
|
16166
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16492
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16167
16493
|
pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, node, &token, value, cast->name, cast->depth);
|
16168
16494
|
|
16169
16495
|
pm_node_destroy(parser, node);
|
@@ -16181,7 +16507,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16181
16507
|
pm_refute_numbered_parameter(parser, message_loc->start, message_loc->end);
|
16182
16508
|
|
16183
16509
|
pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end);
|
16184
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16510
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16185
16511
|
pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
|
16186
16512
|
|
16187
16513
|
pm_node_destroy(parser, (pm_node_t *) cast);
|
@@ -16192,7 +16518,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16192
16518
|
// this is an aref expression, and we can transform it into
|
16193
16519
|
// an aset expression.
|
16194
16520
|
if (pm_call_node_index_p(cast)) {
|
16195
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16521
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16196
16522
|
return (pm_node_t *) pm_index_or_write_node_create(parser, cast, &token, value);
|
16197
16523
|
}
|
16198
16524
|
|
@@ -16204,7 +16530,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16204
16530
|
}
|
16205
16531
|
|
16206
16532
|
parse_call_operator_write(parser, cast, &token);
|
16207
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16533
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
|
16208
16534
|
return (pm_node_t *) pm_call_or_write_node_create(parser, cast, &token, value);
|
16209
16535
|
}
|
16210
16536
|
case PM_MULTI_WRITE_NODE: {
|
@@ -16241,7 +16567,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16241
16567
|
case PM_GLOBAL_VARIABLE_READ_NODE: {
|
16242
16568
|
parser_lex(parser);
|
16243
16569
|
|
16244
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16570
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16245
16571
|
pm_node_t *result = (pm_node_t *) pm_global_variable_operator_write_node_create(parser, node, &token, value);
|
16246
16572
|
|
16247
16573
|
pm_node_destroy(parser, node);
|
@@ -16250,7 +16576,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16250
16576
|
case PM_CLASS_VARIABLE_READ_NODE: {
|
16251
16577
|
parser_lex(parser);
|
16252
16578
|
|
16253
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16579
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16254
16580
|
pm_node_t *result = (pm_node_t *) pm_class_variable_operator_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
|
16255
16581
|
|
16256
16582
|
pm_node_destroy(parser, node);
|
@@ -16259,13 +16585,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16259
16585
|
case PM_CONSTANT_PATH_NODE: {
|
16260
16586
|
parser_lex(parser);
|
16261
16587
|
|
16262
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16588
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16263
16589
|
return (pm_node_t *) pm_constant_path_operator_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
|
16264
16590
|
}
|
16265
16591
|
case PM_CONSTANT_READ_NODE: {
|
16266
16592
|
parser_lex(parser);
|
16267
16593
|
|
16268
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16594
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16269
16595
|
pm_node_t *result = (pm_node_t *) pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
|
16270
16596
|
|
16271
16597
|
pm_node_destroy(parser, node);
|
@@ -16274,7 +16600,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16274
16600
|
case PM_INSTANCE_VARIABLE_READ_NODE: {
|
16275
16601
|
parser_lex(parser);
|
16276
16602
|
|
16277
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16603
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16278
16604
|
pm_node_t *result = (pm_node_t *) pm_instance_variable_operator_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
|
16279
16605
|
|
16280
16606
|
pm_node_destroy(parser, node);
|
@@ -16284,7 +16610,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16284
16610
|
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
|
16285
16611
|
parser_lex(parser);
|
16286
16612
|
|
16287
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16613
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16288
16614
|
pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, node, &token, value, cast->name, cast->depth);
|
16289
16615
|
|
16290
16616
|
pm_node_destroy(parser, node);
|
@@ -16302,7 +16628,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16302
16628
|
pm_refute_numbered_parameter(parser, message_loc->start, message_loc->end);
|
16303
16629
|
|
16304
16630
|
pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end);
|
16305
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16631
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16306
16632
|
pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
|
16307
16633
|
|
16308
16634
|
pm_node_destroy(parser, (pm_node_t *) cast);
|
@@ -16313,7 +16639,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16313
16639
|
// this is an aref expression, and we can transform it into
|
16314
16640
|
// an aset expression.
|
16315
16641
|
if (pm_call_node_index_p(cast)) {
|
16316
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16642
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16317
16643
|
return (pm_node_t *) pm_index_operator_write_node_create(parser, cast, &token, value);
|
16318
16644
|
}
|
16319
16645
|
|
@@ -16325,7 +16651,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16325
16651
|
}
|
16326
16652
|
|
16327
16653
|
parse_call_operator_write(parser, cast, &token);
|
16328
|
-
pm_node_t *value = parse_assignment_value(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16654
|
+
pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16329
16655
|
return (pm_node_t *) pm_call_operator_write_node_create(parser, cast, &token, value);
|
16330
16656
|
}
|
16331
16657
|
case PM_MULTI_WRITE_NODE: {
|
@@ -16347,14 +16673,14 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16347
16673
|
case PM_TOKEN_KEYWORD_AND: {
|
16348
16674
|
parser_lex(parser);
|
16349
16675
|
|
16350
|
-
pm_node_t *right = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16676
|
+
pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_AND, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16351
16677
|
return (pm_node_t *) pm_and_node_create(parser, node, &token, right);
|
16352
16678
|
}
|
16353
16679
|
case PM_TOKEN_KEYWORD_OR:
|
16354
16680
|
case PM_TOKEN_PIPE_PIPE: {
|
16355
16681
|
parser_lex(parser);
|
16356
16682
|
|
16357
|
-
pm_node_t *right = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16683
|
+
pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_OR, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16358
16684
|
return (pm_node_t *) pm_or_node_create(parser, node, &token, right);
|
16359
16685
|
}
|
16360
16686
|
case PM_TOKEN_EQUAL_TILDE: {
|
@@ -16366,7 +16692,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16366
16692
|
//
|
16367
16693
|
// In this case, `foo` should be a method call and not a local yet.
|
16368
16694
|
parser_lex(parser);
|
16369
|
-
pm_node_t *argument = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16695
|
+
pm_node_t *argument = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16370
16696
|
|
16371
16697
|
// By default, we're going to create a call node and then return it.
|
16372
16698
|
pm_call_node_t *call = pm_call_node_binary_create(parser, node, &token, argument);
|
@@ -16451,7 +16777,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16451
16777
|
case PM_TOKEN_STAR_STAR: {
|
16452
16778
|
parser_lex(parser);
|
16453
16779
|
|
16454
|
-
pm_node_t *argument = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16780
|
+
pm_node_t *argument = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16455
16781
|
return (pm_node_t *) pm_call_node_binary_create(parser, node, &token, argument);
|
16456
16782
|
}
|
16457
16783
|
case PM_TOKEN_AMPERSAND_DOT:
|
@@ -16462,7 +16788,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16462
16788
|
|
16463
16789
|
// This if statement handles the foo.() syntax.
|
16464
16790
|
if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
|
16465
|
-
parse_arguments_list(parser, &arguments, true);
|
16791
|
+
parse_arguments_list(parser, &arguments, true, false);
|
16466
16792
|
return (pm_node_t *) pm_call_node_shorthand_create(parser, node, &operator, &arguments);
|
16467
16793
|
}
|
16468
16794
|
|
@@ -16484,7 +16810,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16484
16810
|
}
|
16485
16811
|
}
|
16486
16812
|
|
16487
|
-
parse_arguments_list(parser, &arguments, true);
|
16813
|
+
parse_arguments_list(parser, &arguments, true, accepts_command_call);
|
16488
16814
|
pm_call_node_t *call = pm_call_node_call_create(parser, node, &operator, &message, &arguments);
|
16489
16815
|
|
16490
16816
|
if (
|
@@ -16504,7 +16830,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16504
16830
|
|
16505
16831
|
pm_node_t *right = NULL;
|
16506
16832
|
if (token_begins_expression_p(parser->current.type)) {
|
16507
|
-
right = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16833
|
+
right = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
16508
16834
|
}
|
16509
16835
|
|
16510
16836
|
return (pm_node_t *) pm_range_node_create(parser, node, &token, right);
|
@@ -16513,14 +16839,14 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16513
16839
|
pm_token_t keyword = parser->current;
|
16514
16840
|
parser_lex(parser);
|
16515
16841
|
|
16516
|
-
pm_node_t *predicate = parse_value_expression(parser, binding_power, PM_ERR_CONDITIONAL_IF_PREDICATE);
|
16842
|
+
pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_IF_PREDICATE);
|
16517
16843
|
return (pm_node_t *) pm_if_node_modifier_create(parser, node, &keyword, predicate);
|
16518
16844
|
}
|
16519
16845
|
case PM_TOKEN_KEYWORD_UNLESS_MODIFIER: {
|
16520
16846
|
pm_token_t keyword = parser->current;
|
16521
16847
|
parser_lex(parser);
|
16522
16848
|
|
16523
|
-
pm_node_t *predicate = parse_value_expression(parser, binding_power, PM_ERR_CONDITIONAL_UNLESS_PREDICATE);
|
16849
|
+
pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_UNLESS_PREDICATE);
|
16524
16850
|
return (pm_node_t *) pm_unless_node_modifier_create(parser, node, &keyword, predicate);
|
16525
16851
|
}
|
16526
16852
|
case PM_TOKEN_KEYWORD_UNTIL_MODIFIER: {
|
@@ -16528,7 +16854,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16528
16854
|
pm_statements_node_t *statements = pm_statements_node_create(parser);
|
16529
16855
|
pm_statements_node_body_append(statements, node);
|
16530
16856
|
|
16531
|
-
pm_node_t *predicate = parse_value_expression(parser, binding_power, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
|
16857
|
+
pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
|
16532
16858
|
return (pm_node_t *) pm_until_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0);
|
16533
16859
|
}
|
16534
16860
|
case PM_TOKEN_KEYWORD_WHILE_MODIFIER: {
|
@@ -16536,13 +16862,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16536
16862
|
pm_statements_node_t *statements = pm_statements_node_create(parser);
|
16537
16863
|
pm_statements_node_body_append(statements, node);
|
16538
16864
|
|
16539
|
-
pm_node_t *predicate = parse_value_expression(parser, binding_power, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
|
16865
|
+
pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
|
16540
16866
|
return (pm_node_t *) pm_while_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0);
|
16541
16867
|
}
|
16542
16868
|
case PM_TOKEN_QUESTION_MARK: {
|
16543
16869
|
pm_token_t qmark = parser->current;
|
16544
16870
|
parser_lex(parser);
|
16545
|
-
pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_TERNARY_EXPRESSION_TRUE);
|
16871
|
+
pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_TERNARY_EXPRESSION_TRUE);
|
16546
16872
|
|
16547
16873
|
if (parser->recovering) {
|
16548
16874
|
// If parsing the true expression of this ternary resulted in a syntax
|
@@ -16561,7 +16887,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16561
16887
|
expect1(parser, PM_TOKEN_COLON, PM_ERR_TERNARY_COLON);
|
16562
16888
|
|
16563
16889
|
pm_token_t colon = parser->previous;
|
16564
|
-
pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, PM_ERR_TERNARY_EXPRESSION_FALSE);
|
16890
|
+
pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_TERNARY_EXPRESSION_FALSE);
|
16565
16891
|
|
16566
16892
|
return (pm_node_t *) pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression);
|
16567
16893
|
}
|
@@ -16587,7 +16913,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16587
16913
|
pm_token_t message = parser->previous;
|
16588
16914
|
pm_arguments_t arguments = { 0 };
|
16589
16915
|
|
16590
|
-
parse_arguments_list(parser, &arguments, true);
|
16916
|
+
parse_arguments_list(parser, &arguments, true, accepts_command_call);
|
16591
16917
|
path = (pm_node_t *) pm_call_node_call_create(parser, node, &delimiter, &message, &arguments);
|
16592
16918
|
} else {
|
16593
16919
|
// Otherwise, this is a constant path. That would look like Foo::Bar.
|
@@ -16612,7 +16938,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16612
16938
|
// If we have an identifier following a '::' operator, then it is for
|
16613
16939
|
// sure a method call.
|
16614
16940
|
pm_arguments_t arguments = { 0 };
|
16615
|
-
parse_arguments_list(parser, &arguments, true);
|
16941
|
+
parse_arguments_list(parser, &arguments, true, accepts_command_call);
|
16616
16942
|
pm_call_node_t *call = pm_call_node_call_create(parser, node, &delimiter, &message, &arguments);
|
16617
16943
|
|
16618
16944
|
// If this is followed by a comma then it is a multiple assignment.
|
@@ -16626,7 +16952,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16626
16952
|
// If we have a parenthesis following a '::' operator, then it is the
|
16627
16953
|
// method call shorthand. That would look like Foo::(bar).
|
16628
16954
|
pm_arguments_t arguments = { 0 };
|
16629
|
-
parse_arguments_list(parser, &arguments, true);
|
16955
|
+
parse_arguments_list(parser, &arguments, true, false);
|
16630
16956
|
|
16631
16957
|
return (pm_node_t *) pm_call_node_shorthand_create(parser, node, &delimiter, &arguments);
|
16632
16958
|
}
|
@@ -16640,7 +16966,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16640
16966
|
case PM_TOKEN_KEYWORD_RESCUE_MODIFIER: {
|
16641
16967
|
parser_lex(parser);
|
16642
16968
|
accept1(parser, PM_TOKEN_NEWLINE);
|
16643
|
-
pm_node_t *value = parse_expression(parser, binding_power, PM_ERR_RESCUE_MODIFIER_VALUE);
|
16969
|
+
pm_node_t *value = parse_expression(parser, binding_power, true, PM_ERR_RESCUE_MODIFIER_VALUE);
|
16644
16970
|
|
16645
16971
|
return (pm_node_t *) pm_rescue_modifier_node_create(parser, node, &token, value);
|
16646
16972
|
}
|
@@ -16736,16 +17062,39 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
|
16736
17062
|
* determine if they need to perform additional cleanup.
|
16737
17063
|
*/
|
16738
17064
|
static pm_node_t *
|
16739
|
-
parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id) {
|
17065
|
+
parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) {
|
16740
17066
|
pm_token_t recovery = parser->previous;
|
16741
|
-
pm_node_t *node = parse_expression_prefix(parser, binding_power);
|
17067
|
+
pm_node_t *node = parse_expression_prefix(parser, binding_power, accepts_command_call);
|
16742
17068
|
|
16743
|
-
|
16744
|
-
|
16745
|
-
|
16746
|
-
|
16747
|
-
|
16748
|
-
|
17069
|
+
switch (PM_NODE_TYPE(node)) {
|
17070
|
+
case PM_MISSING_NODE:
|
17071
|
+
// If we found a syntax error, then the type of node returned by
|
17072
|
+
// parse_expression_prefix is going to be a missing node. In that
|
17073
|
+
// case we need to add the error message to the parser's error list.
|
17074
|
+
pm_parser_err(parser, recovery.end, recovery.end, diag_id);
|
17075
|
+
return node;
|
17076
|
+
case PM_PRE_EXECUTION_NODE:
|
17077
|
+
case PM_POST_EXECUTION_NODE:
|
17078
|
+
case PM_ALIAS_GLOBAL_VARIABLE_NODE:
|
17079
|
+
case PM_ALIAS_METHOD_NODE:
|
17080
|
+
case PM_UNDEF_NODE:
|
17081
|
+
// These expressions are statements, and cannot be followed by
|
17082
|
+
// operators (except modifiers).
|
17083
|
+
if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER_RESCUE) {
|
17084
|
+
return node;
|
17085
|
+
}
|
17086
|
+
break;
|
17087
|
+
case PM_RANGE_NODE:
|
17088
|
+
// Range operators are non-associative, so that it does not
|
17089
|
+
// associate with other range operators (i.e. `..1..` should be
|
17090
|
+
// rejected.) For this reason, we check such a case for unary ranges
|
17091
|
+
// here, and if so, it returns the node immediately,
|
17092
|
+
if ((((pm_range_node_t *) node)->left == NULL) && pm_binding_powers[parser->current.type].left >= PM_BINDING_POWER_RANGE) {
|
17093
|
+
return node;
|
17094
|
+
}
|
17095
|
+
break;
|
17096
|
+
default:
|
17097
|
+
break;
|
16749
17098
|
}
|
16750
17099
|
|
16751
17100
|
// Otherwise we'll look and see if the next token can be parsed as an infix
|
@@ -16756,12 +17105,68 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagn
|
|
16756
17105
|
binding_power <= current_binding_powers.left &&
|
16757
17106
|
current_binding_powers.binary
|
16758
17107
|
) {
|
16759
|
-
node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right);
|
16760
|
-
if (
|
16761
|
-
|
16762
|
-
|
16763
|
-
|
16764
|
-
|
17108
|
+
node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call);
|
17109
|
+
if (current_binding_powers.nonassoc) {
|
17110
|
+
bool endless_range_p = PM_NODE_TYPE_P(node, PM_RANGE_NODE) && ((pm_range_node_t *) node)->right == NULL;
|
17111
|
+
pm_binding_power_t left = endless_range_p ? PM_BINDING_POWER_TERM : current_binding_powers.left;
|
17112
|
+
if (
|
17113
|
+
left <= pm_binding_powers[parser->current.type].left ||
|
17114
|
+
// Exceptionally to operator precedences, '1.. & 2' is rejected.
|
17115
|
+
// '1.. || 2' is also an exception, but it is handled by the lexer.
|
17116
|
+
// (Here, parser->current is PM_TOKEN_PIPE, not PM_TOKEN_PIPE_PIPE).
|
17117
|
+
(endless_range_p && match1(parser, PM_TOKEN_AMPERSAND))
|
17118
|
+
) {
|
17119
|
+
break;
|
17120
|
+
}
|
17121
|
+
}
|
17122
|
+
if (accepts_command_call) {
|
17123
|
+
// A command-style method call is only accepted on method chains.
|
17124
|
+
// Thus, we check whether the parsed node can continue method chains.
|
17125
|
+
// The method chain can continue if the parsed node is one of the following five kinds:
|
17126
|
+
// (1) index access: foo[1]
|
17127
|
+
// (2) attribute access: foo.bar
|
17128
|
+
// (3) method call with parenthesis: foo.bar(1)
|
17129
|
+
// (4) method call with a block: foo.bar do end
|
17130
|
+
// (5) constant path: foo::Bar
|
17131
|
+
switch (node->type) {
|
17132
|
+
case PM_CALL_NODE: {
|
17133
|
+
pm_call_node_t *cast = (pm_call_node_t *)node;
|
17134
|
+
if (
|
17135
|
+
// (1) foo[1]
|
17136
|
+
!(
|
17137
|
+
cast->call_operator_loc.start == NULL &&
|
17138
|
+
cast->message_loc.start != NULL &&
|
17139
|
+
cast->message_loc.start[0] == '[' &&
|
17140
|
+
cast->message_loc.end[-1] == ']'
|
17141
|
+
) &&
|
17142
|
+
// (2) foo.bar
|
17143
|
+
!(
|
17144
|
+
cast->call_operator_loc.start != NULL &&
|
17145
|
+
cast->arguments == NULL &&
|
17146
|
+
cast->block == NULL &&
|
17147
|
+
cast->opening_loc.start == NULL
|
17148
|
+
) &&
|
17149
|
+
// (3) foo.bar(1)
|
17150
|
+
!(
|
17151
|
+
cast->call_operator_loc.start != NULL &&
|
17152
|
+
cast->opening_loc.start != NULL
|
17153
|
+
) &&
|
17154
|
+
// (4) foo.bar do end
|
17155
|
+
!(
|
17156
|
+
cast->block != NULL && PM_NODE_TYPE_P(cast->block, PM_BLOCK_NODE)
|
17157
|
+
)
|
17158
|
+
) {
|
17159
|
+
accepts_command_call = false;
|
17160
|
+
}
|
17161
|
+
break;
|
17162
|
+
}
|
17163
|
+
// (5) foo::Bar
|
17164
|
+
case PM_CONSTANT_PATH_NODE:
|
17165
|
+
break;
|
17166
|
+
default:
|
17167
|
+
accepts_command_call = false;
|
17168
|
+
break;
|
17169
|
+
}
|
16765
17170
|
}
|
16766
17171
|
}
|
16767
17172
|
|
@@ -16825,9 +17230,8 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
|
|
16825
17230
|
.error_list = { 0 },
|
16826
17231
|
.current_scope = NULL,
|
16827
17232
|
.current_context = NULL,
|
16828
|
-
.encoding =
|
17233
|
+
.encoding = PM_ENCODING_UTF_8_ENTRY,
|
16829
17234
|
.encoding_changed_callback = NULL,
|
16830
|
-
.encoding_decode_callback = NULL,
|
16831
17235
|
.encoding_comment_start = source,
|
16832
17236
|
.lex_callback = NULL,
|
16833
17237
|
.filepath_string = { 0 },
|
@@ -16836,11 +17240,13 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
|
|
16836
17240
|
.integer_base = 0,
|
16837
17241
|
.current_string = PM_STRING_EMPTY,
|
16838
17242
|
.start_line = 1,
|
17243
|
+
.explicit_encoding = NULL,
|
16839
17244
|
.command_start = true,
|
16840
17245
|
.recovering = false,
|
16841
17246
|
.encoding_changed = false,
|
16842
17247
|
.pattern_matching_newlines = false,
|
16843
17248
|
.in_keyword_arg = false,
|
17249
|
+
.current_param_name = 0,
|
16844
17250
|
.semantic_token_seen = false,
|
16845
17251
|
.frozen_string_literal = false,
|
16846
17252
|
.suppress_warnings = false
|
@@ -16875,9 +17281,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
|
|
16875
17281
|
parser->filepath_string = options->filepath;
|
16876
17282
|
|
16877
17283
|
// line option
|
16878
|
-
|
16879
|
-
parser->start_line = options->line;
|
16880
|
-
}
|
17284
|
+
parser->start_line = options->line;
|
16881
17285
|
|
16882
17286
|
// encoding option
|
16883
17287
|
size_t encoding_length = pm_string_length(&options->encoding);
|
@@ -16943,18 +17347,6 @@ pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_ch
|
|
16943
17347
|
parser->encoding_changed_callback = callback;
|
16944
17348
|
}
|
16945
17349
|
|
16946
|
-
/**
|
16947
|
-
* Register a callback that will be called when prism encounters a magic comment
|
16948
|
-
* with an encoding referenced that it doesn't understand. The callback should
|
16949
|
-
* return NULL if it also doesn't understand the encoding or it should return a
|
16950
|
-
* pointer to a pm_encoding_t struct that contains the functions necessary to
|
16951
|
-
* parse identifiers.
|
16952
|
-
*/
|
16953
|
-
PRISM_EXPORTED_FUNCTION void
|
16954
|
-
pm_parser_register_encoding_decode_callback(pm_parser_t *parser, pm_encoding_decode_callback_t callback) {
|
16955
|
-
parser->encoding_decode_callback = callback;
|
16956
|
-
}
|
16957
|
-
|
16958
17350
|
/**
|
16959
17351
|
* Free all of the memory associated with the comment list.
|
16960
17352
|
*/
|
@@ -17046,7 +17438,7 @@ pm_serialize(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) {
|
|
17046
17438
|
PRISM_EXPORTED_FUNCTION void
|
17047
17439
|
pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data) {
|
17048
17440
|
pm_options_t options = { 0 };
|
17049
|
-
|
17441
|
+
pm_options_read(&options, data);
|
17050
17442
|
|
17051
17443
|
pm_parser_t parser;
|
17052
17444
|
pm_parser_init(&parser, source, size, &options);
|
@@ -17068,15 +17460,15 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons
|
|
17068
17460
|
PRISM_EXPORTED_FUNCTION void
|
17069
17461
|
pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data) {
|
17070
17462
|
pm_options_t options = { 0 };
|
17071
|
-
|
17463
|
+
pm_options_read(&options, data);
|
17072
17464
|
|
17073
17465
|
pm_parser_t parser;
|
17074
17466
|
pm_parser_init(&parser, source, size, &options);
|
17075
17467
|
|
17076
17468
|
pm_node_t *node = pm_parse(&parser);
|
17077
17469
|
pm_serialize_header(buffer);
|
17078
|
-
pm_serialize_encoding(
|
17079
|
-
|
17470
|
+
pm_serialize_encoding(parser.encoding, buffer);
|
17471
|
+
pm_buffer_append_varsint(buffer, parser.start_line);
|
17080
17472
|
pm_serialize_comment_list(&parser, &parser.comment_list, buffer);
|
17081
17473
|
|
17082
17474
|
pm_node_destroy(&parser, node);
|