From 0eaa2a420cb699cdb23ce9b1573560a5d9e59a31 Mon Sep 17 00:00:00 2001 From: Nathan Reiner Date: Wed, 5 Aug 2026 09:08:24 +0200 Subject: add regex literals --- src/z/parser/js/grammar/literal.zig | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) (limited to 'src/z/parser/js/grammar/literal.zig') 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); +} -- cgit v1.2.3-70-g09d2