aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--src/main.zig47
-rw-r--r--src/parse.zig27
-rw-r--r--test.hgn15
4 files changed, 49 insertions, 41 deletions
diff --git a/.gitignore b/.gitignore
index db3cb54..ae38ac6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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)