aboutsummaryrefslogtreecommitdiff
path: root/src/parse.zig
diff options
context:
space:
mode:
authorMathias Magnusson <mathias@magnusson.space>2025-06-04 01:12:01 +0200
committerMathias Magnusson <mathias@magnusson.space>2025-06-04 01:12:01 +0200
commit55f45123f21e63e883d0afe16d97dcb5dafdd296 (patch)
tree657052d329915f76e4bf302b8c4c44a781582a41 /src/parse.zig
parent8a9d15683101ab1ea8584f3d5595e5319d7b9a24 (diff)
downloadhuginn-55f45123f21e63e883d0afe16d97dcb5dafdd296.tar.gz
begin implementing if expressions
registers are used over block boundaries though, which doesn't work very well so i turned off register freeing to make it look like it works (unless you create more than 12 values total)
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) {