Skip to content

Commit

Permalink
Pop lex mode for heredocs in the lexer, not the parser
Browse files Browse the repository at this point in the history
  • Loading branch information
kddnewton committed Oct 3, 2024
1 parent 9f4b24d commit e444d1e
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 14 deletions.
28 changes: 14 additions & 14 deletions src/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,10 +544,7 @@ pm_parser_warn_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id
* token.
*/
static void
pm_parser_err_heredoc_term(pm_parser_t *parser, pm_lex_mode_t *lex_mode) {
const uint8_t *ident_start = lex_mode->as.heredoc.ident_start;
size_t ident_length = lex_mode->as.heredoc.ident_length;

pm_parser_err_heredoc_term(pm_parser_t *parser, const uint8_t *ident_start, size_t ident_length) {
PM_PARSER_ERR_FORMAT(
parser,
ident_start,
Expand Down Expand Up @@ -11171,7 +11168,7 @@ parser_lex(pm_parser_t *parser) {
// this is not a valid heredoc declaration. In this case we
// will add an error, but we will still return a heredoc
// start.
if (!ident_error) pm_parser_err_heredoc_term(parser, parser->lex_modes.current);
if (!ident_error) pm_parser_err_heredoc_term(parser, parser->lex_modes.current->as.heredoc.ident_start, parser->lex_modes.current->as.heredoc.ident_length);
body_start = parser->end;
} else {
// Otherwise, we want to indicate that the body of the
Expand Down Expand Up @@ -12523,10 +12520,11 @@ parser_lex(pm_parser_t *parser) {
// terminator) but still continue parsing so that content after the
// declaration of the heredoc can be parsed.
if (parser->current.end >= parser->end) {
pm_parser_err_heredoc_term(parser, lex_mode);
pm_parser_err_heredoc_term(parser, lex_mode->as.heredoc.ident_start, lex_mode->as.heredoc.ident_length);
parser->next_start = lex_mode->as.heredoc.next_start;
parser->heredoc_end = parser->current.end;
lex_state_set(parser, PM_LEX_STATE_END);
lex_mode_pop(parser);
LEX(PM_TOKEN_HEREDOC_END);
}

Expand Down Expand Up @@ -12582,6 +12580,7 @@ parser_lex(pm_parser_t *parser) {
}

lex_state_set(parser, PM_LEX_STATE_END);
lex_mode_pop(parser);
LEX(PM_TOKEN_HEREDOC_END);
}
}
Expand Down Expand Up @@ -13165,13 +13164,11 @@ expect3(pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_to
* lex mode accordingly.
*/
static void
expect1_heredoc_term(pm_parser_t *parser, pm_lex_mode_t *lex_mode) {
expect1_heredoc_term(pm_parser_t *parser, const uint8_t *ident_start, size_t ident_length) {
if (match1(parser, PM_TOKEN_HEREDOC_END)) {
lex_mode_pop(parser);
parser_lex(parser);
} else {
pm_parser_err_heredoc_term(parser, lex_mode);
lex_mode_pop(parser);
pm_parser_err_heredoc_term(parser, ident_start, ident_length);
parser->previous.start = parser->previous.end;
parser->previous.type = PM_TOKEN_MISSING;
}
Expand Down Expand Up @@ -18444,8 +18441,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// list of strings.
pm_lex_mode_t *lex_mode = parser->lex_modes.current;
assert(lex_mode->mode == PM_LEX_HEREDOC);

pm_heredoc_quote_t quote = lex_mode->as.heredoc.quote;
pm_heredoc_indent_t indent = lex_mode->as.heredoc.indent;
const uint8_t *ident_start = lex_mode->as.heredoc.ident_start;
size_t ident_length = lex_mode->as.heredoc.ident_length;

parser_lex(parser);
pm_token_t opening = parser->previous;
Expand All @@ -18456,7 +18456,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (match2(parser, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) {
// If we get here, then we have an empty heredoc. We'll create
// an empty content token and return an empty string node.
expect1_heredoc_term(parser, lex_mode);
expect1_heredoc_term(parser, ident_start, ident_length);
pm_token_t content = parse_strings_empty_content(parser->previous.start);

if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
Expand Down Expand Up @@ -18497,7 +18497,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}

node = (pm_node_t *) cast;
expect1_heredoc_term(parser, lex_mode);
expect1_heredoc_term(parser, ident_start, ident_length);
} else {
// If we get here, then we have multiple parts in the heredoc,
// so we'll need to create an interpolated string node to hold
Expand All @@ -18519,7 +18519,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_interpolated_x_string_node_t *cast = pm_interpolated_xstring_node_create(parser, &opening, &opening);
cast->parts = parts;

expect1_heredoc_term(parser, lex_mode);
expect1_heredoc_term(parser, ident_start, ident_length);
pm_interpolated_xstring_node_closing_set(cast, &parser->previous);

cast->base.location = cast->opening_loc;
Expand All @@ -18528,7 +18528,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_interpolated_string_node_t *cast = pm_interpolated_string_node_create(parser, &opening, &parts, &opening);
pm_node_list_free(&parts);

expect1_heredoc_term(parser, lex_mode);
expect1_heredoc_term(parser, ident_start, ident_length);
pm_interpolated_string_node_closing_set(cast, &parser->previous);

cast->base.location = cast->opening_loc;
Expand Down
9 changes: 9 additions & 0 deletions test/prism/errors/heredoc_unterminated.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
a=>{<<b
^ unterminated heredoc; can't find string "b" anywhere before EOF
^~~ unexpected heredoc beginning; expected a key in the hash pattern
^ unterminated heredoc; can't find string "b" anywhere before EOF
^~~ expected a label as the key in the hash pattern
^ expected a `}` to close the pattern expression
^ unexpected heredoc ending, expecting end-of-input
^ unexpected heredoc ending, ignoring it

0 comments on commit e444d1e

Please sign in to comment.