Skip to content

Commit 4e71dbf

Browse files
committed
Reject infix operators on command call on writes
1 parent 6d97e76 commit 4e71dbf

File tree

3 files changed

+33
-3
lines changed

3 files changed

+33
-3
lines changed

src/prism.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21605,6 +21605,26 @@ pm_call_node_command_p(const pm_call_node_t *node) {
2160521605
);
2160621606
}
2160721607

21608+
/**
21609+
* Determine if a given write node has a command call as its right-hand side. We
21610+
* need this because command calls as the values of writes cannot be extended by
21611+
* infix operators.
21612+
*/
21613+
static inline bool
21614+
pm_write_node_command_p(const pm_node_t *node) {
21615+
pm_node_t *value;
21616+
switch (PM_NODE_TYPE(node)) {
21617+
case PM_CLASS_VARIABLE_WRITE_NODE: value = ((pm_class_variable_write_node_t *) node)->value; break;
21618+
case PM_CONSTANT_PATH_WRITE_NODE: value = ((pm_constant_path_write_node_t *) node)->value; break;
21619+
case PM_CONSTANT_WRITE_NODE: value = ((pm_constant_write_node_t *) node)->value; break;
21620+
case PM_GLOBAL_VARIABLE_WRITE_NODE: value = ((pm_global_variable_write_node_t *) node)->value; break;
21621+
case PM_INSTANCE_VARIABLE_WRITE_NODE: value = ((pm_instance_variable_write_node_t *) node)->value; break;
21622+
case PM_LOCAL_VARIABLE_WRITE_NODE: value = ((pm_local_variable_write_node_t *) node)->value; break;
21623+
default: return false;
21624+
}
21625+
return PM_NODE_TYPE_P(value, PM_CALL_NODE) && pm_call_node_command_p((pm_call_node_t *) value);
21626+
}
21627+
2160821628
/**
2160921629
* Parse an expression at the given point of the parser using the given binding
2161021630
* power to parse subsequent chains. If this function finds a syntax error, it
@@ -21689,9 +21709,13 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
2168921709
case PM_INSTANCE_VARIABLE_WRITE_NODE:
2169021710
case PM_LOCAL_VARIABLE_WRITE_NODE:
2169121711
// These expressions are statements, by virtue of the right-hand
21692-
// side of their write being an implicit array.
21693-
if (PM_NODE_FLAG_P(node, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY) && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) {
21694-
return node;
21712+
// side of their write being an implicit array or a command call.
21713+
// This mirrors parse.y's behavior where `lhs = command_call`
21714+
// reduces to stmt (not expr), preventing and/or from following.
21715+
if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) {
21716+
if (PM_NODE_FLAG_P(node, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY) || pm_write_node_command_p(node)) {
21717+
return node;
21718+
}
2169521719
}
2169621720
break;
2169721721
case PM_CALL_NODE:

test/prism/errors/command_call_in.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ foo 1 in a
22
^~ unexpected 'in', expecting end-of-input
33
^~ unexpected 'in', ignoring it
44
a = foo 2 in b
5+
^~ unexpected 'in', expecting end-of-input
6+
^~ unexpected 'in', ignoring it
57

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
a = b c and 1
2+
^~~ unexpected 'and', expecting end-of-input
3+
^~~ unexpected 'and', ignoring it
4+

0 commit comments

Comments
 (0)