aboutsummaryrefslogtreecommitdiff
path: root/src/parse.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.zig')
-rw-r--r--src/parse.zig43
1 files changed, 41 insertions, 2 deletions
diff --git a/src/parse.zig b/src/parse.zig
index 422b4f5..92fb219 100644
--- a/src/parse.zig
+++ b/src/parse.zig
@@ -74,6 +74,7 @@ pub const Expr = struct {
bin_op: BinOp,
call: Call,
identifier,
+ @"if": If,
pub const BinOp = struct {
lhs: *const Expr,
@@ -97,6 +98,12 @@ pub const Expr = struct {
proc: *const Expr,
arg: *const Expr,
};
+
+ pub const If = struct {
+ cond: *const Expr,
+ then: Block,
+ @"else": ?Block,
+ };
};
fn format(self: Expr, writer: anytype, source: []const u8, indent: usize) !void {
@@ -109,6 +116,15 @@ pub const Expr = struct {
try writer.print("{}({})", .{ fmt(call.proc, source, indent), fmt(call.arg, source, indent) });
},
.identifier => try writer.print("{s}", .{self.loc.getIdent(source)}),
+ .@"if" => |@"if"| {
+ try writer.print("if {} {}", .{
+ fmt(@"if".cond, source, indent),
+ fmt(@"if".then, source, indent),
+ });
+ if (@"if".@"else") |@"else"| {
+ try writer.print(" else {}", .{fmt(@"else", source, indent)});
+ }
+ },
}
}
};
@@ -162,7 +178,7 @@ pub fn expression(allocator: Allocator, lexer: *Lexer) ParseError!*Expr {
}
pub fn parseTerms(allocator: Allocator, lexer: *Lexer) !*Expr {
- var lhs = try parseInvocations(allocator, lexer);
+ var lhs = try parseIf(allocator, lexer);
while (true) {
const op: Expr.Type.BinOp.Op = switch (lexer.peek().type) {
.plus => .plus,
@@ -171,7 +187,7 @@ pub fn parseTerms(allocator: Allocator, lexer: *Lexer) !*Expr {
};
_ = lexer.next();
- const rhs = try parseInvocations(allocator, lexer);
+ const rhs = try parseIf(allocator, lexer);
lhs = try allocate(Expr, allocator, .{
.loc = lhs.loc.combine(rhs.loc),
.type = .{ .bin_op = .{ .lhs = lhs, .op = op, .rhs = rhs } },
@@ -180,6 +196,29 @@ pub fn parseTerms(allocator: Allocator, lexer: *Lexer) !*Expr {
return lhs;
}
+pub fn parseIf(allocator: Allocator, lexer: *Lexer) !*Expr {
+ switch (lexer.peek().type) {
+ .@"if" => {
+ const @"if" = lexer.next();
+ const cond = try expression(allocator, lexer);
+ const then = try block(allocator, lexer);
+ const @"else" = if (lexer.peek().type == .@"else") blk: {
+ _ = lexer.next();
+ break :blk try block(allocator, lexer);
+ } else null;
+ return try allocate(Expr, allocator, .{
+ .loc = @"if".loc.combine((@"else" orelse then).loc),
+ .type = .{ .@"if" = .{
+ .cond = cond,
+ .then = then,
+ .@"else" = @"else",
+ } },
+ });
+ },
+ else => return try parseInvocations(allocator, lexer),
+ }
+}
+
pub fn parseInvocations(allocator: Allocator, lexer: *Lexer) !*Expr {
var proc = try parsePrimaryExpr(allocator, lexer);
while (true) {