multi-line string literals
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -11,6 +11,7 @@ Kind :: enum u8 {
|
||||
Integer,
|
||||
Float,
|
||||
String,
|
||||
Multiline_String,
|
||||
Character,
|
||||
Underscore,
|
||||
Colon,
|
||||
|
||||
Reference in New Issue
Block a user