diff options
Diffstat (limited to 'src/parse.zig')
-rw-r--r-- | src/parse.zig | 73 |
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), |