diff --git a/src/main.zig b/src/main.zig index 128820d..9280494 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,5 +1,78 @@ const std = @import("std"); -pub fn main() anyerror!void { - std.debug.warn("All your base are belong to us.\n"); +const Allocator = std.mem.Allocator; + +pub const Result = error{ + Ok, + CompileError, +}; + +fn run(allocator: *Allocator, data: []u8) !void { + var stdout_file = try std.io.getStdOut(); + const stdout = &stdout_file.outStream().stream; + return Result.Ok; +} + +fn runFile(allocator: *Allocator, path: []const u8) !void { + var file = try std.fs.File.openRead(path); + defer file.close(); + + const total_bytes = try file.getEndPos(); + + var slice = try allocator.alloc(u8, total_bytes); + _ = try file.read(slice); + + run(allocator, slice) catch |err| { + switch (err) { + Result.Ok => {}, + Result.CompileError => std.os.exit(65), + else => return err, + } + }; +} + +fn runPrompt(allocator: *Allocator) !void { + var stdout_file = try std.io.getStdOut(); + const stdout = &stdout_file.outStream().stream; + + while (true) { + try stdout.print("> "); + var buffer = try std.Buffer.init(allocator, ""[0..]); + + var line = std.io.readLine(&buffer) catch |err| { + if (err == error.EndOfStream) return; + return err; + }; + + run(allocator, line) catch |err| { + switch (err) { + Result.Ok => {}, + Result.CompileError => blk: { + try stdout.print("compile error.\n"); + }, + else => return err, + } + }; + } +} + +pub fn main() anyerror!void { + var da = std.heap.DirectAllocator.init(); + var arena = std.heap.ArenaAllocator.init(&da.allocator); + defer arena.deinit(); + var allocator = &arena.allocator; + + var stdout_file = try std.io.getStdOut(); + var stdout = &stdout_file.outStream().stream; + + var args_it = std.process.args(); + + _ = args_it.next(allocator); + + var filePath = try (args_it.next(allocator) orelse { + try runPrompt(allocator); + return; + }); + + try runFile(allocator, filePath); } diff --git a/src/scanner.zig b/src/scanner.zig new file mode 100644 index 0000000..e2b7682 --- /dev/null +++ b/src/scanner.zig @@ -0,0 +1,31 @@ +const std = @import("std"); +const tokens = @import("tokens.std"); + +const Allocator = std.mem.Allocator; + +pub const TokenError = error{ + Unexpected, + Unterminated, +}; + +fn isDigit(char: u8) bool { + return char >= '0' and char <= '9'; +} + +fn isAlpha(c: u8) bool { + return (c >= 'a' and c <= 'z') or + (c >= 'A' and c <= 'Z') or + c == '_'; +} + +fn isAlphaNumeric(char: u8) bool { + return isAlpha(char) or isDigit(char); +} + +pub const Scanner = struct { + allocator: *Allocator, + + pub fn init(allocator: *Allocator) Scanner { + return Scanner{ .allocator = allocator }; + } +}; diff --git a/src/tokens.zig b/src/tokens.zig new file mode 100644 index 0000000..fb0a6e7 --- /dev/null +++ b/src/tokens.zig @@ -0,0 +1,73 @@ +pub const TokenType = enum { + // basic tokens + LeftParen, + RightParen, + LeftBrace, + RightBrace, + LeftSquare, + RightSquare, + Dot, + Equal, + Semicolon, + Comma, + Colon, + Ampersand, + Pipe, + QuestionMark, + DollarSign, + + // math operators + Plus, + Minus, + Star, + Slash, + Modulo, + + // one-two char tokens + DotEqual, + LeftDoubleChevron, // AKA "<<" + PlusPlus, + PlusEqual, + MinusEqual, + + LessThan, + LessEqual, + GreaterThan, + GreaterEqual, + Bang, + BangEqual, + + // complex types + Integer, + Float, + String, + Identifier, + + // keywords + Break, + Const, + Continue, + Defer, + Else, + Enum, + Fn, + For, + Go, + Goto, + If, + Import, + In, + Interface, + Match, + Module, + Mut, + Or, + Return, + Struct, + Type, +}; + +pub const Token = struct { + ttype: TokenType, + lexeme: []u8, +};