cleanup
This commit is contained in:
parent
4af81abcc1
commit
2ee94b9594
2 changed files with 94 additions and 78 deletions
|
@ -15,10 +15,3 @@ pub fn main() !void {
|
||||||
|
|
||||||
try bw.flush(); // don't forget to flush!
|
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());
|
|
||||||
}
|
|
||||||
|
|
165
src/parser.zig
165
src/parser.zig
|
@ -1,36 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const opcodes = @import("opcodes.zig");
|
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
|
/// The Parser reads a provided input and assembles it into MMIX object code
|
||||||
pub const Parser = struct {
|
pub const Parser = struct {
|
||||||
allocator: std.mem.Allocator,
|
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;
|
const DecimalError = std.fmt.ParseIntError;
|
||||||
|
|
||||||
/// Determine whether the cursor points at a valid integer in base 10
|
/// Determine whether the cursor points at a valid integer in base 10
|
||||||
|
@ -213,6 +193,16 @@ pub const Parser = struct {
|
||||||
UnexpectedSymbol,
|
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
|
/// Determine whether the cursor points at a valid constant
|
||||||
/// The constant may be a string or a number
|
/// The constant may be a string or a number
|
||||||
/// Move the cursor past the constant and return it
|
/// Move the cursor past the constant and return it
|
||||||
|
@ -321,6 +311,16 @@ pub const Parser = struct {
|
||||||
FractionalDivisionOversizedNumerator,
|
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
|
/// Determine whether the cursor points at a valid expression
|
||||||
/// Move the cursor past the expression, evaluate it, and return its value
|
/// Move the cursor past the expression, evaluate it, and return its value
|
||||||
fn identifyExpression(self: *Parser) ExpressionError!ExpressionResult {
|
fn identifyExpression(self: *Parser) ExpressionError!ExpressionResult {
|
||||||
|
@ -616,6 +616,19 @@ pub const Parser = struct {
|
||||||
return opcodes.parseOp(self.allocator, self.input[start..end]);
|
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 {
|
pub fn init(allocator: std.mem.Allocator, input: []const u8) !Parser {
|
||||||
var p = Parser{
|
var p = Parser{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
|
@ -626,6 +639,7 @@ pub const Parser = struct {
|
||||||
.object = std.ArrayList(u8).init(allocator),
|
.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("0B", NumberValue{ .pure = 0 });
|
||||||
try p.symbols.put("1B", NumberValue{ .pure = 0 });
|
try p.symbols.put("1B", NumberValue{ .pure = 0 });
|
||||||
try p.symbols.put("2B", 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" {
|
test "normal ascii characters are recognized as symbol chars" {
|
||||||
const chars = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM_";
|
const chars = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM_";
|
||||||
|
|
||||||
|
@ -941,11 +964,11 @@ test "constants are recognized" {
|
||||||
"\"hello \"world",
|
"\"hello \"world",
|
||||||
};
|
};
|
||||||
|
|
||||||
const expected = [_]ConstantValue{
|
const expected = [_]Parser.ConstantValue{
|
||||||
ConstantValue{ .number = 1234567890 },
|
Parser.ConstantValue{ .number = 1234567890 },
|
||||||
ConstantValue{ .number = 0x1234567890abcdef },
|
Parser.ConstantValue{ .number = 0x1234567890abcdef },
|
||||||
ConstantValue{ .number = 'a' },
|
Parser.ConstantValue{ .number = 'a' },
|
||||||
ConstantValue{ .string = "hello " },
|
Parser.ConstantValue{ .string = "hello " },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (0..4) |i| {
|
for (0..4) |i| {
|
||||||
|
@ -992,15 +1015,15 @@ test "basic primaries are identified" {
|
||||||
"$123",
|
"$123",
|
||||||
};
|
};
|
||||||
|
|
||||||
const expected = [_]ExpressionResult{
|
const expected = [_]Parser.ExpressionResult{
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 1234 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 1234 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 0 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 'a' } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 'a' } },
|
||||||
ExpressionResult{ .string = "hello world" },
|
Parser.ExpressionResult{ .string = "hello world" },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 1234 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 1234 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } },
|
||||||
ExpressionResult{ .number = NumberValue{ .register = 123 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .register = 123 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (0..test_cases.len) |i| {
|
for (0..test_cases.len) |i| {
|
||||||
|
@ -1048,16 +1071,16 @@ test "valid terms are recognized" {
|
||||||
"\"hello\"",
|
"\"hello\"",
|
||||||
};
|
};
|
||||||
|
|
||||||
const expected = [_]ExpressionResult{
|
const expected = [_]Parser.ExpressionResult{
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 408 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 408 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 11 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 11 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 12297829382473034410 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 12297829382473034410 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 1 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 1 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 4 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 4 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 1 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 1 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 0xAA } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xAA } },
|
||||||
ExpressionResult{ .number = NumberValue{ .register = 12 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .register = 12 } },
|
||||||
ExpressionResult{ .string = "hello" },
|
Parser.ExpressionResult{ .string = "hello" },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (0..test_cases.len) |i| {
|
for (0..test_cases.len) |i| {
|
||||||
|
@ -1079,10 +1102,10 @@ test "terms compute the entire chain" {
|
||||||
"3*3%8<<2>>1",
|
"3*3%8<<2>>1",
|
||||||
};
|
};
|
||||||
|
|
||||||
const expected = [_]ExpressionResult{
|
const expected = [_]Parser.ExpressionResult{
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 120 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 120 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 3 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 3 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 2 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 2 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (0..test_cases.len) |i| {
|
for (0..test_cases.len) |i| {
|
||||||
|
@ -1140,25 +1163,25 @@ test "expressions are recognized" {
|
||||||
"$$12",
|
"$$12",
|
||||||
};
|
};
|
||||||
|
|
||||||
const expected = [_]ExpressionResult{
|
const expected = [_]Parser.ExpressionResult{
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 3 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 3 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 1 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 1 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xFFFFFFFFFFFFFFFF } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 0xAA } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xAA } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 0x55 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0x55 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 30 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 30 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 50 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 50 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .pure = 0xab00000100 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .pure = 0xab00000100 } },
|
||||||
ExpressionResult{ .string = "hello" },
|
Parser.ExpressionResult{ .string = "hello" },
|
||||||
ExpressionResult{ .number = NumberValue{ .register = 12 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .register = 12 } },
|
||||||
ExpressionResult{ .number = NumberValue{ .register = 12 } },
|
Parser.ExpressionResult{ .number = Parser.NumberValue{ .register = 12 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (0..test_cases.len) |i| {
|
for (0..test_cases.len) |i| {
|
||||||
var parser = try Parser.init(std.testing.allocator, test_cases[i]);
|
var parser = try Parser.init(std.testing.allocator, test_cases[i]);
|
||||||
defer parser.deinit();
|
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();
|
const symbol = try parser.identifyExpression();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue