From c54e225f34957967709dee59c0d66b265fd30e05 Mon Sep 17 00:00:00 2001 From: Haldun Bayhantopcu Date: Fri, 22 Sep 2023 17:18:02 +0200 Subject: [PATCH] [ruby/yarp] Introduce YP_TOKEN_METHOD_NAME https://github.com/ruby/yarp/commit/e855bf415c --- lib/yarp/lex_compat.rb | 1 + test/yarp/errors_test.rb | 9 +++++++++ yarp/config.yml | 2 ++ yarp/diagnostic.c | 1 + yarp/diagnostic.h | 1 + yarp/yarp.c | 36 +++++++++++++++++++++++++----------- 6 files changed, 39 insertions(+), 11 deletions(-) diff --git a/lib/yarp/lex_compat.rb b/lib/yarp/lex_compat.rb index 37bfecd0bca934..6ed7575ffdcecb 100644 --- a/lib/yarp/lex_compat.rb +++ b/lib/yarp/lex_compat.rb @@ -128,6 +128,7 @@ class LexCompat LESS_EQUAL_GREATER: :on_op, LESS_LESS: :on_op, LESS_LESS_EQUAL: :on_op, + METHOD_NAME: :on_ident, MINUS: :on_op, MINUS_EQUAL: :on_op, MINUS_GREATER: :on_tlambda, diff --git a/test/yarp/errors_test.rb b/test/yarp/errors_test.rb index 110834428bdaa7..d152c7cfc0e786 100644 --- a/test/yarp/errors_test.rb +++ b/test/yarp/errors_test.rb @@ -1310,6 +1310,15 @@ def test_conditional_predicate_closed ] end + def test_parameter_name_ending_with_bang_or_question_mark + source = "def foo(x!,y?); end" + errors = [ + ["Unexpected name for a parameter", 8..10], + ["Unexpected name for a parameter", 11..13] + ] + assert_errors expression(source), source, errors, compare_ripper: false + end + private def assert_errors(expected, source, errors, compare_ripper: RUBY_ENGINE == "ruby") diff --git a/yarp/config.yml b/yarp/config.yml index 18f289a0f48200..b78cf06ee5c342 100644 --- a/yarp/config.yml +++ b/yarp/config.yml @@ -232,6 +232,8 @@ tokens: comment: "<<" - name: LESS_LESS_EQUAL comment: "<<=" + - name: METHOD_NAME + comment: "a method name" - name: MINUS comment: "-" - name: MINUS_EQUAL diff --git a/yarp/diagnostic.c b/yarp/diagnostic.c index 68e6a412fb4d1a..cade793cfead2a 100644 --- a/yarp/diagnostic.c +++ b/yarp/diagnostic.c @@ -193,6 +193,7 @@ static const char* const diagnostic_messages[YP_DIAGNOSTIC_ID_LEN] = { [YP_ERR_OPERATOR_WRITE_BLOCK] = "Unexpected operator after a call with a block", [YP_ERR_PARAMETER_ASSOC_SPLAT_MULTI] = "Unexpected multiple `**` splat parameters", [YP_ERR_PARAMETER_BLOCK_MULTI] = "Multiple block parameters; only one block is allowed", + [YP_ERR_PARAMETER_METHOD_NAME] = "Unexpected name for a parameter", [YP_ERR_PARAMETER_NAME_REPEAT] = "Repeated parameter name", [YP_ERR_PARAMETER_NO_DEFAULT] = "Expected a default value for the parameter", [YP_ERR_PARAMETER_NO_DEFAULT_KW] = "Expected a default value for the keyword parameter", diff --git a/yarp/diagnostic.h b/yarp/diagnostic.h index 9de36650fc218a..250c53cad51632 100644 --- a/yarp/diagnostic.h +++ b/yarp/diagnostic.h @@ -159,6 +159,7 @@ typedef enum { YP_ERR_OPERATOR_WRITE_BLOCK, YP_ERR_PARAMETER_ASSOC_SPLAT_MULTI, YP_ERR_PARAMETER_BLOCK_MULTI, + YP_ERR_PARAMETER_METHOD_NAME, YP_ERR_PARAMETER_NAME_REPEAT, YP_ERR_PARAMETER_NO_DEFAULT, YP_ERR_PARAMETER_NO_DEFAULT_KW, diff --git a/yarp/yarp.c b/yarp/yarp.c index b6f35da6fa0edd..b641521be58b58 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -5702,8 +5702,10 @@ lex_identifier(yp_parser_t *parser, bool previous_command_start) { } } - return YP_TOKEN_IDENTIFIER; - } else if (lex_state_p(parser, YP_LEX_STATE_FNAME) && peek_offset(parser, 1) != '~' && peek_offset(parser, 1) != '>' && (peek_offset(parser, 1) != '=' || peek_offset(parser, 2) == '>') && match(parser, '=')) { + return YP_TOKEN_METHOD_NAME; + } + + if (lex_state_p(parser, YP_LEX_STATE_FNAME) && peek_offset(parser, 1) != '~' && peek_offset(parser, 1) != '>' && (peek_offset(parser, 1) != '=' || peek_offset(parser, 2) == '>') && match(parser, '=')) { // If we're in a position where we can accept a = at the end of an // identifier, then we'll optionally accept it. return YP_TOKEN_IDENTIFIER; @@ -7296,7 +7298,7 @@ parser_lex(yp_parser_t *parser) { yp_lex_state_t last_state = parser->lex_state; - if (type == YP_TOKEN_IDENTIFIER || type == YP_TOKEN_CONSTANT) { + if (type == YP_TOKEN_IDENTIFIER || type == YP_TOKEN_CONSTANT || type == YP_TOKEN_METHOD_NAME) { if (lex_state_p(parser, YP_LEX_STATE_BEG_ANY | YP_LEX_STATE_ARG_ANY | YP_LEX_STATE_DOT)) { if (previous_command_start) { lex_state_set(parser, YP_LEX_STATE_CMDARG); @@ -9284,7 +9286,8 @@ parse_parameters( case YP_TOKEN_IDENTIFIER: case YP_TOKEN_CONSTANT: case YP_TOKEN_INSTANCE_VARIABLE: - case YP_TOKEN_GLOBAL_VARIABLE: { + case YP_TOKEN_GLOBAL_VARIABLE: + case YP_TOKEN_METHOD_NAME: { parser_lex(parser); switch (parser->previous.type) { case YP_TOKEN_CONSTANT: @@ -9299,6 +9302,9 @@ parse_parameters( case YP_TOKEN_CLASS_VARIABLE: yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, YP_ERR_ARGUMENT_FORMAL_CLASS); break; + case YP_TOKEN_METHOD_NAME: + yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, YP_ERR_PARAMETER_METHOD_NAME); + break; default: break; } @@ -10128,6 +10134,7 @@ parse_symbol(yp_parser_t *parser, yp_lex_mode_t *lex_mode, yp_lex_state_t next_s case YP_TOKEN_IDENTIFIER: case YP_TOKEN_CONSTANT: case YP_TOKEN_INSTANCE_VARIABLE: + case YP_TOKEN_METHOD_NAME: case YP_TOKEN_CLASS_VARIABLE: case YP_TOKEN_GLOBAL_VARIABLE: case YP_TOKEN_NUMBERED_REFERENCE: @@ -10142,7 +10149,7 @@ parse_symbol(yp_parser_t *parser, yp_lex_mode_t *lex_mode, yp_lex_state_t next_s symbol = parser->previous; break; default: - expect1(parser, YP_TOKEN_IDENTIFIER, YP_ERR_SYMBOL_INVALID); + expect2(parser, YP_TOKEN_IDENTIFIER, YP_TOKEN_METHOD_NAME, YP_ERR_SYMBOL_INVALID); symbol = parser->previous; break; } @@ -10214,7 +10221,8 @@ parse_undef_argument(yp_parser_t *parser) { case YP_CASE_KEYWORD: case YP_CASE_OPERATOR: case YP_TOKEN_CONSTANT: - case YP_TOKEN_IDENTIFIER: { + case YP_TOKEN_IDENTIFIER: + case YP_TOKEN_METHOD_NAME: { parser_lex(parser); yp_token_t opening = not_provided(parser); @@ -10244,7 +10252,8 @@ parse_alias_argument(yp_parser_t *parser, bool first) { case YP_CASE_OPERATOR: case YP_CASE_KEYWORD: case YP_TOKEN_CONSTANT: - case YP_TOKEN_IDENTIFIER: { + case YP_TOKEN_IDENTIFIER: + case YP_TOKEN_METHOD_NAME: { if (first) { lex_state_set(parser, YP_LEX_STATE_FNAME | YP_LEX_STATE_FITEM); } @@ -10351,6 +10360,7 @@ parse_method_definition_name(yp_parser_t *parser) { case YP_CASE_KEYWORD: case YP_TOKEN_CONSTANT: case YP_TOKEN_IDENTIFIER: + case YP_TOKEN_METHOD_NAME: parser_lex(parser); return parser->previous; case YP_CASE_OPERATOR: @@ -10782,7 +10792,8 @@ parse_pattern_hash(yp_parser_t *parser, yp_node_t *first_assoc) { static yp_node_t * parse_pattern_primitive(yp_parser_t *parser, yp_diagnostic_id_t diag_id) { switch (parser->current.type) { - case YP_TOKEN_IDENTIFIER: { + case YP_TOKEN_IDENTIFIER: + case YP_TOKEN_METHOD_NAME: { parser_lex(parser); yp_parser_local_add_token(parser, &parser->previous); return (yp_node_t *) yp_local_variable_target_node_create(parser, &parser->previous); @@ -11717,7 +11728,8 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { return node; } - case YP_TOKEN_IDENTIFIER: { + case YP_TOKEN_IDENTIFIER: + case YP_TOKEN_METHOD_NAME: { parser_lex(parser); yp_token_t identifier = parser->previous; yp_node_t *node = parse_variable_call(parser); @@ -13940,7 +13952,8 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t case YP_CASE_OPERATOR: case YP_CASE_KEYWORD: case YP_TOKEN_CONSTANT: - case YP_TOKEN_IDENTIFIER: { + case YP_TOKEN_IDENTIFIER: + case YP_TOKEN_METHOD_NAME: { parser_lex(parser); message = parser->previous; break; @@ -14070,7 +14083,8 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t } case YP_CASE_OPERATOR: case YP_CASE_KEYWORD: - case YP_TOKEN_IDENTIFIER: { + case YP_TOKEN_IDENTIFIER: + case YP_TOKEN_METHOD_NAME: { parser_lex(parser); yp_token_t message = parser->previous;