diff options
author | Kevin Newton <kddnewton@gmail.com> | 2024-06-14 15:09:25 -0400 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2024-06-14 19:22:54 +0000 |
commit | 7529591df11563fa29e19716322ca03b0c6d3e3e (patch) | |
tree | 3f07b5f16a07af8ae8726b12f7a404a96c461990 | |
parent | 4d73f3f9ebefa347acc1ec8031ac4025f5f71ba8 (diff) | |
download | ruby-7529591df11563fa29e19716322ca03b0c6d3e3e.tar.gz |
[ruby/prism] Ensure ranges are non-associative
https://github.com/ruby/prism/commit/f59295938b
-rw-r--r-- | prism/config.yml | 1 | ||||
-rw-r--r-- | prism/prism.c | 18 | ||||
-rw-r--r-- | prism/templates/src/diagnostic.c.erb | 1 | ||||
-rw-r--r-- | test/prism/errors_test.rb | 4 |
4 files changed, 13 insertions, 11 deletions
diff --git a/prism/config.yml b/prism/config.yml index 9b54982106..98443af774 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -267,6 +267,7 @@ errors: - UNEXPECTED_INDEX_BLOCK - UNEXPECTED_INDEX_KEYWORDS - UNEXPECTED_MULTI_WRITE + - UNEXPECTED_RANGE_OPERATOR - UNEXPECTED_SAFE_NAVIGATION - UNEXPECTED_TOKEN_CLOSE_CONTEXT - UNEXPECTED_TOKEN_IGNORE diff --git a/prism/prism.c b/prism/prism.c index 6b094715e6..2c9d3d9c56 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -17737,6 +17737,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_node_t *right = parse_expression(parser, pm_binding_powers[operator.type].left, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + + // Unary .. and ... are special because these are non-associative + // operators that can also be unary operators. In this case we need + // to explicitly reject code that has a .. or ... that follows this + // expression. + if (match2(parser, PM_TOKEN_DOT_DOT, PM_TOKEN_DOT_DOT_DOT)) { + pm_parser_err_current(parser, PM_ERR_UNEXPECTED_RANGE_OPERATOR); + } + return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right); } case PM_TOKEN_FLOAT: @@ -20987,15 +20996,6 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc return node; } break; - case PM_RANGE_NODE: - // 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 ((((pm_range_node_t *) node)->left == NULL) && pm_binding_powers[parser->current.type].left >= PM_BINDING_POWER_RANGE) { - return node; - } - break; default: break; } diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 1fc3e6047e..f94f83a7a1 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -348,6 +348,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_UNEXPECTED_INDEX_BLOCK] = { "unexpected block arg given in index assignment; blocks are not allowed in index assignment expressions", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNEXPECTED_INDEX_KEYWORDS] = { "unexpected keyword arg given in index assignment; keywords are not allowed in index assignment expressions", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNEXPECTED_MULTI_WRITE] = { "unexpected multiple assignment; multiple assignment is not allowed in this context", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_UNEXPECTED_RANGE_OPERATOR] = { "unexpected range operator; .. and ... are non-associative and cannot be chained", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNEXPECTED_SAFE_NAVIGATION] = { "&. inside multiple assignment destination", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT] = { "unexpected %s, assuming it is closing the parent %s", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_UNEXPECTED_TOKEN_IGNORE] = { "unexpected %s, ignoring it", PM_ERROR_LEVEL_SYNTAX }, diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 91ba6ea373..2d8ddd7a11 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -1975,8 +1975,8 @@ module Prism RUBY assert_errors expression(source), source, [ - ["unexpected .., expecting end-of-input", 3..5], - ["unexpected .., ignoring it", 3..5], + ["unexpected range operator; .. and ... are non-associative and cannot be chained", 3..5], + ["unexpected range operator; .. and ... are non-associative and cannot be chained", 10..12], ["unexpected .., expecting end-of-input", 10..12], ["unexpected .., ignoring it", 10..12] ] |