diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2026-08-05 09:08:24 +0200 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2026-08-05 09:08:24 +0200 |
| commit | 0eaa2a420cb699cdb23ce9b1573560a5d9e59a31 (patch) | |
| tree | 7c33f4be58e47aa6c1641b66442216352fa3f36b /src/z/parser/js/grammar | |
| parent | 356c2bc0ccb1794b5ec219079d8c5b85ddcc4c87 (diff) | |
add regex literals
Diffstat (limited to 'src/z/parser/js/grammar')
| -rw-r--r-- | src/z/parser/js/grammar/identifier.zig | 2 | ||||
| -rw-r--r-- | src/z/parser/js/grammar/keyword.zig | 2 | ||||
| -rw-r--r-- | src/z/parser/js/grammar/literal.zig | 37 | ||||
| -rw-r--r-- | src/z/parser/js/grammar/punctuator.zig | 2 | ||||
| -rw-r--r-- | src/z/parser/js/grammar/root.zig | 1 |
5 files changed, 40 insertions, 4 deletions
diff --git a/src/z/parser/js/grammar/identifier.zig b/src/z/parser/js/grammar/identifier.zig index 905f937..ccc5268 100644 --- a/src/z/parser/js/grammar/identifier.zig +++ b/src/z/parser/js/grammar/identifier.zig @@ -12,6 +12,8 @@ pub const Identifier = enum { comptime { defer lexer.revert(); + lexer.context.regex_possible = false; + const token = tok: { if (lexer.peekChar() == '#') { const t = lexer.start(.{ .identifier = .private }); diff --git a/src/z/parser/js/grammar/keyword.zig b/src/z/parser/js/grammar/keyword.zig index c3b32ac..8e99b4a 100644 --- a/src/z/parser/js/grammar/keyword.zig +++ b/src/z/parser/js/grammar/keyword.zig @@ -72,6 +72,8 @@ pub const Keyword = enum { @setEvalBranchQuota(10000); errdefer lexer.revert(); + lexer.context.regex_possible = true; + const index = std.mem.findNone(u8, lexer.buffer, std.ascii.lowercase) orelse lexer.buffer.len; if (index == 0) return Lexer.Error.UnexpectedToken; diff --git a/src/z/parser/js/grammar/literal.zig b/src/z/parser/js/grammar/literal.zig index 039ebf4..71b990d 100644 --- a/src/z/parser/js/grammar/literal.zig +++ b/src/z/parser/js/grammar/literal.zig @@ -24,6 +24,9 @@ pub const Literal = union(enum) { var token = lexer.start(.{ .literal = undefined }); + const regex_possible = lexer.context.regex_possible; + lexer.context.regex_possible = false; + switch (try lexer.consume()) { '0'...'9', '.' => |c| { const base = if (c != '0') 10 else switch (lexer.peekChar() orelse 0) { @@ -69,7 +72,7 @@ pub const Literal = union(enum) { while (true) { switch (try lexer.consume()) { quote => break, - '\\' => try lexer.consume(), + '\\' => try lexer.skip(), else => {}, } } @@ -83,11 +86,12 @@ pub const Literal = union(enum) { token.kind.literal.template = .whole; break; }, - '\\' => try lexer.consume(), + '\\' => try lexer.skip(), '$' => if (lexer.peekChar() == '{') { lexer.skip() catch unreachable; lexer.context.template_nesting += 1; token.kind.literal.template = .start; + lexer.context.regex_possible = true; break; }, else => {}, @@ -104,17 +108,28 @@ pub const Literal = union(enum) { token.kind.literal.template = .end; break; }, - '\\' => try lexer.consume(), + '\\' => try lexer.skip(), '$' => if (lexer.peekChar() == '{') { lexer.skip() catch unreachable; lexer.context.template_nesting += 1; token.kind.literal.template = .middle; + lexer.context.regex_possible = true; break; }, else => {}, } } - }, + } else return Lexer.Error.UnexpectedToken, + '/' => if (regex_possible) { + while (true) { + switch (try lexer.consume()) { + '/' => break, + '\\' => try lexer.skip(), + '\n' => return Lexer.Error.UnexpectedToken, + else => {}, + } + } + } else return Lexer.Error.UnexpectedToken, else => return Lexer.Error.UnexpectedToken, } @@ -159,3 +174,17 @@ test "string" { Simple.run("'hello", 0), ); } + +test "regex" { + const Simple = struct { + pub fn run(comptime buffer: []const u8, n: usize) !void { + comptime var lexer: Lexer = .init(buffer); + try Literal.tokenize(&lexer); + try std.testing.expectEqual(1, lexer.tokens.len); + try std.testing.expectEqual(n, lexer.tokens[0].slice.len); + } + }; + + try Simple.run("/hello/", 7); + try Simple.run("/some string\\/ here/", 20); +} diff --git a/src/z/parser/js/grammar/punctuator.zig b/src/z/parser/js/grammar/punctuator.zig index 4fd5d16..b085ce1 100644 --- a/src/z/parser/js/grammar/punctuator.zig +++ b/src/z/parser/js/grammar/punctuator.zig @@ -85,6 +85,8 @@ pub const Punctuator = enum { @setEvalBranchQuota(10_000); defer lexer.revert(); + lexer.context.regex_possible = true; + if (punctuatormap.getLongestPrefix(lexer.buffer)) |pair| { if (std.mem.eql(u8, pair.key, "}") and lexer.context.template_nesting > 0) { diff --git a/src/z/parser/js/grammar/root.zig b/src/z/parser/js/grammar/root.zig index 56f3990..f732b7f 100644 --- a/src/z/parser/js/grammar/root.zig +++ b/src/z/parser/js/grammar/root.zig @@ -31,6 +31,7 @@ pub const Grammar = union(enum) { pub const Context = struct { template_nesting: usize = 0, + regex_possible: bool = true, }; pub inline fn tokenize(comptime lexer: *Lexer) Lexer.Error!void { |