aboutsummaryrefslogtreecommitdiff
path: root/src/parse.zig
diff options
context:
space:
mode:
authorMathias Magnusson <mathias@magnusson.space>2025-06-07 00:05:22 +0200
committerMathias Magnusson <mathias@magnusson.space>2025-06-07 00:57:32 +0200
commit1ed87d6c58cab383f18590093f651ef35c4fa671 (patch)
treec76bc3b8797f6e9973439462565b015da1dcbd80 /src/parse.zig
parent8c9a56311ac2774bf83eda4ea0aa9bde0aec125f (diff)
downloadhuginn-1ed87d6c58cab383f18590093f651ef35c4fa671.tar.gz
add variable reassignments and basic block arguments
Diffstat (limited to 'src/parse.zig')
-rw-r--r--src/parse.zig36
1 files changed, 25 insertions, 11 deletions
diff --git a/src/parse.zig b/src/parse.zig
index 92fb219..8347687 100644
--- a/src/parse.zig
+++ b/src/parse.zig
@@ -43,11 +43,12 @@ pub const Stmt = struct {
pub const Type = union(enum) {
expr: *const Expr,
- declare_var: DeclareVar,
+ assign_var: AssignVar,
block: Block,
- pub const DeclareVar = struct {
+ pub const AssignVar = struct {
ident: Lexer.Location,
+ is_decl: bool,
value: *const Expr,
};
};
@@ -57,9 +58,10 @@ pub const Stmt = struct {
return switch (self.type) {
.expr => |expr| writer.print("{}", .{fmt(expr, source, indent)}),
.block => |b| writer.print("{}", .{fmt(b, source, indent)}),
- .declare_var => |declare_var| writer.print("let {s} = {}", .{
- declare_var.ident.getIdent(source),
- fmt(declare_var.value, source, indent),
+ .assign_var => |assign_var| writer.print("{s}{s} = {}", .{
+ if (assign_var.is_decl) "let " else "",
+ assign_var.ident.getIdent(source),
+ fmt(assign_var.value, source, indent),
}),
};
}
@@ -129,7 +131,7 @@ pub const Expr = struct {
}
};
-const ParseError = error{ OutOfMemory, ExpectedRightParen, UnexpectedToken };
+const ParseError = error{ OutOfMemory, ExpectedRightParen, UnexpectedToken, InvalidAssignTarget };
pub fn block(allocator: Allocator, lexer: *Lexer) !Block {
const left_curly = try mustEat(lexer, .left_curly);
@@ -153,7 +155,7 @@ pub fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt {
const value = try expression(allocator, lexer);
return .{
.loc = let.loc.combine(value.loc),
- .type = .{ .declare_var = .{ .ident = ident.loc, .value = value } },
+ .type = .{ .assign_var = .{ .ident = ident.loc, .is_decl = true, .value = value } },
};
},
.left_curly => {
@@ -164,10 +166,22 @@ pub fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt {
};
},
else => {
- const expr = try expression(allocator, lexer);
+ const lhs = try expression(allocator, lexer);
+ if (lexer.peek().type == .equal) {
+ _ = try mustEat(lexer, .equal);
+ const value = try expression(allocator, lexer);
+ if (lhs.type != .identifier) {
+ std.debug.print("Invalid assign target. Found '{s}', expected an identifier.", .{@tagName(lhs.type)});
+ return error.InvalidAssignTarget;
+ }
+ return .{
+ .loc = lhs.loc,
+ .type = .{ .assign_var = .{ .ident = lhs.loc, .is_decl = false, .value = value } },
+ };
+ }
return .{
- .loc = expr.loc,
- .type = .{ .expr = expr },
+ .loc = lhs.loc,
+ .type = .{ .expr = lhs },
};
},
}
@@ -247,7 +261,7 @@ pub fn parsePrimaryExpr(allocator: Allocator, lexer: *Lexer) !*Expr {
.integer_literal => .{ .loc = token.loc, .type = .integer_literal },
.identifier => .{ .loc = token.loc, .type = .identifier },
else => |t| {
- std.debug.print("Expected '(', integer literal, or identifier. Got {}\n", .{t});
+ std.debug.print("Expected '(', integer literal, or identifier. Got '{s}'\n", .{@tagName(t)});
return error.UnexpectedToken;
},
});