This commit is contained in:
Kevin Newton 2024-10-01 10:22:07 -04:00
Родитель 169a5ee99e
Коммит ec230ac643
6 изменённых файлов: 49 добавлений и 10 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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);
@ -14786,7 +14783,7 @@ parse_parameters(
}
default:
if (parser->previous.type == PM_TOKEN_COMMA) {
if (allows_trailing_comma) {
if (allows_trailing_comma && order >= PM_PARAMETERS_ORDER_NAMED) {
// If we get here, then we have a trailing comma in a
// block parameter list.
pm_node_t *param = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
@ -21575,6 +21572,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
@ -21609,6 +21619,23 @@ 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;
case PM_SYMBOL_NODE:
// If we have a symbol node that is being parsed as a label, then we
// need to immediately return, because there should never be an
// infix operator following this node.
if (pm_symbol_node_label_p(node)) {
return node;
}
default:
break;
}
@ -21624,6 +21651,13 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call, (uint16_t) (depth + 1));
switch (PM_NODE_TYPE(node)) {
case PM_MULTI_WRITE_NODE:
// Multi-write nodes are statements, and cannot be followed by
// operators except modifiers.
if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) {
return node;
}
break;
case PM_CLASS_VARIABLE_WRITE_NODE:
case PM_CONSTANT_PATH_WRITE_NODE:
case PM_CONSTANT_WRITE_NODE:

Просмотреть файл

@ -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 },

Просмотреть файл

@ -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

Просмотреть файл

@ -0,0 +1,6 @@
{ 'a':.upcase => 1 }
^ unexpected '.'; expected a value in the hash literal
^ expected a `}` to close the hash literal
^ unexpected '}', expecting end-of-input
^ unexpected '}', ignoring it

Просмотреть файл

@ -0,0 +1,3 @@
p{|&,|}
^ unexpected `,` in parameters