multi-line string literals

This commit is contained in:
2026-06-26 22:53:49 +02:00
parent f2ed0b4c4f
commit f926bbc605
5 changed files with 117 additions and 16 deletions
+28
View File
@@ -277,6 +277,34 @@ lex :: proc(
)
append_token(&stream, source_file, .Invalid, start, cursor, diagnostic=id)
}
case '`':
// Multi-line string: each line is marked with a leading '`'; raw
// content (no escapes) runs to end of line. Consecutive backtick
// lines collapse into one token; the trailing '\n' is left to
// become the statement-terminating Newline.
start := cursor
content_end := cursor
for {
cursor += 1 // skip backtick
for cursor < len(bytes) && bytes[cursor] != '\n' {
cursor += 1
}
content_end = cursor
look := cursor
if look < len(bytes) && bytes[look] == '\n' {
look += 1
}
for look < len(bytes) && (bytes[look] == ' ' || bytes[look] == '\t') {
look += 1
}
if look < len(bytes) && bytes[look] == '`' {
cursor = look
continue
}
break
}
cursor = content_end
append_token(&stream, source_file, .Multiline_String, start, content_end)
case ';':
append_token(&stream, source_file, .Semicolon, cursor, cursor+1)
cursor += 1
+29 -2
View File
@@ -560,9 +560,9 @@ parse_primary :: proc(parser: ^Parser, nesting: int) -> ast.Expr_Id {
right=ast.INVALID_EXPR,
diagnostic=source.INVALID_DIAGNOSTIC,
})
case .String:
case .String, .Multiline_String:
advance(parser)
value := decode_import_path(parser, tok)
value := decode_import_path(parser, tok) if tok.kind == .String else decode_multiline_string(parser, tok)
id := u64(len(parser.module.strings))
append(&parser.module.strings, value)
return add_expr(parser, ast.Expr{
@@ -1690,6 +1690,33 @@ decode_import_path :: proc(parser: ^Parser, tok: token.Token) -> string {
return fmt.aprintf("%s", strings.to_string(builder), allocator=parser.module.allocator)
}
decode_multiline_string :: proc(parser: ^Parser, tok: token.Token) -> string {
text := token_text(parser, tok)
builder := strings.builder_make(parser.module.allocator)
defer strings.builder_destroy(&builder)
first := true
index := 0
for index < len(text) {
for index < len(text) && (text[index] == ' ' || text[index] == '\t') {
index += 1
}
if index >= len(text) || text[index] != '`' {
break
}
index += 1 // skip backtick
if !first {
strings.write_byte(&builder, '\n')
}
first = false
for index < len(text) && text[index] != '\n' {
strings.write_byte(&builder, text[index])
index += 1
}
index += 1 // skip newline (terminates this line)
}
return fmt.aprintf("%s", strings.to_string(builder), allocator=parser.module.allocator)
}
parse_import :: proc(parser: ^Parser, alias: token.Token, start: token.Token) {
skip_newlines(parser)
path_token := current(parser)
+1
View File
@@ -11,6 +11,7 @@ Kind :: enum u8 {
Integer,
Float,
String,
Multiline_String,
Character,
Underscore,
Colon,