diff options
author | jjanzen <jjanzen@jjanzen.ca> | 2025-03-04 20:40:26 -0600 |
---|---|---|
committer | jjanzen <jjanzen@jjanzen.ca> | 2025-03-04 20:40:26 -0600 |
commit | 2ee94b959442f4cf6da73403cfb91a6fbafae452 (patch) | |
tree | b8ba6c8932b7069a9ca10ff8b3df147954600e4a | |
parent | 4af81abcc1c9555011677da25b89061ce6bc605e (diff) |
-rw-r--r-- | src/main.zig | 7 | ||||
-rw-r--r-- | src/parser.zig | 165 |
2 files changed, 94 insertions, 78 deletions
diff --git a/src/main.zig b/src/main.zig index c8a3f67..c7892a0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -15,10 +15,3 @@ pub fn main() !void { try bw.flush(); // don't forget to flush! } - -test "simple test" { - var list = std.ArrayList(i32).init(std.testing.allocator); - defer list.deinit(); // try commenting this out and see if zig detects the memory leak! - try list.append(42); - try std.testing.expectEqual(@as(i32, 42), list.pop()); -} diff --git a/src/parser.zig b/src/parser.zig index 51ea0ac..08466ad 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -1,36 +1,6 @@ const std = @import("std"); const opcodes = @import("opcodes.zig"); -/// A number's value can be pure or point to a register -const NumberType = enum { - pure, - register, -}; -const NumberValue = union(NumberType) { - pure: u64, - register: u8, -}; - -/// An expression's result can be a NumberValue or a string -const ExpressionResultType = enum { - number, - string, -}; -const ExpressionResult = union(ExpressionResultType) { - number: NumberValue, - string: []const u8, -}; - -/// A constant can be a number of a string -const ConstantType = enum { - number, - string, -}; -const ConstantValue = union(ConstantType) { - number: u64, - string: []const u8, -}; - /// The Parser reads a provided input and assembles it into MMIX object code pub const Parser = struct { allocator: std.mem.Allocator, @@ -84,6 +54,16 @@ pub const Parser = struct { } } + /// A number's value can be pure or point to a register + const NumberType = enum { + pure, + register, + }; + const NumberValue = union(NumberType) { + pure: u64, + register: u8, + }; + const DecimalError = std.fmt.ParseIntError; /// Determine whether the cursor points at a valid integer in base 10 @@ -213,6 +193,16 @@ pub const Parser = struct { UnexpectedSymbol, }; + /// A constant can be a number of a string + const ConstantType = enum { + number, + string, + }; + const ConstantValue = union(ConstantType) { + number: u64, + string: []const u8, + }; + /// Determine whether the cursor points at a valid constant /// The constant may be a string or a number /// Move the cursor past the constant and return it @@ -321,6 +311,16 @@ pub const Parser = struct { FractionalDivisionOversizedNumerator, }; + /// An expression's result can be a NumberValue or a string + const ExpressionResultType = enum { + number, + string, + }; + const ExpressionResult = union(ExpressionResultType) { + number: NumberValue, + string: []const u8, + }; + /// Determine whether the cursor points at a valid expression /// Move the cursor past the expression, evaluate it, and return its value fn identifyExpression(self: *Parser) ExpressionError!ExpressionResult { @@ -616,6 +616,19 @@ pub const Parser = struct { return opcodes.parseOp(self.allocator, self.input[start..end]); } + const LineContents = struct { + allocator: std.mem.Allocator, + symbol_text: ?[]const u8, + opcode: opcodes.Operation, + expressions: std.ArrayList(?ExpressionResult), + unresolved_expressions: std.AutoHashMap(usize, u4), + }; + + fn identifyLine(self: *Parser) !LineContents { + _ = self; + return error.NotImplemented; + } + pub fn init(allocator: std.mem.Allocator, input: []const u8) !Parser { var p = Parser{ .allocator = allocator, @@ -626,6 +639,7 @@ pub const Parser = struct { .object = std.ArrayList(u8).init(allocator), }; + // Populate the symbol table with backwards references try p.symbols.put("0B", NumberValue{ .pure = 0 }); try p.symbols.put("1B", NumberValue{ .pure = 0 }); try p.symbols.put("2B", NumberValue{ .pure = 0 }); @@ -646,6 +660,15 @@ pub const Parser = struct { } }; +// ===========================================================================// +// _____ _____ _____ _____ _____ // +// |_ _| ___/ ___|_ _/ ___| // +// | | | |__ \ `--. | | \ `--. // +// | | | __| `--. \ | | `--. \ // +// | | | |___/\__/ / | | /\__/ / // +// \_/ \____/\____/ \_/ \____/ // +// ===========================================================================// + test "normal ascii characters are recognized as symbol chars" { const chars = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM_"; @@ -941,11 +964,11 @@ test "constants are recognized" { "\"hello \"world", }; - const expected = [_]ConstantValue{ - ConstantValue{ .number = 1234567890 }, - ConstantValue{ .number = 0x1234567890abcdef }, - ConstantValue{ .number = 'a' }, - ConstantValue{ .string = "hello " }, + const expected = [_]Parser.ConstantValue{ + Parser.ConstantValue{ .number = 1234567890 }, + Parser.ConstantValue{ .number = 0x1234567890abcdef }, + Parser.ConstantValue{ .number = 'a' }, + Parser.ConstantValue{ .string = "hello " }, }; for (0..4) |i| { @@ -992,15 +1015,15 @@ test "basic primaries are identified" { "$123", }; - const expected = [_]ExpressionResult{ - ExpressionResult{ .number = NumberValue{ .pure = 1234 } }, - ExpressionResult{ .number = NumberValue{ .pure = 0 } }, - ExpressionResult{ .number = NumberValue{ .pure = 'a' } }, - ExpressionResult{ .string = "hello world" }, - ExpressionResult{ .number = NumberValue{ .pure = 1234 } }, - ExpressionResult{ .number = NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } }, - ExpressionResult{ .number = NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } }, - ExpressionResult{ .number = NumberValue{ .register = 123 } }, + const expected = [_]Parser.ExpressionResult{ + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 1234 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 'a' } }, + Parser.ExpressionResult{ .string = "hello world" }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 1234 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .register = 123 } }, }; for (0..test_cases.len) |i| { @@ -1048,16 +1071,16 @@ test "valid terms are recognized" { "\"hello\"", }; - const expected = [_]ExpressionResult{ - ExpressionResult{ .number = NumberValue{ .pure = 408 } }, - ExpressionResult{ .number = NumberValue{ .pure = 11 } }, - ExpressionResult{ .number = NumberValue{ .pure = 12297829382473034410 } }, - ExpressionResult{ .number = NumberValue{ .pure = 1 } }, - ExpressionResult{ .number = NumberValue{ .pure = 4 } }, - ExpressionResult{ .number = NumberValue{ .pure = 1 } }, - ExpressionResult{ .number = NumberValue{ .pure = 0xAA } }, - ExpressionResult{ .number = NumberValue{ .register = 12 } }, - ExpressionResult{ .string = "hello" }, + const expected = [_]Parser.ExpressionResult{ + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 408 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 11 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 12297829382473034410 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 1 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 4 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 1 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xAA } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .register = 12 } }, + Parser.ExpressionResult{ .string = "hello" }, }; for (0..test_cases.len) |i| { @@ -1079,10 +1102,10 @@ test "terms compute the entire chain" { "3*3%8<<2>>1", }; - const expected = [_]ExpressionResult{ - ExpressionResult{ .number = NumberValue{ .pure = 120 } }, - ExpressionResult{ .number = NumberValue{ .pure = 3 } }, - ExpressionResult{ .number = NumberValue{ .pure = 2 } }, + const expected = [_]Parser.ExpressionResult{ + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 120 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 3 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 2 } }, }; for (0..test_cases.len) |i| { @@ -1140,25 +1163,25 @@ test "expressions are recognized" { "$$12", }; - const expected = [_]ExpressionResult{ - ExpressionResult{ .number = NumberValue{ .pure = 3 } }, - ExpressionResult{ .number = NumberValue{ .pure = 1 } }, - ExpressionResult{ .number = NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } }, - ExpressionResult{ .number = NumberValue{ .pure = 0xAA } }, - ExpressionResult{ .number = NumberValue{ .pure = 0x55 } }, - ExpressionResult{ .number = NumberValue{ .pure = 30 } }, - ExpressionResult{ .number = NumberValue{ .pure = 50 } }, - ExpressionResult{ .number = NumberValue{ .pure = 0xab00000100 } }, - ExpressionResult{ .string = "hello" }, - ExpressionResult{ .number = NumberValue{ .register = 12 } }, - ExpressionResult{ .number = NumberValue{ .register = 12 } }, + const expected = [_]Parser.ExpressionResult{ + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 3 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 1 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xAA } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0x55 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 30 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 50 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xab00000100 } }, + Parser.ExpressionResult{ .string = "hello" }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .register = 12 } }, + Parser.ExpressionResult{ .number = Parser.NumberValue{ .register = 12 } }, }; for (0..test_cases.len) |i| { var parser = try Parser.init(std.testing.allocator, test_cases[i]); defer parser.deinit(); - try parser.symbols.put("k", NumberValue{ .pure = 0xcdef00 }); + try parser.symbols.put("k", Parser.NumberValue{ .pure = 0xcdef00 }); const symbol = try parser.identifyExpression(); |