Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check command calls in parse_expression #3107

Merged
merged 1 commit into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ errors:
- ARGUMENT_FORMAL_GLOBAL
- ARGUMENT_FORMAL_IVAR
- ARGUMENT_FORWARDING_UNBOUND
- ARGUMENT_IN
- ARGUMENT_NO_FORWARDING_AMPERSAND
- ARGUMENT_NO_FORWARDING_ELLIPSES
- ARGUMENT_NO_FORWARDING_STAR
Expand Down
26 changes: 23 additions & 3 deletions src/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -14271,9 +14271,6 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for

pm_static_literals_free(&hash_keys);
parsed_bare_hash = true;
} else if (accept1(parser, PM_TOKEN_KEYWORD_IN)) {
// TODO: Could we solve this with binding powers instead?
pm_parser_err_current(parser, PM_ERR_ARGUMENT_IN);
}

parse_arguments_append(parser, arguments, argument);
Expand Down Expand Up @@ -21573,6 +21570,19 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
#undef PM_PARSE_PATTERN_TOP
#undef PM_PARSE_PATTERN_MULTI

/**
* Determine if a given call node looks like a "command", which means it has
* arguments but does not have parentheses.
*/
static inline bool
pm_call_node_command_p(const pm_call_node_t *node) {
return (
(node->opening_loc.start == NULL) &&
(node->block == NULL || PM_NODE_TYPE_P(node->block, PM_BLOCK_ARGUMENT_NODE)) &&
(node->arguments != NULL || node->block != NULL)
);
}

/**
* Parse an expression at the given point of the parser using the given binding
* power to parse subsequent chains. If this function finds a syntax error, it
Expand Down Expand Up @@ -21607,6 +21617,16 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
return node;
}
break;
case PM_CALL_NODE:
// If we have a call node, then we need to check if it looks like a
// method call without parentheses that contains arguments. If it
// does, then it has different rules for parsing infix operators,
// namely that it only accepts composition (and/or) and modifiers
// (if/unless/etc.).
if ((pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_COMPOSITION) && pm_call_node_command_p((pm_call_node_t *) node)) {
return node;
}
break;
default:
break;
}
Expand Down
1 change: 0 additions & 1 deletion templates/src/diagnostic.c.erb
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_ARGUMENT_FORMAL_GLOBAL] = { "invalid formal argument; formal argument cannot be a global variable", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_FORMAL_IVAR] = { "invalid formal argument; formal argument cannot be an instance variable", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_IN] = { "unexpected `in` keyword in arguments", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND] = { "unexpected `&`; no anonymous block parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = { "unexpected ... when the parent method is not forwarding", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = { "unexpected `*`; no anonymous rest parameter", PM_ERROR_LEVEL_SYNTAX },
Expand Down
6 changes: 2 additions & 4 deletions test/prism/errors/command_call_in.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
foo 1 in a
^ unexpected `in` keyword in arguments
^ unexpected local variable or method, expecting end-of-input
^~ unexpected 'in', expecting end-of-input
^~ unexpected 'in', ignoring it
a = foo 2 in b
^ unexpected `in` keyword in arguments
^ unexpected local variable or method, expecting end-of-input

Loading