diff options
author | Mathias Magnusson <mathias@magnusson.space> | 2025-06-04 01:12:01 +0200 |
---|---|---|
committer | Mathias Magnusson <mathias@magnusson.space> | 2025-06-04 01:12:01 +0200 |
commit | 55f45123f21e63e883d0afe16d97dcb5dafdd296 (patch) | |
tree | 657052d329915f76e4bf302b8c4c44a781582a41 /src/parse.zig | |
parent | 8a9d15683101ab1ea8584f3d5595e5319d7b9a24 (diff) | |
download | huginn-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.zig | 43 |
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) { |