From b6b31f673d9514a8af8992b0f7abb8b0597d87af Mon Sep 17 00:00:00 2001 From: Hiroya Fujinami Date: Tue, 21 Nov 2023 11:45:08 +0900 Subject: [ruby/prism] Check a token after targets more strictly (https://github.com/ruby/prism/pull/1878) Fix https://github.com/ruby/prism/pull/1832 https://github.com/ruby/prism/commit/060bcc81a8 --- prism/prism.c | 10 ++++++++-- test/prism/errors_test.rb | 5 +++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 3b70ae1115..09ccaf70cf 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -10692,8 +10692,12 @@ static pm_node_t * parse_target_validate(pm_parser_t *parser, pm_node_t *target) { pm_node_t *result = parse_target(parser, target); - // Ensure that we have either an = or a ) after the targets. - if (!match3(parser, PM_TOKEN_EQUAL, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_KEYWORD_IN)) { + // Ensure that we have one of an =, an 'in' in for indexes, and a ')' in parens after the targets. + if ( + !match1(parser, PM_TOKEN_EQUAL) && + !(context_p(parser, PM_CONTEXT_FOR_INDEX) && match1(parser, PM_TOKEN_KEYWORD_IN)) && + !(context_p(parser, PM_CONTEXT_PARENS) && match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) + ) { pm_parser_err_node(parser, result, PM_ERR_WRITE_TARGET_UNEXPECTED); } @@ -13746,7 +13750,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { // Otherwise, we're going to parse the first statement in the list // of statements within the parentheses. pm_accepts_block_stack_push(parser, true); + context_push(parser, PM_CONTEXT_PARENS); pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT, PM_ERR_CANNOT_PARSE_EXPRESSION); + context_pop(parser); // Determine if this statement is followed by a terminator. In the // case of a single statement, this is fine. But in the case of diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index c6d35baed4..cf7330dfb2 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -1225,6 +1225,11 @@ module Prism assert_error_messages "Foo::foo,", error_messages assert_error_messages "foo[foo],", error_messages assert_error_messages "(foo, bar)", error_messages + assert_error_messages "foo((foo, bar))", error_messages + assert_error_messages "foo((*))", error_messages + assert_error_messages "foo(((foo, bar), *))", error_messages + assert_error_messages "(foo, bar) + 1", error_messages + assert_error_messages "(foo, bar) in baz", error_messages end def test_call_with_block_and_write -- cgit v1.2.3