diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/main.zig | 47 | ||||
-rw-r--r-- | src/parse.zig | 27 | ||||
-rw-r--r-- | test.hgn | 15 |
4 files changed, 49 insertions, 41 deletions
@@ -1,2 +1,3 @@ /.zig-cache/ /zig-out/ +*.elf diff --git a/src/main.zig b/src/main.zig index 367edf8..5873c66 100644 --- a/src/main.zig +++ b/src/main.zig @@ -14,45 +14,26 @@ pub fn main() !void { var args = std.process.args(); _ = args.next(); + const in_path = args.next(); + const in_file = if (in_path) |path| + try std.fs.cwd().openFile(path, .{}) + else + std.io.getStdIn(); + const out_path = args.next(); const out_file = if (out_path) |path| try std.fs.cwd().createFile(path, .{ .mode = 0o777 }) else std.io.getStdOut(); + const run = if (args.next()) |arg| std.mem.eql(u8, arg, "run") else false; - // var br = std.io.bufferedReader(std.io.getStdIn().reader()); - // const stdin = br.reader(); - // - // var line: std.ArrayList(u8) = .init(alloc); - // defer line.deinit(); - // while (true) { - // try stdin.streamUntilDelimiter(line.writer(), '\n', null); - // - // const lexer = Lexer{.source = line}; - // - // try stdout.print("{s}\n", .{line.items}); - // } + const source = try in_file.readToEndAlloc( + allocator, + 640 * 1024, // ought to be enough for anyone + ); + defer allocator.free(source); - const source = - \\{ - \\ let x = 10 - \\ let y = 0 - \\ print(x > y) - \\ while y < 3 { - \\ x = x + x - \\ y = y + 1 - \\ } - \\ if x { - \\ # let x = read_int(0) - \\ # print(18446744073709551615) - \\ x = x + x - \\ } else { - \\ x = 69 - \\ } - \\ print(x) - \\} - ; var lexer: Lexer = .{ .source = source }; std.debug.print("Tokens:\n", .{}); while (true) { @@ -61,7 +42,7 @@ pub fn main() !void { if (token.type == .eof) break; } lexer = .{ .source = source }; - const ast = try parse.block(allocator, &lexer); + const ast = try parse.file(allocator, &lexer); std.debug.print("Parse tree:\n{}\n", .{parse.fmt(ast, source, 0)}); if (lexer.peek().type != .eof) { std.debug.print("Unexpected token {}, expected end of file\n", .{lexer.next()}); @@ -81,7 +62,7 @@ pub fn main() !void { else &.{ "qemu-riscv64", out_path.? }, ); - std.debug.print("{}\n{any}\n", .{err, @errorReturnTrace()}); + std.debug.print("{}\n{any}\n", .{ err, @errorReturnTrace() }); } } diff --git a/src/parse.zig b/src/parse.zig index efb5c8e..26f32e9 100644 --- a/src/parse.zig +++ b/src/parse.zig @@ -151,7 +151,18 @@ pub const Expr = struct { const ParseError = error{ OutOfMemory, ExpectedRightParen, UnexpectedToken, InvalidAssignTarget }; -pub fn block(allocator: Allocator, lexer: *Lexer) !Block { +pub fn file(allocator: Allocator, lexer: *Lexer) !Block { + var stmts: std.ArrayList(Stmt) = .init(allocator); + while (lexer.peek().type != .eof) { + try stmts.append(try statement(allocator, lexer)); + } + return .{ + .loc = stmts.items[0].loc.combine(stmts.getLast().loc), + .stmts = try stmts.toOwnedSlice(), + }; +} + +fn block(allocator: Allocator, lexer: *Lexer) !Block { const left_curly = try mustEat(lexer, .left_curly); var stmts: std.ArrayList(Stmt) = .init(allocator); while (lexer.peek().type != .right_curly) { @@ -164,7 +175,7 @@ pub fn block(allocator: Allocator, lexer: *Lexer) !Block { }; } -pub fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt { +fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt { switch (lexer.peek().type) { .let => { const let = lexer.next(); @@ -217,11 +228,11 @@ pub fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt { } } -pub fn expression(allocator: Allocator, lexer: *Lexer) ParseError!*Expr { +fn expression(allocator: Allocator, lexer: *Lexer) ParseError!*Expr { return parseComparisons(allocator, lexer); } -pub fn parseComparisons(allocator: Allocator, lexer: *Lexer) ParseError!*Expr { +fn parseComparisons(allocator: Allocator, lexer: *Lexer) ParseError!*Expr { const lhs = try parseTerms(allocator, lexer); const op: Expr.Type.BinOp.Op = switch (lexer.peek().type) { @@ -240,7 +251,7 @@ pub fn parseComparisons(allocator: Allocator, lexer: *Lexer) ParseError!*Expr { }); } -pub fn parseTerms(allocator: Allocator, lexer: *Lexer) !*Expr { +fn parseTerms(allocator: Allocator, lexer: *Lexer) !*Expr { var lhs = try parseIf(allocator, lexer); while (true) { const op: Expr.Type.BinOp.Op = switch (lexer.peek().type) { @@ -259,7 +270,7 @@ pub fn parseTerms(allocator: Allocator, lexer: *Lexer) !*Expr { return lhs; } -pub fn parseIf(allocator: Allocator, lexer: *Lexer) !*Expr { +fn parseIf(allocator: Allocator, lexer: *Lexer) !*Expr { switch (lexer.peek().type) { .@"if" => { const @"if" = lexer.next(); @@ -282,7 +293,7 @@ pub fn parseIf(allocator: Allocator, lexer: *Lexer) !*Expr { } } -pub fn parseInvocations(allocator: Allocator, lexer: *Lexer) !*Expr { +fn parseInvocations(allocator: Allocator, lexer: *Lexer) !*Expr { var proc = try parsePrimaryExpr(allocator, lexer); while (true) { if (lexer.peek().type != .left_paren) break; @@ -297,7 +308,7 @@ pub fn parseInvocations(allocator: Allocator, lexer: *Lexer) !*Expr { return proc; } -pub fn parsePrimaryExpr(allocator: Allocator, lexer: *Lexer) !*Expr { +fn parsePrimaryExpr(allocator: Allocator, lexer: *Lexer) !*Expr { const token = lexer.next(); return allocate(Expr, allocator, switch (token.type) { .left_paren => { diff --git a/test.hgn b/test.hgn new file mode 100644 index 0000000..2aec1a8 --- /dev/null +++ b/test.hgn @@ -0,0 +1,15 @@ +let x = 10 +let y = 0 +print(x > y) +while y < 3 { + x = x + x + y = y + 1 +} +if x { + # let x = read_int(0) + # print(18446744073709551615) + x = x + x +} else { + x = 69 +} +print(x) |