add if statements
This commit is contained in:
parent
83910811fa
commit
9b3e9e8139
3 changed files with 99 additions and 14 deletions
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
66
src/ast.zig
66
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.*)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue