aboutsummaryrefslogtreecommitdiff
path: root/src/z/parser/js/grammar/literal.zig
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2026-08-04 19:02:27 +0200
committerNathan Reiner <nathan@nathanreiner.xyz>2026-08-04 19:02:27 +0200
commita10b091d78208907397a6d49791b27e04e675161 (patch)
treebc695613559f14ce69baeb268bb23414dd05ad7e /src/z/parser/js/grammar/literal.zig
parent0bc6d195195d1e126b535554a4a4105468cd06d9 (diff)
add tokenizer for all other variants
Diffstat (limited to 'src/z/parser/js/grammar/literal.zig')
-rw-r--r--src/z/parser/js/grammar/literal.zig81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/z/parser/js/grammar/literal.zig b/src/z/parser/js/grammar/literal.zig
index a2ef97a..7f92240 100644
--- a/src/z/parser/js/grammar/literal.zig
+++ b/src/z/parser/js/grammar/literal.zig
@@ -1,5 +1,86 @@
+const std = @import("std");
+
+const root = @import("root.zig");
+const Lexer = root.Lexer;
+const Token = root.Token;
+
pub const Literal = enum {
+ // NOTE: currently only decimal literals are tokenized
numeric,
bigint,
string,
+
+ pub inline fn tokenize(comptime lexer: *Lexer) Lexer.Error!void {
+ comptime {
+ errdefer lexer.revert();
+
+ var token = lexer.start(.{ .literal = undefined });
+
+ switch (try lexer.consume()) {
+ '0'...'9', '.' => |c| {
+ token.kind.literal = .numeric;
+
+ var had_period = c == '.';
+
+ while (lexer.peekChar()) |ch| {
+ switch (ch) {
+ '0'...'9' => {},
+ '.' => if (had_period) {
+ return Lexer.Error.UnexpectedToken;
+ } else {
+ had_period = true;
+ },
+ else => return Lexer.Error.UnexpectedToken,
+ }
+
+ try lexer.skip();
+ }
+ },
+ '\'', '"' => |quote| while (try lexer.consume() != quote) {
+ if (quote == '\\') {
+ try lexer.consume();
+ }
+ },
+ else => return Lexer.Error.UnexpectedToken,
+ }
+
+ lexer.commit(token);
+ }
+ }
};
+
+test "numeric" {
+ 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("1234", 4);
+ try Simple.run("1.234", 5);
+ try std.testing.expectError(
+ Lexer.Error.UnexpectedToken,
+ Simple.run("12.3.4", 0),
+ );
+}
+
+test "string" {
+ 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("\"hello\"", 7);
+ try std.testing.expectError(
+ Lexer.Error.EndOfBuffer,
+ Simple.run("'hello", 0),
+ );
+}