diff options
Diffstat (limited to 'src/z/parser/js/grammar/literal.zig')
| -rw-r--r-- | src/z/parser/js/grammar/literal.zig | 63 |
1 files changed, 56 insertions, 7 deletions
diff --git a/src/z/parser/js/grammar/literal.zig b/src/z/parser/js/grammar/literal.zig index 6a91291..039ebf4 100644 --- a/src/z/parser/js/grammar/literal.zig +++ b/src/z/parser/js/grammar/literal.zig @@ -4,11 +4,17 @@ const root = @import("root.zig"); const Lexer = root.Lexer; const Token = root.Token; -pub const Literal = enum { +pub const Literal = union(enum) { // NOTE: currently only decimal literals are tokenized - numeric, - bigint, - string, + numeric: void, + bigint: void, + string: void, + template: enum { + whole, + start, + middle, + end, + }, const digits = "_0123456789abcdef"; @@ -60,9 +66,52 @@ pub const Literal = enum { }, '\'', '"' => |quote| { token.kind.literal = .string; - while (try lexer.consume() != quote) { - if (quote == '\\') { - try lexer.consume(); + while (true) { + switch (try lexer.consume()) { + quote => break, + '\\' => try lexer.consume(), + else => {}, + } + } + }, + '`' => { + token.kind.literal = .{ .template = undefined }; + + while (true) { + switch (try lexer.consume()) { + '`' => { + token.kind.literal.template = .whole; + break; + }, + '\\' => try lexer.consume(), + '$' => if (lexer.peekChar() == '{') { + lexer.skip() catch unreachable; + lexer.context.template_nesting += 1; + token.kind.literal.template = .start; + break; + }, + else => {}, + } + } + }, + '}' => if (lexer.context.template_nesting > 0) { + lexer.context.template_nesting -= 1; + token.kind.literal = .{ .template = undefined }; + + while (true) { + switch (try lexer.consume()) { + '`' => { + token.kind.literal.template = .end; + break; + }, + '\\' => try lexer.consume(), + '$' => if (lexer.peekChar() == '{') { + lexer.skip() catch unreachable; + lexer.context.template_nesting += 1; + token.kind.literal.template = .middle; + break; + }, + else => {}, } } }, |