aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-04-17 15:21:31 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-04-17 15:21:31 -0700
commit025fe36defe2468ca1ed224855aa1effa09001ca (patch)
tree908735f5fedc8cf5a1e668c1112f66a312d8d213 /src
downloadbun-025fe36defe2468ca1ed224855aa1effa09001ca.tar.gz
bun-025fe36defe2468ca1ed224855aa1effa09001ca.tar.zst
bun-025fe36defe2468ca1ed224855aa1effa09001ca.zip
woot
Diffstat (limited to 'src')
-rw-r--r--src/lexer/js_lexer.zig176
-rw-r--r--src/logger/logger.zig103
-rw-r--r--src/main.zig6
3 files changed, 285 insertions, 0 deletions
diff --git a/src/lexer/js_lexer.zig b/src/lexer/js_lexer.zig
new file mode 100644
index 000000000..587ea2caa
--- /dev/null
+++ b/src/lexer/js_lexer.zig
@@ -0,0 +1,176 @@
+const std = @import("std");
+
+pub const T = enum(u8) {
+ t_end_of_file,
+ t_syntax_error,
+
+ // "#!/usr/bin/env node"
+ t_hashbang,
+
+ // literals
+ t_no_substitution_template_literal, // contents are in lexer.string_literal ([]uint16)
+ t_numeric_literal, // contents are in lexer.number (float64)
+ t_string_literal, // contents are in lexer.string_literal ([]uint16)
+ t_big_integer_literal, // contents are in lexer.identifier (string)
+
+ // pseudo-literals
+ t_template_head, // contents are in lexer.string_literal ([]uint16)
+ t_template_middle, // contents are in lexer.string_literal ([]uint16)
+ t_template_tail, // contents are in lexer.string_literal ([]uint16)
+
+ // punctuation
+ t_ampersand,
+ t_ampersand_ampersand,
+ t_asterisk,
+ t_asterisk_asterisk,
+ t_at,
+ t_bar,
+ t_bar_bar,
+ t_caret,
+ t_close_brace,
+ t_close_bracket,
+ t_close_paren,
+ t_colon,
+ t_comma,
+ t_dot,
+ t_dot_dot_dot,
+ t_equals_equals,
+ t_equals_equals_equals,
+ t_equals_greater_than,
+ t_exclamation,
+ t_exclamation_equals,
+ t_exclamation_equals_equals,
+ t_greater_than,
+ t_greater_than_equals,
+ t_greater_than_greater_than,
+ t_greater_than_greater_than_greater_than,
+ t_less_than,
+ t_less_than_equals,
+ t_less_than_less_than,
+ t_minus,
+ t_minus_minus,
+ t_open_brace,
+ t_open_bracket,
+ t_open_paren,
+ t_percent,
+ t_plus,
+ t_plus_plus,
+ t_question,
+ t_question_dot,
+ t_question_question,
+ t_semicolon,
+ t_slash,
+ t_tilde,
+
+ // assignments (keep in sync with is_assign() below)
+ t_ampersand_ampersand_equals,
+ t_ampersand_equals,
+ t_asterisk_asterisk_equals,
+ t_asterisk_equals,
+ t_bar_bar_equals,
+ t_bar_equals,
+ t_caret_equals,
+ t_equals,
+ t_greater_than_greater_than_equals,
+ t_greater_than_greater_than_greater_than_equals,
+ t_less_than_less_than_equals,
+ t_minus_equals,
+ t_percent_equals,
+ t_plus_equals,
+ t_question_question_equals,
+ t_slash_equals,
+
+ // class-private fields and methods
+ t_private_identifier,
+
+ // identifiers
+ t_identifier, // contents are in lexer.identifier (string)
+ t_escaped_keyword, // a keyword that has been escaped as an identifer
+
+ // reserved words
+ t_break,
+ t_case,
+ t_catch,
+ t_class,
+ t_const,
+ t_continue,
+ t_debugger,
+ t_default,
+ t_delete,
+ t_do,
+ t_else,
+ t_enum,
+ t_export,
+ t_extends,
+ t_false,
+ t_finally,
+ t_for,
+ t_function,
+ t_if,
+ t_import,
+ t_in,
+ t_instanceof,
+ t_new,
+ t_null,
+ t_return,
+ t_super,
+ t_switch,
+ t_this,
+ t_throw,
+ t_true,
+ t_try,
+ t_typeof,
+ t_var,
+ t_void,
+ t_while,
+ t_with,
+
+ pub fn isAssign() bool {
+ return self >= T.t_ampersand_ampersand_equals and self <= T.t_slash_equals;
+ }
+
+ pub fn isReservedWord() bool {
+ return self >= T.t_break and self <= T.t_with;
+ }
+};
+
+pub const Keywords = std.ComptimeStringMap(T, .{
+ .{ "break", .t_break },
+ .{ "case", .t_case },
+ .{ "catch", .t_catch },
+ .{ "class", .t_class },
+ .{ "const", .t_const },
+ .{ "continue", .t_continue },
+ .{ "debugger", .t_debugger },
+ .{ "default", .t_default },
+ .{ "delete", .t_delete },
+ .{ "do", .t_do },
+ .{ "else", .t_else },
+ .{ "enum", .t_enum },
+ .{ "export", .t_export },
+ .{ "extends", .t_extends },
+ .{ "false", .t_false },
+ .{ "finally", .t_finally },
+ .{ "for", .t_for },
+ .{ "function", .t_function },
+ .{ "if", .t_if },
+ .{ "import", .t_import },
+ .{ "in", .t_in },
+ .{ "instanceof", .t_instanceof },
+ .{ "new", .t_new },
+ .{ "null", .t_null },
+ .{ "return", .t_return },
+ .{ "super", .t_super },
+ .{ "switch", .t_switch },
+ .{ "this", .t_this },
+ .{ "throw", .t_throw },
+ .{ "true", .t_true },
+ .{ "try", .t_try },
+ .{ "typeof", .t_typeof },
+ .{ "var", .t_var },
+ .{ "void", .t_void },
+ .{ "while", .t_while },
+ .{ "with", .t_with },
+});
+
+const Lexer = struct {};
diff --git a/src/logger/logger.zig b/src/logger/logger.zig
new file mode 100644
index 000000000..8409d767a
--- /dev/null
+++ b/src/logger/logger.zig
@@ -0,0 +1,103 @@
+const std = @import("std");
+
+const expect = std.testing.expect;
+
+const ArrayList = std.ArrayList;
+
+pub const Msg = struct {
+ pub const Kind = enum {
+ err,
+ warn,
+ note,
+ debug,
+
+ pub fn string(self: Kind) []const u8 {
+ return switch (self) {
+ .err => "error",
+ .warn => "warn",
+ .note => "note",
+ .debug => "debug",
+ };
+ }
+ };
+
+ pub const Location = struct {
+ file: []u8,
+ namespace: []u8 = "file",
+ line: i32 = 1, // 1-based
+ column: i32 = 0, // 0-based, in bytes
+ length: u32 = 0, // in bytes
+ line_text: ?[]u8,
+ suggestion: ?[]u8,
+
+ pub fn init(file: []u8, namespace: []u8, line: i32, column: i32, length: u32, line_text: ?[]u8, suggestion: ?[]u8) Location {
+ return Location{
+ .file = file,
+ .namespace = namespace,
+ .line = line,
+ .column = column,
+ .length = length,
+ .line_text = line_text,
+ .suggestion = suggestion,
+ };
+ }
+
+ pub fn init_file(file: []u8, line: i32, column: i32, length: u32, line_text: ?[]u8, suggestion: ?[]u8) Location {
+ var namespace = "file".*;
+ return Location{
+ .file = file,
+ .namespace = &namespace,
+ .line = line,
+ .column = column,
+ .length = length,
+ .line_text = line_text,
+ .suggestion = suggestion,
+ };
+ }
+ };
+
+ pub const Data = struct { text: []u8, location: *Msg.Location };
+
+ kind: Kind,
+ data: Data,
+};
+
+pub const Log = struct {
+ debug: bool = false,
+ warnings: u8 = 0,
+ errors: u8 = 0,
+ msgs: ArrayList(Msg),
+
+ pub fn add_msg(self: *Log, msg: Msg) !void {
+ try self.msgs.append(msg);
+ }
+
+ pub fn print(self: *Log) void {
+ if (self.msgs.items.len > 0) {
+ var msg: Msg = self.msgs.items[0];
+ std.debug.print("\n\n{s}: {s}\n{s}\n{s}:{}:{}", .{ msg.kind.string(), msg.data.text, msg.data.location.line_text, msg.data.location.file, msg.data.location.line, msg.data.location.column });
+ }
+ }
+};
+
+pub const Source = struct { index: u32, contents: []u8,
+// An identifier that is mixed in to automatically-generated symbol names to
+// improve readability. For example, if the identifier is "util" then the
+// symbol for an "export default" statement will be called "util_default".
+identifier_name: []u8 };
+
+test "print msg" {
+ var log = Log{ .msgs = ArrayList(Msg).init(std.testing.allocator) };
+ defer log.msgs.deinit();
+ var filename = "test.js".*;
+ var syntax = "for(i = 0;)".*;
+ var err = "invalid syntax".*;
+ var namespace = "file".*;
+
+ try log.add_msg(Msg{
+ .kind = .err,
+ .data = Msg.Data{ .location = &Msg.Location.init_file(&filename, 1, 3, 0, &syntax, ""), .text = &err },
+ });
+
+ log.print();
+}
diff --git a/src/main.zig b/src/main.zig
new file mode 100644
index 000000000..582427975
--- /dev/null
+++ b/src/main.zig
@@ -0,0 +1,6 @@
+const std = @import("std");
+const lex = @import("lexer/js_lexer.zig");
+
+pub fn main() anyerror!void {
+ std.log.info("All your codebase are belong to us. {s}", .{lex.Keywords.get("hey")});
+}