Skip to content

Commit

Permalink
[ruby/yarp] Fix up unary minus precedence
Browse files Browse the repository at this point in the history
  • Loading branch information
kddnewton authored and matzbot committed Sep 14, 2023
1 parent 174aa53 commit 1b6d2b9
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 63 deletions.
4 changes: 4 additions & 0 deletions test/yarp/fixtures/arithmetic.txt
Expand Up @@ -7,3 +7,7 @@ foo !bar
foo ~bar

foo << bar << baz

-1**2

-1.zero?
142 changes: 90 additions & 52 deletions test/yarp/snapshots/arithmetic.txt
@@ -1,8 +1,8 @@
@ ProgramNode (location: (0...58))
@ ProgramNode (location: (0...75))
├── locals: []
└── statements:
@ StatementsNode (location: (0...58))
└── body: (length: 5)
@ StatementsNode (location: (0...75))
└── body: (length: 7)
├── @ CallNode (location: (0...8))
│ ├── receiver: ∅
│ ├── call_operator_loc: ∅
Expand Down Expand Up @@ -151,57 +151,95 @@
│ ├── block: ∅
│ ├── flags: ∅
│ └── name: "foo"
└── @ CallNode (location: (41...58))
├── @ CallNode (location: (41...58))
│ ├── receiver:
│ │ @ CallNode (location: (41...51))
│ │ ├── receiver:
│ │ │ @ CallNode (location: (41...44))
│ │ │ ├── receiver: ∅
│ │ │ ├── call_operator_loc: ∅
│ │ │ ├── message_loc: (41...44) = "foo"
│ │ │ ├── opening_loc: ∅
│ │ │ ├── arguments: ∅
│ │ │ ├── closing_loc: ∅
│ │ │ ├── block: ∅
│ │ │ ├── flags: variable_call
│ │ │ └── name: "foo"
│ │ ├── call_operator_loc: ∅
│ │ ├── message_loc: (45...47) = "<<"
│ │ ├── opening_loc: ∅
│ │ ├── arguments:
│ │ │ @ ArgumentsNode (location: (48...51))
│ │ │ └── arguments: (length: 1)
│ │ │ └── @ CallNode (location: (48...51))
│ │ │ ├── receiver: ∅
│ │ │ ├── call_operator_loc: ∅
│ │ │ ├── message_loc: (48...51) = "bar"
│ │ │ ├── opening_loc: ∅
│ │ │ ├── arguments: ∅
│ │ │ ├── closing_loc: ∅
│ │ │ ├── block: ∅
│ │ │ ├── flags: variable_call
│ │ │ └── name: "bar"
│ │ ├── closing_loc: ∅
│ │ ├── block: ∅
│ │ ├── flags: ∅
│ │ └── name: "<<"
│ ├── call_operator_loc: ∅
│ ├── message_loc: (52...54) = "<<"
│ ├── opening_loc: ∅
│ ├── arguments:
│ │ @ ArgumentsNode (location: (55...58))
│ │ └── arguments: (length: 1)
│ │ └── @ CallNode (location: (55...58))
│ │ ├── receiver: ∅
│ │ ├── call_operator_loc: ∅
│ │ ├── message_loc: (55...58) = "baz"
│ │ ├── opening_loc: ∅
│ │ ├── arguments: ∅
│ │ ├── closing_loc: ∅
│ │ ├── block: ∅
│ │ ├── flags: variable_call
│ │ └── name: "baz"
│ ├── closing_loc: ∅
│ ├── block: ∅
│ ├── flags: ∅
│ └── name: "<<"
├── @ CallNode (location: (60...65))
│ ├── receiver:
│ │ @ CallNode (location: (61...65))
│ │ ├── receiver:
│ │ │ @ IntegerNode (location: (61...62))
│ │ │ └── flags: decimal
│ │ ├── call_operator_loc: ∅
│ │ ├── message_loc: (62...64) = "**"
│ │ ├── opening_loc: ∅
│ │ ├── arguments:
│ │ │ @ ArgumentsNode (location: (64...65))
│ │ │ └── arguments: (length: 1)
│ │ │ └── @ IntegerNode (location: (64...65))
│ │ │ └── flags: decimal
│ │ ├── closing_loc: ∅
│ │ ├── block: ∅
│ │ ├── flags: ∅
│ │ └── name: "**"
│ ├── call_operator_loc: ∅
│ ├── message_loc: (60...61) = "-"
│ ├── opening_loc: ∅
│ ├── arguments: ∅
│ ├── closing_loc: ∅
│ ├── block: ∅
│ ├── flags: ∅
│ └── name: "-@"
└── @ CallNode (location: (67...75))
├── receiver:
│ @ CallNode (location: (41...51))
│ ├── receiver:
│ │ @ CallNode (location: (41...44))
│ │ ├── receiver: ∅
│ │ ├── call_operator_loc: ∅
│ │ ├── message_loc: (41...44) = "foo"
│ │ ├── opening_loc: ∅
│ │ ├── arguments: ∅
│ │ ├── closing_loc: ∅
│ │ ├── block: ∅
│ │ ├── flags: variable_call
│ │ └── name: "foo"
│ ├── call_operator_loc: ∅
│ ├── message_loc: (45...47) = "<<"
│ ├── opening_loc: ∅
│ ├── arguments:
│ │ @ ArgumentsNode (location: (48...51))
│ │ └── arguments: (length: 1)
│ │ └── @ CallNode (location: (48...51))
│ │ ├── receiver: ∅
│ │ ├── call_operator_loc: ∅
│ │ ├── message_loc: (48...51) = "bar"
│ │ ├── opening_loc: ∅
│ │ ├── arguments: ∅
│ │ ├── closing_loc: ∅
│ │ ├── block: ∅
│ │ ├── flags: variable_call
│ │ └── name: "bar"
│ ├── closing_loc: ∅
│ ├── block: ∅
│ ├── flags: ∅
│ └── name: "<<"
├── call_operator_loc: ∅
├── message_loc: (52...54) = "<<"
│ @ IntegerNode (location: (67...69))
│ └── flags: decimal
├── call_operator_loc: (69...70) = "."
├── message_loc: (70...75) = "zero?"
├── opening_loc: ∅
├── arguments:
│ @ ArgumentsNode (location: (55...58))
│ └── arguments: (length: 1)
│ └── @ CallNode (location: (55...58))
│ ├── receiver: ∅
│ ├── call_operator_loc: ∅
│ ├── message_loc: (55...58) = "baz"
│ ├── opening_loc: ∅
│ ├── arguments: ∅
│ ├── closing_loc: ∅
│ ├── block: ∅
│ ├── flags: variable_call
│ └── name: "baz"
├── arguments: ∅
├── closing_loc: ∅
├── block: ∅
├── flags: ∅
└── name: "<<"
└── name: "zero?"
29 changes: 18 additions & 11 deletions yarp/yarp.c
Expand Up @@ -7940,7 +7940,7 @@ yp_binding_powers_t yp_binding_powers[YP_TOKEN_MAXIMUM] = {

// -@
[YP_TOKEN_UMINUS] = RIGHT_ASSOCIATIVE_UNARY(YP_BINDING_POWER_UMINUS),
[YP_TOKEN_UMINUS_NUM] = RIGHT_ASSOCIATIVE_UNARY(YP_BINDING_POWER_UMINUS),
[YP_TOKEN_UMINUS_NUM] = { YP_BINDING_POWER_UMINUS, YP_BINDING_POWER_MAX, false },

// **
[YP_TOKEN_STAR_STAR] = RIGHT_ASSOCIATIVE(YP_BINDING_POWER_EXPONENT),
Expand Down Expand Up @@ -12953,16 +12953,23 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) {
yp_token_t operator = parser->previous;
yp_node_t *node = parse_expression(parser, yp_binding_powers[parser->previous.type].right, YP_ERR_UNARY_RECEIVER_MINUS);

switch (YP_NODE_TYPE(node)) {
case YP_INTEGER_NODE:
case YP_FLOAT_NODE:
case YP_RATIONAL_NODE:
case YP_IMAGINARY_NODE:
parse_negative_numeric(node);
break;
default:
node = (yp_node_t *) yp_call_node_unary_create(parser, &operator, node, "-@");
break;
if (accept(parser, YP_TOKEN_STAR_STAR)) {
yp_token_t exponent_operator = parser->previous;
yp_node_t *exponent = parse_expression(parser, yp_binding_powers[exponent_operator.type].right, YP_ERR_EXPECT_ARGUMENT);
node = (yp_node_t *) yp_call_node_binary_create(parser, node, &exponent_operator, exponent);
node = (yp_node_t *) yp_call_node_unary_create(parser, &operator, node, "-@");
} else {
switch (YP_NODE_TYPE(node)) {
case YP_INTEGER_NODE:
case YP_FLOAT_NODE:
case YP_RATIONAL_NODE:
case YP_IMAGINARY_NODE:
parse_negative_numeric(node);
break;
default:
node = (yp_node_t *) yp_call_node_unary_create(parser, &operator, node, "-@");
break;
}
}

return node;
Expand Down

0 comments on commit 1b6d2b9

Please sign in to comment.