Skip to content

Commit c5da02a

Browse files
committed
Pop block stack _before_ ending in parenthesized method call in command call
1 parent 26cfb91 commit c5da02a

2 files changed

Lines changed: 22 additions & 1 deletion

File tree

src/prism.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15290,6 +15290,12 @@ parse_block(pm_parser_t *parser, uint16_t depth) {
1529015290
statements = UP(parse_statements(parser, PM_CONTEXT_BLOCK_BRACES, (uint16_t) (depth + 1)));
1529115291
}
1529215292

15293+
/* Pop before consuming the closing `}` so the following token (e.g. a
15294+
* `do`) is lexed in the enclosing context rather than as a block
15295+
* belonging to this block's interior. Otherwise a `do` block would
15296+
* wrongly bind to a command whose argument ends in a brace block, as in
15297+
* `foo(m a { } do end)`. */
15298+
pm_accepts_block_stack_pop(parser);
1529315299
expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_BLOCK_TERM_BRACE, &opening);
1529415300
} else {
1529515301
if (!match1(parser, PM_TOKEN_KEYWORD_END)) {
@@ -15305,6 +15311,8 @@ parse_block(pm_parser_t *parser, uint16_t depth) {
1530515311
}
1530615312
}
1530715313

15314+
/* As with the brace case above, pop before consuming `end`. */
15315+
pm_accepts_block_stack_pop(parser);
1530815316
expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BLOCK_TERM_END, &opening);
1530915317
}
1531015318

@@ -15313,7 +15321,6 @@ parse_block(pm_parser_t *parser, uint16_t depth) {
1531315321
pm_node_t *parameters = parse_blocklike_parameters(parser, UP(block_parameters), &opening, &parser->previous);
1531415322

1531515323
pm_parser_scope_pop(parser);
15316-
pm_accepts_block_stack_pop(parser);
1531715324

1531815325
return pm_block_node_create(parser, &locals, &opening, parameters, statements, &parser->previous);
1531915326
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
foo(m a { } do end)
2+
^~ unexpected 'do'; expected a `)` to close the arguments
3+
^~ unexpected 'do', expecting end-of-input
4+
^~ unexpected 'do', ignoring it
5+
^~~ unexpected 'end', ignoring it
6+
^ unexpected ')', ignoring it
7+
8+
foo(m a.b { } do end)
9+
^~ unexpected 'do'; expected a `)` to close the arguments
10+
^~ unexpected 'do', expecting end-of-input
11+
^~ unexpected 'do', ignoring it
12+
^~~ unexpected 'end', ignoring it
13+
^ unexpected ')', ignoring it
14+

0 commit comments

Comments
 (0)