Skip to content

Commit 55408bf

Browse files
authored
Merge pull request ruby#3496 from ruby/multiple-statements-flag
Add a multiple statements flag to parentheses
2 parents 5c04045 + b63b5d6 commit 55408bf

File tree

12 files changed

+53
-23
lines changed

12 files changed

+53
-23
lines changed

config.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,11 @@ flags:
719719
- name: REPEATED_PARAMETER
720720
comment: "a parameter name that has been repeated in the method signature"
721721
comment: Flags for parameter nodes.
722+
- name: ParenthesesNodeFlags
723+
values:
724+
- name: MULTIPLE_STATEMENTS
725+
comment: "parentheses that contain multiple potentially void statements"
726+
comment: Flags for parentheses nodes.
722727
- name: RangeFlags
723728
values:
724729
- name: EXCLUDE_END
@@ -3851,6 +3856,7 @@ nodes:
38513856
^^^^^^^
38523857
end
38533858
- name: ParenthesesNode
3859+
flags: ParenthesesNodeFlags
38543860
fields:
38553861
- name: body
38563862
type: node?

src/prism.c

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6406,12 +6406,13 @@ pm_program_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, pm_st
64066406
* Allocate and initialize new ParenthesesNode node.
64076407
*/
64086408
static pm_parentheses_node_t *
6409-
pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_node_t *body, const pm_token_t *closing) {
6409+
pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_node_t *body, const pm_token_t *closing, pm_node_flags_t flags) {
64106410
pm_parentheses_node_t *node = PM_NODE_ALLOC(parser, pm_parentheses_node_t);
64116411

64126412
*node = (pm_parentheses_node_t) {
64136413
{
64146414
.type = PM_PARENTHESES_NODE,
6415+
.flags = flags,
64156416
.node_id = PM_NODE_IDENTIFY(parser),
64166417
.location = {
64176418
.start = opening->start,
@@ -17551,7 +17552,7 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p
1755117552
pm_node_t *body = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN, (uint16_t) (depth + 1));
1755217553
accept1(parser, PM_TOKEN_NEWLINE);
1755317554
expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN);
17554-
pm_node_t *right = (pm_node_t *) pm_parentheses_node_create(parser, &opening, body, &parser->previous);
17555+
pm_node_t *right = (pm_node_t *) pm_parentheses_node_create(parser, &opening, body, &parser->previous, 0);
1755517556

1755617557
if (node == NULL) {
1755717558
node = right;
@@ -18174,12 +18175,19 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1817418175
case PM_TOKEN_PARENTHESIS_LEFT:
1817518176
case PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES: {
1817618177
pm_token_t opening = parser->current;
18178+
pm_node_flags_t flags = 0;
1817718179

1817818180
pm_node_list_t current_block_exits = { 0 };
1817918181
pm_node_list_t *previous_block_exits = push_block_exits(parser, &current_block_exits);
1818018182

1818118183
parser_lex(parser);
18182-
while (accept2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE));
18184+
while (true) {
18185+
if (accept1(parser, PM_TOKEN_SEMICOLON)) {
18186+
flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS;
18187+
} else if (!accept1(parser, PM_TOKEN_NEWLINE)) {
18188+
break;
18189+
}
18190+
}
1818318191

1818418192
// If this is the end of the file or we match a right parenthesis, then
1818518193
// we have an empty parentheses node, and we can immediately return.
@@ -18189,7 +18197,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1818918197
pop_block_exits(parser, previous_block_exits);
1819018198
pm_node_list_free(&current_block_exits);
1819118199

18192-
return (pm_node_t *) pm_parentheses_node_create(parser, &opening, NULL, &parser->previous);
18200+
return (pm_node_t *) pm_parentheses_node_create(parser, &opening, NULL, &parser->previous, flags);
1819318201
}
1819418202

1819518203
// Otherwise, we're going to parse the first statement in the list
@@ -18202,9 +18210,23 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1820218210
// Determine if this statement is followed by a terminator. In the
1820318211
// case of a single statement, this is fine. But in the case of
1820418212
// multiple statements it's required.
18205-
bool terminator_found = accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
18213+
bool terminator_found = false;
18214+
18215+
if (accept1(parser, PM_TOKEN_SEMICOLON)) {
18216+
terminator_found = true;
18217+
flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS;
18218+
} else if (accept1(parser, PM_TOKEN_NEWLINE)) {
18219+
terminator_found = true;
18220+
}
18221+
1820618222
if (terminator_found) {
18207-
while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON));
18223+
while (true) {
18224+
if (accept1(parser, PM_TOKEN_SEMICOLON)) {
18225+
flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS;
18226+
} else if (!accept1(parser, PM_TOKEN_NEWLINE)) {
18227+
break;
18228+
}
18229+
}
1820818230
}
1820918231

1821018232
// If we hit a right parenthesis, then we're done parsing the
@@ -18276,13 +18298,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1827618298
pm_statements_node_t *statements = pm_statements_node_create(parser);
1827718299
pm_statements_node_body_append(parser, statements, statement, true);
1827818300

18279-
return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous);
18301+
return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous, flags);
1828018302
}
1828118303

1828218304
// If we have more than one statement in the set of parentheses,
1828318305
// then we are going to parse all of them as a list of statements.
1828418306
// We'll do that here.
1828518307
context_push(parser, PM_CONTEXT_PARENS);
18308+
flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS;
18309+
1828618310
pm_statements_node_t *statements = pm_statements_node_create(parser);
1828718311
pm_statements_node_body_append(parser, statements, statement, true);
1828818312

@@ -18359,7 +18383,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1835918383
pm_node_list_free(&current_block_exits);
1836018384

1836118385
pm_void_statements_check(parser, statements, true);
18362-
return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous);
18386+
return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous, flags);
1836318387
}
1836418388
case PM_TOKEN_BRACE_LEFT: {
1836518389
// If we were passed a current_hash_keys via the parser, then that
@@ -19405,7 +19429,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1940519429
expect2(parser, PM_TOKEN_DOT, PM_TOKEN_COLON_COLON, PM_ERR_DEF_RECEIVER_TERM);
1940619430

1940719431
operator = parser->previous;
19408-
receiver = (pm_node_t *) pm_parentheses_node_create(parser, &lparen, expression, &rparen);
19432+
receiver = (pm_node_t *) pm_parentheses_node_create(parser, &lparen, expression, &rparen, 0);
1940919433

1941019434
// To push `PM_CONTEXT_DEF_PARAMS` again is for the same
1941119435
// reason as described the above.
@@ -19738,7 +19762,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1973819762
pm_token_t lparen = parser->previous;
1973919763

1974019764
if (accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
19741-
receiver = (pm_node_t *) pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous);
19765+
receiver = (pm_node_t *) pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0);
1974219766
} else {
1974319767
arguments.opening_loc = PM_LOCATION_TOKEN_VALUE(&lparen);
1974419768
receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1));

test/prism/snapshots/break.txt

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/prism/snapshots/methods.txt

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/prism/snapshots/next.txt

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/prism/snapshots/nils.txt

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/prism/snapshots/return.txt

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/prism/snapshots/unparser/corpus/literal/def.txt

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/prism/snapshots/unparser/corpus/literal/send.txt

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/prism/snapshots/variables.txt

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)