diff --git a/examples/hello.v b/examples/hello.v index 8685e38..81b5f60 100644 --- a/examples/hello.v +++ b/examples/hello.v @@ -11,4 +11,10 @@ fn main(a int) int { 3 / (51 + 2) mut a := 1+2 a = 2 + + if a { + println(30) + } else { + println(50) + } } diff --git a/src/ast.zig b/src/ast.zig index 23b829d..27c0b8c 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -88,12 +88,12 @@ pub const Expr = union(ExprType) { Grouping: *Expr, }; -pub const IfBranch = std.ArrayList(Stmt); +pub const IfBranch = std.ArrayList(*Stmt); pub const IfStmt = struct { condition: *Expr, then_branch: IfBranch, - else_branch: IfBranch, + else_branch: ?IfBranch, }; pub const Stmt = union(enum) { @@ -107,6 +107,23 @@ pub const Stmt = union(enum) { println.* = Stmt{ .Println = expr }; return println; } + + pub fn mkIfStmt( + allocator: *std.mem.Allocator, + condition: *Expr, + then: IfBranch, + else_branch: ?IfBranch, + ) !*Stmt { + var println = try allocator.create(Stmt); + println.* = Stmt{ + .If = IfStmt{ + .condition = condition, + .then_branch = then, + .else_branch = else_branch, + }, + }; + return println; + } }; pub const Node = union(NodeType) { @@ -138,6 +155,22 @@ fn print(ident: usize, comptime fmt: []const u8, args: ...) void { std.debug.warn(fmt, args); } +fn printBlock(ident: usize, block: var, endNewline: bool) void { + std.debug.warn("(\n"); + + for (block.toSlice()) |stmt| { + printIdent(ident); + printStmt(ident, stmt); + std.debug.warn("\n"); + } + + if (endNewline) { + print(ident - 1, ")\n"); + } else { + print(ident - 1, ")"); + } +} + pub fn printNode(node: *Node, ident: usize) void { switch (node.*) { .FnDecl => |decl| { @@ -147,15 +180,8 @@ pub fn printNode(node: *Node, ident: usize) void { std.debug.warn("({} {}) ", param.name.lexeme, param.typ.lexeme); } - std.debug.warn(") (\n"); - - for (decl.body.toSlice()) |stmt| { - printIdent(ident + 1); - printStmt(stmt); - std.debug.warn("\n"); - } - - print(ident, ")\n"); + printBlock(ident + 1, decl.body, false); + std.debug.warn(")\n"); }, .ConstDecl => |consts| { @@ -189,7 +215,7 @@ pub fn printNode(node: *Node, ident: usize) void { .Stmt => |stmt| blk: { printIdent(ident); - printStmt(stmt); + printStmt(ident, stmt); std.debug.warn("\n"); }, @@ -250,10 +276,24 @@ pub fn printExpr(expr: *Expr) void { } } -pub fn printStmt(stmt: *Stmt) void { +pub fn printStmt(ident: usize, stmt: *Stmt) void { switch (stmt.*) { .Println => |expr| parenthetize("println", &[_]*Expr{expr}), .Expr => |expr| printExpr(expr), + + .If => |ifstmt| { + std.debug.warn("(if "); + printExpr(ifstmt.condition); + std.debug.warn(" "); + + printBlock(ident + 1, ifstmt.then_branch, false); + if (ifstmt.else_branch) |else_branch| { + std.debug.warn(" else "); + printBlock(ident + 1, else_branch, false); + } + + std.debug.warn(")\n"); + }, else => std.debug.warn("UnknownStmt-{}", @tagName(stmt.*)), } } diff --git a/src/parser.zig b/src/parser.zig index 88ee9b3..768bd0b 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -419,7 +419,6 @@ pub const Parser = struct { _ = try self.consumeSingle(.LeftBrace); while (self.peek().ttype != .RightBrace) { - std.debug.warn("get smt with cur {}\n", self.peek().ttype); var stmt = try self.parseDecl(); ast.printNode(try self.mkStmt(stmt), 0); try stmts.append(stmt); @@ -436,6 +435,7 @@ pub const Parser = struct { fn parseStmt(self: *@This()) anyerror!*Stmt { return switch (self.peek().ttype) { + .If => try self.parseIfStmt(), .Println => try self.parsePrintln(), // TODO make newlines tokens and consume newline? @@ -443,6 +443,45 @@ pub const Parser = struct { }; } + /// Copy of parseBlock for if branches + fn parseIfBranch(self: *@This()) !ast.IfBranch { + var branch = ast.IfBranch.init(self.allocator); + errdefer branch.deinit(); + + _ = try self.consumeSingle(.LeftBrace); + + while (self.peek().ttype != .RightBrace) { + var stmt = try self.parseDecl(); + ast.printNode(try self.mkStmt(stmt), 0); + try branch.append(stmt); + } + + _ = try self.consumeSingle(.RightBrace); + + return branch; + } + + fn parseIfStmt(self: *@This()) !*Stmt { + _ = try self.consumeSingle(.If); + var condition = (try self.parseExpr()).Expr; + + const then_branch = try self.parseIfBranch(); + + var else_branch: ?ast.IfBranch = null; + + if (self.check(.Else)) { + _ = try self.consumeSingle(.Else); + else_branch = try self.parseIfBranch(); + } + + return try Stmt.mkIfStmt( + self.allocator, + condition, + then_branch, + else_branch, + ); + } + fn parsePrintln(self: *@This()) !*Stmt { _ = try self.consumeSingle(.Println);