aboutsummaryrefslogtreecommitdiff
path: root/src/parse.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.zig')
-rw-r--r--src/parse.zig73
1 files changed, 60 insertions, 13 deletions
diff --git a/src/parse.zig b/src/parse.zig
index bd6b000..bd0ca46 100644
--- a/src/parse.zig
+++ b/src/parse.zig
@@ -23,6 +23,25 @@ pub fn fmt(tree: anytype, source: []const u8, indent: usize) Fmt(@TypeOf(tree))
return .{ .data = .{ tree, source, indent } };
}
+pub const File = struct {
+ decls: []Decl,
+
+ const Decl = struct {
+ loc: Lexer.Location,
+ inner: Stmt.Type.AssignVar,
+ };
+
+ fn format(self: File, writer: anytype, source: []const u8, indent: usize) !void {
+ for (self.decls) |decl| {
+ try writer.print("{s} {s} {}", .{
+ decl.inner.ident.getIdent(source),
+ ":=",
+ fmt(decl.inner.value, source, indent),
+ });
+ }
+ }
+};
+
pub const Block = struct {
loc: Lexer.Location,
stmts: []Stmt,
@@ -87,6 +106,7 @@ pub const Expr = struct {
call: Call,
identifier,
@"if": If,
+ proc: Proc,
pub const BinOp = struct {
lhs: *const Expr,
@@ -124,6 +144,10 @@ pub const Expr = struct {
then: Block,
@"else": ?Block,
};
+
+ pub const Proc = struct {
+ body: Block,
+ };
};
fn format(self: Expr, writer: anytype, source: []const u8, indent: usize) !void {
@@ -145,6 +169,9 @@ pub const Expr = struct {
try writer.print(" else {}", .{fmt(@"else", source, indent)});
}
},
+ .proc => |proc| {
+ try writer.print("proc() {}", .{fmt(proc.body, source, indent)});
+ },
}
}
};
@@ -157,22 +184,28 @@ const ParseError = error{
ExprStatementMustBeCall,
};
-pub fn file(allocator: Allocator, lexer: *Lexer) !Block {
- var stmts: std.ArrayList(Stmt) = .init(allocator);
+pub fn file(allocator: Allocator, lexer: *Lexer) !File {
+ var decls: std.ArrayList(File.Decl) = .init(allocator);
while (lexer.peek().type != .eof) {
- try stmts.append(try statement(allocator, lexer));
+ const stmt = try parseStatement(allocator, lexer);
+ if (stmt.type != .assign_var or !stmt.type.assign_var.is_decl) {
+ return error.ExpectedProcedureDeclaration;
+ }
+ try decls.append(.{
+ .loc = stmt.loc,
+ .inner = stmt.type.assign_var,
+ });
}
return .{
- .loc = stmts.items[0].loc.combine(stmts.getLast().loc),
- .stmts = try stmts.toOwnedSlice(),
+ .decls = try decls.toOwnedSlice(),
};
}
-fn block(allocator: Allocator, lexer: *Lexer) !Block {
+fn parseBlock(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) {
- try stmts.append(try statement(allocator, lexer));
+ try stmts.append(try parseStatement(allocator, lexer));
}
const right_curly = try mustEat(lexer, .right_curly);
return .{
@@ -181,10 +214,10 @@ fn block(allocator: Allocator, lexer: *Lexer) !Block {
};
}
-fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt {
+fn parseStatement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt {
switch (lexer.peek().type) {
.left_curly => {
- const b = try block(allocator, lexer);
+ const b = try parseBlock(allocator, lexer);
return .{
.loc = b.loc,
.type = .{ .block = b },
@@ -193,7 +226,7 @@ fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt {
.@"while" => {
const @"while" = lexer.next();
const cond = try expression(allocator, lexer);
- const do = try block(allocator, lexer);
+ const do = try parseBlock(allocator, lexer);
return .{
.loc = @"while".loc.combine(do.loc),
.type = .{ .@"while" = .{
@@ -232,7 +265,21 @@ fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt {
}
fn expression(allocator: Allocator, lexer: *Lexer) ParseError!*Expr {
- return parseComparisons(allocator, lexer);
+ return parseProc(allocator, lexer);
+}
+
+fn parseProc(allocator: Allocator, lexer: *Lexer) ParseError!*Expr {
+ if (lexer.peek().type != .proc) return parseComparisons(allocator, lexer);
+ const proc = try mustEat(lexer, .proc);
+ _ = try mustEat(lexer, .left_paren);
+ // TODO: parameters
+ _ = try mustEat(lexer, .right_paren);
+ const body = try parseBlock(allocator, lexer);
+
+ return allocate(Expr, allocator, .{
+ .loc = proc.loc.combine(body.loc),
+ .type = .{ .proc = .{ .body = body } },
+ });
}
fn parseComparisons(allocator: Allocator, lexer: *Lexer) ParseError!*Expr {
@@ -278,10 +325,10 @@ fn parseIf(allocator: Allocator, lexer: *Lexer) !*Expr {
.@"if" => {
const @"if" = lexer.next();
const cond = try expression(allocator, lexer);
- const then = try block(allocator, lexer);
+ const then = try parseBlock(allocator, lexer);
const @"else" = if (lexer.peek().type == .@"else") blk: {
_ = lexer.next();
- break :blk try block(allocator, lexer);
+ break :blk try parseBlock(allocator, lexer);
} else null;
return try allocate(Expr, allocator, .{
.loc = @"if".loc.combine((@"else" orelse then).loc),