summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2024-10-01 10:22:07 -0400
committerKevin Newton <kddnewton@gmail.com>2024-10-01 11:03:25 -0400
commitec230ac6432ea89f1ee53d82a62337d4883dc83a (patch)
tree8d61d7119eabad74dac370eeab8828486d7de673
parent169a5ee99e1e8742e6821f8b846d39e90c3c9ea8 (diff)
Resync to latest Prism
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/11753
-rw-r--r--prism/config.yml1
-rw-r--r--prism/prism.c42
-rw-r--r--prism/templates/src/diagnostic.c.erb1
-rw-r--r--test/prism/errors/command_call_in.txt6
-rw-r--r--test/prism/errors/infix_after_label.txt6
-rw-r--r--test/prism/errors/trailing_comma_after_block.txt3
6 files changed, 49 insertions, 10 deletions
diff --git a/prism/config.yml b/prism/config.yml
index b5de4d2b4a..972f1e8e69 100644
--- a/prism/config.yml
+++ b/prism/config.yml
@@ -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
diff --git a/prism/prism.c b/prism/prism.c
index a99fb712e3..2e98702d9b 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -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);
@@ -21576,6 +21573,19 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
#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
* will append the error message to the parser's error list.
@@ -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:
diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb
index b2381db57f..d2b7b4f691 100644
--- a/prism/templates/src/diagnostic.c.erb
+++ b/prism/templates/src/diagnostic.c.erb
@@ -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 },
diff --git a/test/prism/errors/command_call_in.txt b/test/prism/errors/command_call_in.txt
index a4357028c6..2fdcf09738 100644
--- a/test/prism/errors/command_call_in.txt
+++ b/test/prism/errors/command_call_in.txt
@@ -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
diff --git a/test/prism/errors/infix_after_label.txt b/test/prism/errors/infix_after_label.txt
new file mode 100644
index 0000000000..c3bcfaeceb
--- /dev/null
+++ b/test/prism/errors/infix_after_label.txt
@@ -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
+
diff --git a/test/prism/errors/trailing_comma_after_block.txt b/test/prism/errors/trailing_comma_after_block.txt
new file mode 100644
index 0000000000..d25db0efbe
--- /dev/null
+++ b/test/prism/errors/trailing_comma_after_block.txt
@@ -0,0 +1,3 @@
+p{|&,|}
+ ^ unexpected `,` in parameters
+