aboutsummaryrefslogtreecommitdiff
path: root/src/z/js/parser/lexical_grammar.zig
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2026-07-30 09:36:34 +0200
committerNathan Reiner <nathan@nathanreiner.xyz>2026-07-30 09:36:34 +0200
commitaca38f5c96709f56db75a476051eb644de644d3d (patch)
tree1ce90ccffb80cff8d527be6efbd073031fccd3a1 /src/z/js/parser/lexical_grammar.zig
parent006674d7e08146a9bd980e2138ce9444d2e40e6f (diff)
restructure project
Diffstat (limited to 'src/z/js/parser/lexical_grammar.zig')
-rw-r--r--src/z/js/parser/lexical_grammar.zig1137
1 files changed, 0 insertions, 1137 deletions
diff --git a/src/z/js/parser/lexical_grammar.zig b/src/z/js/parser/lexical_grammar.zig
deleted file mode 100644
index 2211fbe..0000000
--- a/src/z/js/parser/lexical_grammar.zig
+++ /dev/null
@@ -1,1137 +0,0 @@
-const std = @import("std");
-
-const ast = @import("ast.zig");
-pub const Loc = ast.Loc;
-
-pub const TokenType = enum {
- // Keywords
- await,
- @"break",
- case,
- @"catch",
- class,
- @"const",
- @"continue",
- debugger,
- default,
- delete,
- do,
- @"else",
- @"enum",
- @"export",
- extends,
- false,
- finally,
- @"for",
- function,
- @"if",
- import,
- in,
- instanceof,
- let,
- new,
- null,
- @"return",
- super,
- @"switch",
- this,
- throw,
- true,
- @"try",
- typeof,
- @"var",
- void,
- @"while",
- with,
- yield,
- using,
- async,
- static,
- get,
- set,
- of,
-
- // Identifiers and literals
- identifier,
- private_identifier,
- number,
- string,
- bigint,
- regex,
- template_head,
- template_middle,
- template_tail,
- no_sub_template,
-
- // Punctuators
- lbrace,
- rbrace,
- lparen,
- rparen,
- lbracket,
- rbracket,
- dot,
- semicolon,
- comma,
- @"...",
- @"<",
- @">",
- @"<=",
- @">=",
- @"==",
- @"!=",
- @"===",
- @"!==",
- @"+",
- @"-",
- @"*",
- @"%",
- @"**",
- @"++",
- @"--",
- @"<<",
- @">>",
- @">>>",
- @"&",
- @"|",
- @"^",
- @"!",
- @"~",
- @"&&",
- @"||",
- @"??",
- @"?",
- @":",
- @"=",
- @"+=",
- @"-=",
- @"*=",
- @"%=",
- @"**=",
- @"<<=",
- @">>=",
- @">>>=",
- @"&=",
- @"|=",
- @"^=",
- @"&&=",
- @"||=",
- @"??=",
- @"=>",
- @"/",
- @"/=",
- @"?.",
- @".",
- @"#",
-
- // Special
- from,
- eof,
- unknown,
-
- pub fn isKeyword(self: TokenType) bool {
- return switch (self) {
- .await,
- .@"break",
- .case,
- .@"catch",
- .class,
- .@"const",
- .@"continue",
- .debugger,
- .default,
- .delete,
- .do,
- .@"else",
- .@"enum",
- .@"export",
- .extends,
- .false,
- .finally,
- .@"for",
- .function,
- .@"if",
- .import,
- .in,
- .instanceof,
- .let,
- .new,
- .null,
- .@"return",
- .super,
- .@"switch",
- .this,
- .throw,
- .true,
- .@"try",
- .typeof,
- .@"var",
- .void,
- .@"while",
- .with,
- .yield,
- .using,
- .async,
- .static,
- .get,
- .set,
- .of,
- .from,
- => true,
- else => false,
- };
- }
-
- pub fn isIdentifier(self: TokenType) bool {
- return self == .identifier or self.isKeyword();
- }
-
- pub fn isKeywordButNotLet(self: TokenType) bool {
- return self.isKeyword() and self != .let;
- }
-};
-
-pub const Token = struct {
- kind: TokenType,
- loc: Loc,
- slice: []const u8,
-};
-
-pub const Lexer = struct {
- source: []const u8,
- pos: usize,
-
- const Self = @This();
-
- pub fn init(source: []const u8) Self {
- return .{ .source = source, .pos = 0 };
- }
-
- pub fn tokenize(source: []const u8) []const Token {
- var buf: [4096]Token = undefined;
- return tokenizeBuf(source, &buf);
- }
-
- pub fn tokenizeBuf(source: []const u8, tokens: *[4096]Token) []const Token {
- @setEvalBranchQuota(100000);
- var lexer = Self.init(source);
- var count: usize = 0;
-
- while (true) {
- const tok = lexer.next();
- tokens[count] = tok;
- count += 1;
- if (tok.kind == .eof) break;
- if (count >= tokens.len - 1) {
- tokens[count] = .{ .kind = .eof, .loc = .{ .start = lexer.pos, .end = lexer.pos }, .slice = "" };
- break;
- }
- }
-
- return tokens[0..count];
- }
-
- fn ch(self: Self) ?u8 {
- if (self.pos >= self.source.len) return null;
- return self.source[self.pos];
- }
-
- fn chAt(self: Self, offset: usize) ?u8 {
- const idx = self.pos + offset;
- if (idx >= self.source.len) return null;
- return self.source[idx];
- }
-
- fn advance(self: *Self) void {
- if (self.pos < self.source.len) self.pos += 1;
- }
-
- fn isWhiteSpace(c: u8) bool {
- return switch (c) {
- ' ', '\t', 0x0B, 0x0C => true,
- else => false,
- };
- }
-
- fn isLineTerminator(c: u8) bool {
- return switch (c) {
- '\n', '\r' => true,
- else => false,
- };
- }
-
- fn isDigit(c: u8) bool {
- return c >= '0' and c <= '9';
- }
-
- fn isHexDigit(c: u8) bool {
- return switch (c) {
- '0'...'9', 'a'...'f', 'A'...'F' => true,
- else => false,
- };
- }
-
- fn isOctalDigit(c: u8) bool {
- return c >= '0' and c <= '7';
- }
-
- fn isIdStart(c: u8) bool {
- return switch (c) {
- 'a'...'z', 'A'...'Z', '_', '$' => true,
- else => c > 0x7F,
- };
- }
-
- fn isIdContinue(c: u8) bool {
- return isIdStart(c) or isDigit(c) or c == 0x200C or c == 0x200D;
- }
-
- fn skipWhiteSpace(self: *Self) void {
- while (self.ch()) |c| {
- if (isWhiteSpace(c) or isLineTerminator(c)) {
- self.advance();
- } else {
- break;
- }
- }
- }
-
- fn skipSingleLineComment(self: *Self) void {
- self.advance();
- self.advance();
- while (self.ch()) |c| {
- if (isLineTerminator(c)) break;
- self.advance();
- }
- }
-
- fn skipMultiLineComment(self: *Self) void {
- self.advance();
- self.advance();
- while (self.ch()) |c| {
- if (c == '*') {
- if (self.chAt(1)) |n| {
- if (n == '/') {
- self.advance();
- self.advance();
- return;
- }
- }
- }
- self.advance();
- }
- }
-
- fn skipHashbang(self: *Self) void {
- if (self.ch()) |c| {
- if (c == '#') {
- self.advance();
- if (self.ch()) |n| {
- if (n == '!') {
- self.advance();
- while (self.ch()) |c2| {
- if (isLineTerminator(c2)) break;
- self.advance();
- }
- }
- }
- }
- }
- }
-
- fn scanString(self: *Self, quote: u8) Token {
- const start = self.pos;
- self.advance();
-
- while (self.ch()) |c| {
- if (c == quote) {
- self.advance();
- return .{
- .kind = .string,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start + 1 .. self.pos - 1],
- };
- }
- if (c == '\\') {
- self.advance();
- if (self.ch()) |_| self.advance();
- } else if (isLineTerminator(c) and c != 0x2028 and c != 0x2029) {
- break;
- } else {
- self.advance();
- }
- }
-
- return .{
- .kind = .string,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start + 1 .. self.pos],
- };
- }
-
- fn scanTemplate(self: *Self, start_kind: TokenType) Token {
- const start = self.pos;
- if (start_kind == .template_middle or start_kind == .template_head) {
- self.advance();
- }
- return self.scanTemplateRest(start);
- }
-
- fn scanTemplateRest(self: *Self, start: usize) Token {
- while (self.ch()) |c| {
- if (c == '`') {
- self.advance();
- return .{
- .kind = .no_sub_template,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start .. self.pos - 1],
- };
- }
- if (c == '$') {
- if (self.chAt(1)) |n| {
- if (n == '{') {
- self.advance();
- self.advance();
- return .{
- .kind = .template_head,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start .. self.pos - 2],
- };
- }
- }
- }
- if (c == '\\') {
- self.advance();
- if (self.ch()) |_| self.advance();
- } else {
- self.advance();
- }
- }
-
- return .{
- .kind = .no_sub_template,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start..self.pos],
- };
- }
-
- fn scanTemplateMiddleOrTail(self: *Self) Token {
- const start = self.pos;
- self.advance();
-
- while (self.ch()) |c| {
- if (c == '`') {
- self.advance();
- return .{
- .kind = .template_tail,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start .. self.pos - 1],
- };
- }
- if (c == '$') {
- if (self.chAt(1)) |n| {
- if (n == '{') {
- self.advance();
- self.advance();
- return .{
- .kind = .template_middle,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start .. self.pos - 2],
- };
- }
- }
- }
- if (c == '\\') {
- self.advance();
- if (self.ch()) |_| self.advance();
- } else {
- self.advance();
- }
- }
-
- return .{
- .kind = .template_tail,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start..self.pos],
- };
- }
-
- fn scanNumber(self: *Self) Token {
- const start = self.pos;
-
- if (self.ch()) |c| {
- if (c == '0') {
- self.advance();
- if (self.ch()) |n| {
- switch (n) {
- 'x', 'X' => return self.scanHex(start),
- 'b', 'B' => return self.scanBinary(start),
- 'o', 'O' => return self.scanOctal(start),
- 'n' => {
- self.advance();
- return .{
- .kind = .bigint,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start .. self.pos - 1],
- };
- },
- 'e', 'E' => return self.scanDecimalAfterInt(start),
- '.', '0'...'9' => return self.scanDecimalAfterInt(start),
- else => {},
- }
- }
- }
- }
-
- return self.scanDecimal(start);
- }
-
- fn scanDecimal(self: *Self, start: usize) Token {
- while (self.ch()) |c| {
- if (!isDigit(c) and c != '_') break;
- self.advance();
- }
-
- if (self.ch()) |c| {
- if (c == '.') {
- self.advance();
- while (self.ch()) |c2| {
- if (!isDigit(c2) and c2 != '_') break;
- self.advance();
- }
- }
- if (self.ch()) |c2| {
- if (c2 == 'e' or c2 == 'E') {
- return self.scanExponent(start);
- }
- }
- if (self.ch()) |c2| {
- if (c2 == 'n') {
- self.advance();
- return .{
- .kind = .bigint,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start .. self.pos - 1],
- };
- }
- }
- }
-
- return .{
- .kind = .number,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start..self.pos],
- };
- }
-
- fn scanDecimalAfterInt(self: *Self, start: usize) Token {
- while (self.ch()) |c| {
- if (!isDigit(c) and c != '_') break;
- self.advance();
- }
- if (self.ch()) |c| {
- if (c == '.') {
- self.advance();
- while (self.ch()) |c2| {
- if (!isDigit(c2) and c2 != '_') break;
- self.advance();
- }
- }
- if (self.ch()) |c2| {
- if (c2 == 'e' or c2 == 'E') {
- return self.scanExponent(start);
- }
- }
- if (self.ch()) |c2| {
- if (c2 == 'n') {
- self.advance();
- return .{
- .kind = .bigint,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start .. self.pos - 1],
- };
- }
- }
- }
- return .{
- .kind = .number,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start..self.pos],
- };
- }
-
- fn scanExponent(self: *Self, start: usize) Token {
- self.advance();
- if (self.ch()) |c| {
- if (c == '+' or c == '-') self.advance();
- }
- while (self.ch()) |c| {
- if (!isDigit(c) and c != '_') break;
- self.advance();
- }
- return .{
- .kind = .number,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start..self.pos],
- };
- }
-
- fn scanHex(self: *Self, start: usize) Token {
- self.advance();
- while (self.ch()) |c| {
- if (!isHexDigit(c) and c != '_') break;
- self.advance();
- }
- if (self.ch()) |c| {
- if (c == 'n') {
- self.advance();
- return .{
- .kind = .bigint,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start .. self.pos - 1],
- };
- }
- }
- return .{
- .kind = .number,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start..self.pos],
- };
- }
-
- fn scanBinary(self: *Self, start: usize) Token {
- self.advance();
- while (self.ch()) |c| {
- if (c != '0' and c != '1' and c != '_') break;
- self.advance();
- }
- if (self.ch()) |c| {
- if (c == 'n') {
- self.advance();
- return .{
- .kind = .bigint,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start .. self.pos - 1],
- };
- }
- }
- return .{
- .kind = .number,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start..self.pos],
- };
- }
-
- fn scanOctal(self: *Self, start: usize) Token {
- self.advance();
- while (self.ch()) |c| {
- if (!isOctalDigit(c) and c != '_') break;
- self.advance();
- }
- if (self.ch()) |c| {
- if (c == 'n') {
- self.advance();
- return .{
- .kind = .bigint,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start .. self.pos - 1],
- };
- }
- }
- return .{
- .kind = .number,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start..self.pos],
- };
- }
-
- fn scanIdentifierOrKeyword(self: *Self) Token {
- const start = self.pos;
- while (self.ch()) |c| {
- if (!isIdContinue(c)) break;
- self.advance();
- }
-
- const slice = self.source[start..self.pos];
- const kind = keywordFromString(slice);
-
- return .{
- .kind = kind,
- .loc = .{ .start = start, .end = self.pos },
- .slice = slice,
- };
- }
-
- fn scanPrivateIdentifier(self: *Self) Token {
- const start = self.pos;
- self.advance();
- while (self.ch()) |c| {
- if (!isIdContinue(c)) break;
- self.advance();
- }
- return .{
- .kind = .private_identifier,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start..self.pos],
- };
- }
-
- fn scanRegex(self: *Self) Token {
- const start = self.pos;
- self.advance();
-
- var in_class = false;
- while (self.ch()) |c| {
- if (c == '\\') {
- self.advance();
- if (self.ch()) |_| self.advance();
- } else if (c == '[') {
- in_class = true;
- self.advance();
- } else if (c == ']') {
- in_class = false;
- self.advance();
- } else if (c == '/' and !in_class) {
- self.advance();
- break;
- } else if (isLineTerminator(c)) {
- break;
- } else {
- self.advance();
- }
- }
-
- while (self.ch()) |c| {
- if (!isIdContinue(c)) break;
- self.advance();
- }
-
- return .{
- .kind = .regex,
- .loc = .{ .start = start, .end = self.pos },
- .slice = self.source[start..self.pos],
- };
- }
-
- fn scanPunctuator(self: *Self) Token {
- const start = self.pos;
- const c = self.ch().?;
-
- switch (c) {
- '{' => {
- self.advance();
- return simple(.lbrace, start);
- },
- '}' => {
- self.advance();
- return simple(.rbrace, start);
- },
- '(' => {
- self.advance();
- return simple(.lparen, start);
- },
- ')' => {
- self.advance();
- return simple(.rparen, start);
- },
- '[' => {
- self.advance();
- return simple(.lbracket, start);
- },
- ']' => {
- self.advance();
- return simple(.rbracket, start);
- },
- ';' => {
- self.advance();
- return simple(.semicolon, start);
- },
- ',' => {
- self.advance();
- return simple(.comma, start);
- },
- ':' => {
- self.advance();
- return simple(.@":", start);
- },
- '?' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '?') {
- self.advance();
- if (self.ch()) |n2| {
- if (n2 == '=') {
- self.advance();
- return simple(.@"??=", start);
- }
- }
- return simple(.@"??", start);
- }
- if (n == '.') {
- if (self.chAt(1)) |n2| {
- if (!isDigit(n2)) {
- self.advance();
- return simple(.@"?.", start);
- }
- } else {
- self.advance();
- return simple(.@"?.", start);
- }
- }
- }
- return simple(.@"?", start);
- },
- '~' => {
- self.advance();
- return simple(.@"~", start);
- },
- '.' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '.') {
- if (self.chAt(1)) |n2| {
- if (n2 == '.') {
- self.advance();
- self.advance();
- return simple(.@"...", start);
- }
- }
- }
- }
- return simple(.@".", start);
- },
- '#' => {
- self.advance();
- if (self.ch()) |n| {
- if (isIdStart(n)) {
- return self.scanPrivateIdentifier();
- }
- }
- return simple(.@"#", start);
- },
- '+' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '+') {
- self.advance();
- return simple(.@"++", start);
- }
- if (n == '=') {
- self.advance();
- return simple(.@"+=", start);
- }
- }
- return simple(.@"+", start);
- },
- '-' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '-') {
- self.advance();
- return simple(.@"--", start);
- }
- if (n == '=') {
- self.advance();
- return simple(.@"-=", start);
- }
- }
- return simple(.@"-", start);
- },
- '*' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '*') {
- self.advance();
- if (self.ch()) |n2| {
- if (n2 == '=') {
- self.advance();
- return simple(.@"**=", start);
- }
- }
- return simple(.@"**", start);
- }
- if (n == '=') {
- self.advance();
- return simple(.@"*=", start);
- }
- }
- return simple(.@"*", start);
- },
- '%' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '=') {
- self.advance();
- return simple(.@"%=", start);
- }
- }
- return simple(.@"%", start);
- },
- '=' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '=') {
- self.advance();
- if (self.ch()) |n2| {
- if (n2 == '=') {
- self.advance();
- return simple(.@"===", start);
- }
- }
- return simple(.@"==", start);
- }
- if (n == '>') {
- self.advance();
- return simple(.@"=>", start);
- }
- }
- return simple(.@"=", start);
- },
- '!' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '=') {
- self.advance();
- if (self.ch()) |n2| {
- if (n2 == '=') {
- self.advance();
- return simple(.@"!==", start);
- }
- }
- return simple(.@"!=", start);
- }
- }
- return simple(.@"!", start);
- },
- '<' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '<') {
- self.advance();
- if (self.ch()) |n2| {
- if (n2 == '=') {
- self.advance();
- return simple(.@"<<=", start);
- }
- }
- return simple(.@"<<", start);
- }
- if (n == '=') {
- self.advance();
- return simple(.@"<=", start);
- }
- }
- return simple(.@"<", start);
- },
- '>' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '>') {
- self.advance();
- if (self.ch()) |n2| {
- if (n2 == '>') {
- self.advance();
- if (self.ch()) |n3| {
- if (n3 == '=') {
- self.advance();
- return simple(.@">>>=", start);
- }
- }
- return simple(.@">>>", start);
- }
- if (n2 == '=') {
- self.advance();
- return simple(.@">>=", start);
- }
- }
- return simple(.@">>", start);
- }
- if (n == '=') {
- self.advance();
- return simple(.@">=", start);
- }
- }
- return simple(.@">", start);
- },
- '&' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '&') {
- self.advance();
- if (self.ch()) |n2| {
- if (n2 == '=') {
- self.advance();
- return simple(.@"&&=", start);
- }
- }
- return simple(.@"&&", start);
- }
- if (n == '=') {
- self.advance();
- return simple(.@"&=", start);
- }
- }
- return simple(.@"&", start);
- },
- '|' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '|') {
- self.advance();
- if (self.ch()) |n2| {
- if (n2 == '=') {
- self.advance();
- return simple(.@"||=", start);
- }
- }
- return simple(.@"||", start);
- }
- if (n == '=') {
- self.advance();
- return simple(.@"|=", start);
- }
- }
- return simple(.@"|", start);
- },
- '^' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '=') {
- self.advance();
- return simple(.@"^=", start);
- }
- }
- return simple(.@"^", start);
- },
- '`' => {
- self.advance();
- return self.scanTemplateRest(start);
- },
- '\'' => return self.scanString('\''),
- '"' => return self.scanString('"'),
- '/' => {
- self.advance();
- if (self.ch()) |n| {
- if (n == '/') {
- self.skipSingleLineComment();
- return self.next();
- }
- if (n == '*') {
- self.skipMultiLineComment();
- return self.next();
- }
- if (n == '=') {
- self.advance();
- return simple(.@"/=", start);
- }
- }
- return simple(.@"/", start);
- },
- else => {
- if (isLineTerminator(c) or isWhiteSpace(c)) {
- self.skipWhiteSpace();
- return self.next();
- }
- if (isDigit(c)) return self.scanNumber();
- if (isIdStart(c)) return self.scanIdentifierOrKeyword();
- if (c == '\\') {
- self.advance();
- return self.scanIdentifierOrKeyword();
- }
- self.advance();
- return simple(.unknown, start);
- },
- }
- }
-
- fn simple(kind: TokenType, start: usize) Token {
- return .{ .kind = kind, .loc = .{ .start = start, .end = start }, .slice = "" };
- }
-
- fn simpleWithSlice(comptime kind: TokenType, start: usize, slice: []const u8) Token {
- return .{ .kind = kind, .loc = .{ .start = start, .end = start }, .slice = slice };
- }
-
- pub fn next(self: *Self) Token {
- if (self.ch()) |c| {
- _ = c;
- // Handle hashbang at beginning
- if (self.pos == 0) {
- if (self.ch()) |c2| {
- if (c2 == '#') {
- self.skipHashbang();
- return self.next();
- }
- }
- }
- return self.scanPunctuator();
- }
- return simple(.eof, self.pos);
- }
-
- fn keywordFromString(s: []const u8) TokenType {
- const keywords = comptime keywords: {
- const arr = struct {
- const data = [_]struct { key: []const u8, val: TokenType }{
- .{ .key = "await", .val = .await },
- .{ .key = "break", .val = .@"break" },
- .{ .key = "case", .val = .case },
- .{ .key = "catch", .val = .@"catch" },
- .{ .key = "class", .val = .class },
- .{ .key = "const", .val = .@"const" },
- .{ .key = "continue", .val = .@"continue" },
- .{ .key = "debugger", .val = .debugger },
- .{ .key = "default", .val = .default },
- .{ .key = "delete", .val = .delete },
- .{ .key = "do", .val = .do },
- .{ .key = "else", .val = .@"else" },
- .{ .key = "enum", .val = .@"enum" },
- .{ .key = "export", .val = .@"export" },
- .{ .key = "extends", .val = .extends },
- .{ .key = "false", .val = .false },
- .{ .key = "finally", .val = .finally },
- .{ .key = "for", .val = .@"for" },
- .{ .key = "function", .val = .function },
- .{ .key = "if", .val = .@"if" },
- .{ .key = "import", .val = .import },
- .{ .key = "in", .val = .in },
- .{ .key = "instanceof", .val = .instanceof },
- .{ .key = "let", .val = .let },
- .{ .key = "new", .val = .new },
- .{ .key = "null", .val = .null },
- .{ .key = "return", .val = .@"return" },
- .{ .key = "super", .val = .super },
- .{ .key = "switch", .val = .@"switch" },
- .{ .key = "this", .val = .this },
- .{ .key = "throw", .val = .throw },
- .{ .key = "true", .val = .true },
- .{ .key = "try", .val = .@"try" },
- .{ .key = "typeof", .val = .typeof },
- .{ .key = "var", .val = .@"var" },
- .{ .key = "void", .val = .void },
- .{ .key = "while", .val = .@"while" },
- .{ .key = "with", .val = .with },
- .{ .key = "yield", .val = .yield },
- .{ .key = "using", .val = .using },
- .{ .key = "async", .val = .async },
- .{ .key = "static", .val = .static },
- .{ .key = "get", .val = .get },
- .{ .key = "set", .val = .set },
- .{ .key = "of", .val = .of },
- .{ .key = "from", .val = .from },
- };
- };
- break :keywords arr.data;
- };
- inline for (keywords) |entry| {
- if (std.mem.eql(u8, s, entry.key)) return entry.val;
- }
- return .identifier;
- }
-
- pub fn tokenizeComptime(comptime source: []const u8) []const Token {
- comptime {
- return tokenize(source);
- }
- }
-};