[ruby/prism] Fix associativity of binary range with begin-less range
Fix https://github.com/ruby/prism/pull/1828 https://github.com/ruby/prism/commit/22c0640e48
This commit is contained in:
parent
2aefbbaab9
commit
8794836bf2
@ -10202,6 +10202,8 @@ pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = {
|
||||
// .. ...
|
||||
[PM_TOKEN_DOT_DOT] = NON_ASSOCIATIVE(PM_BINDING_POWER_RANGE),
|
||||
[PM_TOKEN_DOT_DOT_DOT] = NON_ASSOCIATIVE(PM_BINDING_POWER_RANGE),
|
||||
[PM_TOKEN_UDOT_DOT] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_LOGICAL_OR),
|
||||
[PM_TOKEN_UDOT_DOT_DOT] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_LOGICAL_OR),
|
||||
|
||||
// ||
|
||||
[PM_TOKEN_PIPE_PIPE] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_LOGICAL_OR),
|
||||
@ -13956,7 +13958,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) {
|
||||
pm_token_t operator = parser->current;
|
||||
parser_lex(parser);
|
||||
|
||||
pm_node_t *right = parse_expression(parser, binding_power, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
||||
pm_node_t *right = parse_expression(parser, pm_binding_powers[operator.type].left, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
|
||||
return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
|
||||
}
|
||||
case PM_TOKEN_FLOAT:
|
||||
@ -16766,6 +16768,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
||||
static pm_node_t *
|
||||
parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagnostic_id_t diag_id) {
|
||||
pm_token_t recovery = parser->previous;
|
||||
bool is_udot = parser->current.type == PM_TOKEN_UDOT_DOT || parser->current.type == PM_TOKEN_UDOT_DOT_DOT;
|
||||
pm_node_t *node = parse_expression_prefix(parser, binding_power);
|
||||
|
||||
switch (PM_NODE_TYPE(node)) {
|
||||
@ -16789,6 +16792,14 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, pm_diagn
|
||||
break;
|
||||
}
|
||||
|
||||
// Range operators are non-associative, so that it does not associate with
|
||||
// other range operators (i.e. `..1..` should be rejected.)
|
||||
// For this reason, we check such a case for unary ranges here, and if so,
|
||||
// it returns the node immediately,
|
||||
if (is_udot && pm_binding_powers[parser->current.type].left >= PM_BINDING_POWER_RANGE) {
|
||||
return node;
|
||||
}
|
||||
|
||||
// Otherwise we'll look and see if the next token can be parsed as an infix
|
||||
// operator. If it can, then we'll parse it using parse_expression_infix.
|
||||
pm_binding_powers_t current_binding_powers;
|
||||
|
@ -1770,6 +1770,21 @@ module Prism
|
||||
]
|
||||
end
|
||||
|
||||
def test_binary_range_with_left_unary_range
|
||||
source = <<~RUBY
|
||||
..1..
|
||||
...1..
|
||||
RUBY
|
||||
message1 = 'Expected a newline or semicolon after the statement'
|
||||
message2 = 'Cannot parse the expression'
|
||||
assert_errors expression(source), source, [
|
||||
[message1, 3..3],
|
||||
[message2, 3..3],
|
||||
[message1, 10..10],
|
||||
[message2, 10..10],
|
||||
]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assert_errors(expected, source, errors, compare_ripper: RUBY_ENGINE == "ruby")
|
||||
|
@ -15,3 +15,5 @@ foo[...2]
|
||||
{ foo: ..bar }
|
||||
|
||||
(1..)
|
||||
|
||||
1 .. ..1
|
||||
|
@ -1,8 +1,8 @@
|
||||
@ ProgramNode (location: (1,0)-(17,5))
|
||||
@ ProgramNode (location: (1,0)-(19,8))
|
||||
├── locals: []
|
||||
└── statements:
|
||||
@ StatementsNode (location: (1,0)-(17,5))
|
||||
└── body: (length: 9)
|
||||
@ StatementsNode (location: (1,0)-(19,8))
|
||||
└── body: (length: 10)
|
||||
├── @ ParenthesesNode (location: (1,0)-(1,6))
|
||||
│ ├── body:
|
||||
│ │ @ StatementsNode (location: (1,1)-(1,5))
|
||||
@ -146,16 +146,30 @@
|
||||
│ │ │ └── flags: ∅
|
||||
│ │ └── operator_loc: ∅
|
||||
│ └── closing_loc: (15,13)-(15,14) = "}"
|
||||
└── @ ParenthesesNode (location: (17,0)-(17,5))
|
||||
├── body:
|
||||
│ @ StatementsNode (location: (17,1)-(17,4))
|
||||
│ └── body: (length: 1)
|
||||
│ └── @ RangeNode (location: (17,1)-(17,4))
|
||||
│ ├── left:
|
||||
│ │ @ IntegerNode (location: (17,1)-(17,2))
|
||||
│ │ └── flags: decimal
|
||||
│ ├── right: ∅
|
||||
│ ├── operator_loc: (17,2)-(17,4) = ".."
|
||||
│ └── flags: ∅
|
||||
├── opening_loc: (17,0)-(17,1) = "("
|
||||
└── closing_loc: (17,4)-(17,5) = ")"
|
||||
├── @ ParenthesesNode (location: (17,0)-(17,5))
|
||||
│ ├── body:
|
||||
│ │ @ StatementsNode (location: (17,1)-(17,4))
|
||||
│ │ └── body: (length: 1)
|
||||
│ │ └── @ RangeNode (location: (17,1)-(17,4))
|
||||
│ │ ├── left:
|
||||
│ │ │ @ IntegerNode (location: (17,1)-(17,2))
|
||||
│ │ │ └── flags: decimal
|
||||
│ │ ├── right: ∅
|
||||
│ │ ├── operator_loc: (17,2)-(17,4) = ".."
|
||||
│ │ └── flags: ∅
|
||||
│ ├── opening_loc: (17,0)-(17,1) = "("
|
||||
│ └── closing_loc: (17,4)-(17,5) = ")"
|
||||
└── @ RangeNode (location: (19,0)-(19,8))
|
||||
├── left:
|
||||
│ @ IntegerNode (location: (19,0)-(19,1))
|
||||
│ └── flags: decimal
|
||||
├── right:
|
||||
│ @ RangeNode (location: (19,5)-(19,8))
|
||||
│ ├── left: ∅
|
||||
│ ├── right:
|
||||
│ │ @ IntegerNode (location: (19,7)-(19,8))
|
||||
│ │ └── flags: decimal
|
||||
│ ├── operator_loc: (19,5)-(19,7) = ".."
|
||||
│ └── flags: ∅
|
||||
├── operator_loc: (19,2)-(19,4) = ".."
|
||||
└── flags: ∅
|
||||
|
Loading…
x
Reference in New Issue
Block a user