summaryrefslogtreecommitdiff
path: root/prism
diff options
context:
space:
mode:
authorTSUYUSATO Kitsune <make.just.on@gmail.com>2023-12-11 14:10:57 +0900
committergit <svn-admin@ruby-lang.org>2023-12-11 13:34:48 +0000
commita860e3605c53e708d3cb06e2080ff73b58de4b22 (patch)
tree8ac3990fe9426a295afcec47829b64879e064515 /prism
parent1ab91b12fa5f7e98bba2e59e2f40b57004d9acf1 (diff)
[ruby/prism] Fix to parse a (endless-)range with binary operators
Fix https://github.com/ruby/prism/pull/2022 Fix https://github.com/ruby/prism/pull/2030 https://github.com/ruby/prism/commit/b78d8b6525
Diffstat (limited to 'prism')
-rw-r--r--prism/prism.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/prism/prism.c b/prism/prism.c
index ca9430f6ca..9ca542ba30 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -10128,7 +10128,7 @@ typedef struct {
#define BINDING_POWER_ASSIGNMENT { PM_BINDING_POWER_UNARY, PM_BINDING_POWER_ASSIGNMENT, true, false }
#define LEFT_ASSOCIATIVE(precedence) { precedence, precedence + 1, true, false }
#define RIGHT_ASSOCIATIVE(precedence) { precedence, precedence, true, false }
-#define NON_ASSOCIATIVE(precedence) { precedence + 1, precedence + 1, true, true }
+#define NON_ASSOCIATIVE(precedence) { precedence, precedence + 1, true, true }
#define RIGHT_ASSOCIATIVE_UNARY(precedence) { precedence, precedence, false, false }
pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = {
@@ -16967,11 +16967,18 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
current_binding_powers.binary
) {
node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call);
- if (
- current_binding_powers.nonassoc &&
- current_binding_powers.right <= pm_binding_powers[parser->current.type].left
- ) {
- break;
+ if (current_binding_powers.nonassoc) {
+ bool endless_range_p = PM_NODE_TYPE_P(node, PM_RANGE_NODE) && ((pm_range_node_t *) node)->right == NULL;
+ pm_binding_power_t left = endless_range_p ? PM_BINDING_POWER_TERM : current_binding_powers.left;
+ if (
+ left <= pm_binding_powers[parser->current.type].left ||
+ // Exceptionally to operator precedences, '1.. & 2' is rejected.
+ // '1.. || 2' is also an exception, but it is handled by the lexer.
+ // (Here, parser->current is PM_TOKEN_PIPE, not PM_TOKEN_PIPE_PIPE).
+ (endless_range_p && match1(parser, PM_TOKEN_AMPERSAND))
+ ) {
+ break;
+ }
}
if (accepts_command_call) {
// A command-style method call is only accepted on method chains.