summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--prism/prism.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/prism/prism.c b/prism/prism.c
index 97d47c8985..4107550223 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -16878,6 +16878,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
// start with a single string content node.
pm_string_t unescaped;
pm_token_t content;
+
if (match1(parser, PM_TOKEN_EOF)) {
unescaped = PM_STRING_EMPTY;
content = not_provided(parser);
@@ -16940,7 +16941,19 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) {
if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
pm_node_flag_set(node, parse_unescaped_encoding(parser));
- expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF);
+
+ // Kind of odd behavior, but basically if we have an
+ // unterminated string and it ends in a newline, we back up one
+ // character so that the error message is on the last line of
+ // content in the string.
+ if (!accept1(parser, PM_TOKEN_STRING_END)) {
+ const uint8_t *location = parser->previous.end;
+ if (location > parser->start && location[-1] == '\n') location--;
+ pm_parser_err(parser, location, location, PM_ERR_STRING_LITERAL_EOF);
+
+ parser->previous.start = parser->previous.end;
+ parser->previous.type = PM_TOKEN_MISSING;
+ }
} else if (accept1(parser, PM_TOKEN_LABEL_END)) {
node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true));
} else {