diff options
| author | TSUYUSATO Kitsune <make.just.on@gmail.com> | 2023-12-11 14:10:57 +0900 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2023-12-11 13:34:48 +0000 |
| commit | a860e3605c53e708d3cb06e2080ff73b58de4b22 (patch) | |
| tree | 8ac3990fe9426a295afcec47829b64879e064515 | |
| parent | 1ab91b12fa5f7e98bba2e59e2f40b57004d9acf1 (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
| -rw-r--r-- | prism/prism.c | 19 | ||||
| -rw-r--r-- | test/prism/errors_test.rb | 17 | ||||
| -rw-r--r-- | test/prism/fixtures/ranges.txt | 30 | ||||
| -rw-r--r-- | test/prism/snapshots/ranges.txt | 337 |
4 files changed, 386 insertions, 17 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. diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index b0e2554338..7744bd8b88 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -1971,6 +1971,23 @@ module Prism end end + def test_range_and_bin_op + sources = <<~RUBY.lines + 1..2..3 + 1..2.. + 1.. || 2 + 1.. & 2 + 1.. * 2 + 1.. / 2 + 1.. % 2 + 1.. ** 2 + RUBY + sources.each do |source| + assert_nil Ripper.sexp_raw(source) + assert_false(Prism.parse(source).success?) + end + end + def test_constant_assignment_in_method source = 'def foo();A=1;end' assert_errors expression(source), source, [ diff --git a/test/prism/fixtures/ranges.txt b/test/prism/fixtures/ranges.txt index c9bfe50399..e2e4136ae9 100644 --- a/test/prism/fixtures/ranges.txt +++ b/test/prism/fixtures/ranges.txt @@ -17,3 +17,33 @@ foo[...2] (1..) 1 .. ..1 + +1.. && 2 + +1.. == 2 + +1.. != 2 + +1.. === 2 + +1.. <=> 2 + +1.. =~ 2 + +1.. !~ 2 + +1.. < 2 + +1.. > 2 + +1.. <= 2 + +1.. >= 2 + +1.. << 2 + +1.. >> 2 + +1.. + 2 + +1.. - 2 diff --git a/test/prism/snapshots/ranges.txt b/test/prism/snapshots/ranges.txt index 471efc49a7..c9dbf26022 100644 --- a/test/prism/snapshots/ranges.txt +++ b/test/prism/snapshots/ranges.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(19,8)) +@ ProgramNode (location: (1,0)-(49,7)) ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(19,8)) - └── body: (length: 10) + @ StatementsNode (location: (1,0)-(49,7)) + └── body: (length: 25) ├── @ ParenthesesNode (location: (1,0)-(1,6)) │ ├── body: │ │ @ StatementsNode (location: (1,1)-(1,5)) @@ -161,17 +161,332 @@ │ │ └── operator_loc: (17,2)-(17,4) = ".." │ ├── opening_loc: (17,0)-(17,1) = "(" │ └── closing_loc: (17,4)-(17,5) = ")" - └── @ RangeNode (location: (19,0)-(19,8)) + ├── @ RangeNode (location: (19,0)-(19,8)) + │ ├── flags: ∅ + │ ├── left: + │ │ @ IntegerNode (location: (19,0)-(19,1)) + │ │ └── flags: decimal + │ ├── right: + │ │ @ RangeNode (location: (19,5)-(19,8)) + │ │ ├── flags: ∅ + │ │ ├── left: ∅ + │ │ ├── right: + │ │ │ @ IntegerNode (location: (19,7)-(19,8)) + │ │ │ └── flags: decimal + │ │ └── operator_loc: (19,5)-(19,7) = ".." + │ └── operator_loc: (19,2)-(19,4) = ".." + ├── @ AndNode (location: (21,0)-(21,8)) + │ ├── left: + │ │ @ RangeNode (location: (21,0)-(21,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (21,0)-(21,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (21,1)-(21,3) = ".." + │ ├── right: + │ │ @ IntegerNode (location: (21,7)-(21,8)) + │ │ └── flags: decimal + │ └── operator_loc: (21,4)-(21,6) = "&&" + ├── @ CallNode (location: (23,0)-(23,8)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (23,0)-(23,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (23,0)-(23,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (23,1)-(23,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :== + │ ├── message_loc: (23,4)-(23,6) = "==" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (23,7)-(23,8)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (23,7)-(23,8)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (25,0)-(25,8)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (25,0)-(25,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (25,0)-(25,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (25,1)-(25,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :!= + │ ├── message_loc: (25,4)-(25,6) = "!=" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (25,7)-(25,8)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (25,7)-(25,8)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (27,0)-(27,9)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (27,0)-(27,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (27,0)-(27,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (27,1)-(27,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :=== + │ ├── message_loc: (27,4)-(27,7) = "===" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (27,8)-(27,9)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (27,8)-(27,9)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (29,0)-(29,9)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (29,0)-(29,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (29,0)-(29,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (29,1)-(29,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :<=> + │ ├── message_loc: (29,4)-(29,7) = "<=>" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (29,8)-(29,9)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (29,8)-(29,9)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (31,0)-(31,8)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (31,0)-(31,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (31,0)-(31,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (31,1)-(31,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :=~ + │ ├── message_loc: (31,4)-(31,6) = "=~" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (31,7)-(31,8)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (31,7)-(31,8)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (33,0)-(33,8)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (33,0)-(33,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (33,0)-(33,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (33,1)-(33,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :!~ + │ ├── message_loc: (33,4)-(33,6) = "!~" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (33,7)-(33,8)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (33,7)-(33,8)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (35,0)-(35,7)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (35,0)-(35,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (35,0)-(35,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (35,1)-(35,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :< + │ ├── message_loc: (35,4)-(35,5) = "<" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (35,6)-(35,7)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (35,6)-(35,7)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (37,0)-(37,7)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (37,0)-(37,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (37,0)-(37,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (37,1)-(37,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :> + │ ├── message_loc: (37,4)-(37,5) = ">" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (37,6)-(37,7)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (37,6)-(37,7)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (39,0)-(39,8)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (39,0)-(39,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (39,0)-(39,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (39,1)-(39,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :<= + │ ├── message_loc: (39,4)-(39,6) = "<=" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (39,7)-(39,8)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (39,7)-(39,8)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (41,0)-(41,8)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (41,0)-(41,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (41,0)-(41,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (41,1)-(41,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :>= + │ ├── message_loc: (41,4)-(41,6) = ">=" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (41,7)-(41,8)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (41,7)-(41,8)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (43,0)-(43,8)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (43,0)-(43,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (43,0)-(43,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (43,1)-(43,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :<< + │ ├── message_loc: (43,4)-(43,6) = "<<" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (43,7)-(43,8)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (43,7)-(43,8)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (45,0)-(45,8)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ RangeNode (location: (45,0)-(45,3)) + │ │ ├── flags: ∅ + │ │ ├── left: + │ │ │ @ IntegerNode (location: (45,0)-(45,1)) + │ │ │ └── flags: decimal + │ │ ├── right: ∅ + │ │ └── operator_loc: (45,1)-(45,3) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :>> + │ ├── message_loc: (45,4)-(45,6) = ">>" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (45,7)-(45,8)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (45,7)-(45,8)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ RangeNode (location: (47,0)-(47,7)) + │ ├── flags: ∅ + │ ├── left: + │ │ @ IntegerNode (location: (47,0)-(47,1)) + │ │ └── flags: decimal + │ ├── right: + │ │ @ CallNode (location: (47,4)-(47,7)) + │ │ ├── flags: ∅ + │ │ ├── receiver: + │ │ │ @ IntegerNode (location: (47,6)-(47,7)) + │ │ │ └── flags: decimal + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :+@ + │ │ ├── message_loc: (47,4)-(47,5) = "+" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ └── operator_loc: (47,1)-(47,3) = ".." + └── @ RangeNode (location: (49,0)-(49,7)) ├── flags: ∅ ├── left: - │ @ IntegerNode (location: (19,0)-(19,1)) + │ @ IntegerNode (location: (49,0)-(49,1)) │ └── flags: decimal ├── right: - │ @ RangeNode (location: (19,5)-(19,8)) + │ @ CallNode (location: (49,4)-(49,7)) │ ├── flags: ∅ - │ ├── left: ∅ - │ ├── right: - │ │ @ IntegerNode (location: (19,7)-(19,8)) + │ ├── receiver: + │ │ @ IntegerNode (location: (49,6)-(49,7)) │ │ └── flags: decimal - │ └── operator_loc: (19,5)-(19,7) = ".." - └── operator_loc: (19,2)-(19,4) = ".." + │ ├── call_operator_loc: ∅ + │ ├── name: :-@ + │ ├── message_loc: (49,4)-(49,5) = "-" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ └── block: ∅ + └── operator_loc: (49,1)-(49,3) = ".." |
