diff --git a/test/yarp/fixtures/arithmetic.txt b/test/yarp/fixtures/arithmetic.txt index 47fa4ec24f5918..b1e1267b95c2de 100644 --- a/test/yarp/fixtures/arithmetic.txt +++ b/test/yarp/fixtures/arithmetic.txt @@ -7,3 +7,7 @@ foo !bar foo ~bar foo << bar << baz + +-1**2 + +-1.zero? diff --git a/test/yarp/snapshots/arithmetic.txt b/test/yarp/snapshots/arithmetic.txt index 7138973041d090..408d4cc7d6659e 100644 --- a/test/yarp/snapshots/arithmetic.txt +++ b/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: ∅ @@ -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?" diff --git a/yarp/yarp.c b/yarp/yarp.c index f1b49a7a957d0b..80070ef8f79cef 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -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), @@ -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;