aboutsummaryrefslogtreecommitdiff
path: root/src/parse.zig
diff options
context:
space:
mode:
authorMathias Magnusson <mathias@magnusson.space>2025-06-02 18:47:24 +0200
committerMathias Magnusson <mathias@magnusson.space>2025-06-02 18:47:24 +0200
commitbb66477d1423f16c77986b48acd6156222d7d195 (patch)
tree772e8f3915dc5854f0d5e2d4376fcd1490a11dc6 /src/parse.zig
parent601916b828b8d94a89df6950da73ea68a20daa69 (diff)
downloadhuginn-bb66477d1423f16c77986b48acd6156222d7d195.tar.gz
add variable declarations
Diffstat (limited to 'src/parse.zig')
-rw-r--r--src/parse.zig50
1 files changed, 38 insertions, 12 deletions
diff --git a/src/parse.zig b/src/parse.zig
index cadc489..e240ce3 100644
--- a/src/parse.zig
+++ b/src/parse.zig
@@ -11,6 +11,12 @@ pub const Stmt = struct {
pub const Type = union(enum) {
expr: *const Expr,
+ declare_var: DeclareVar,
+
+ pub const DeclareVar = struct {
+ ident: Lexer.Location,
+ value: *const Expr,
+ };
};
pub fn fmt(self: Stmt, file_source: []const u8) Format {
@@ -24,6 +30,7 @@ pub const Stmt = struct {
_ = options;
return switch (self.type) {
.expr => |expr| writer.print("{};", .{expr.fmt(file_source)}),
+ .declare_var => |declare_var| writer.print("let {s} = {};", .{ declare_var.ident.getIdent(file_source), declare_var.value.fmt(file_source) }),
};
}
}.format);
@@ -48,9 +55,7 @@ pub const Expr = struct {
plus,
minus,
- pub fn format(self: Op, comptime f: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
- _ = f;
- _ = options;
+ pub fn format(self: Op, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
try writer.writeByte(switch (self) {
.plus => '+',
.minus => '-',
@@ -70,10 +75,8 @@ pub const Expr = struct {
}
const Format = std.fmt.Formatter(struct {
- fn format(data: struct { Expr, []const u8 }, comptime f: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
+ fn format(data: struct { Expr, []const u8 }, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
const self, const file_source = data;
- _ = f;
- _ = options;
switch (self.type) {
.integer_literal => try writer.print("{}", .{self.loc.getInt(file_source)}),
.bin_op => |bin_op| try writer.print("({} {} {})", .{ bin_op.lhs.fmt(file_source), bin_op.op, bin_op.rhs.fmt(file_source) }),
@@ -93,12 +96,28 @@ pub fn statements(allocator: Allocator, lexer: *Lexer) ![]Stmt {
}
pub fn statement(allocator: Allocator, lexer: *Lexer) !Stmt {
- var expr = try expression(allocator, lexer);
- const semicolon: Lexer.Token = if (lexer.peek().type == .semicolon) lexer.next() else return error.ExpectedSemicolon;
- return .{
- .loc = expr.loc.combine(semicolon.loc),
- .type = .{ .expr = expr },
- };
+ switch (lexer.peek().type) {
+ .let => {
+ const let = lexer.next();
+ const ident = try mustEat(lexer, .identifier);
+ _ = try mustEat(lexer, .equal);
+ const value = try expression(allocator, lexer);
+ const semicolon = try mustEat(lexer, .semicolon);
+ return .{
+ .loc = let.loc.combine(semicolon.loc),
+ .type = .{ .declare_var = .{ .ident = ident.loc, .value = value } },
+ };
+ },
+ else => {
+ var expr = try expression(allocator, lexer);
+ const semicolon = lexer.next();
+ if (semicolon.type != .semicolon) return error.ExpectedSemicolon;
+ return .{
+ .loc = expr.loc.combine(semicolon.loc),
+ .type = .{ .expr = expr },
+ };
+ },
+ }
}
pub fn expression(allocator: Allocator, lexer: *Lexer) error{ OutOfMemory, ExpectedRightParen, UnexpectedToken }!*Expr {
@@ -159,6 +178,13 @@ pub fn primaryExpr(allocator: Allocator, lexer: *Lexer) !*Expr {
});
}
+fn mustEat(lexer: *Lexer, ty: Lexer.Token.Type) !Lexer.Token {
+ const token = lexer.next();
+ std.debug.print("Expected {}. Got {}\n", .{ ty, token.type });
+ if (token.type != ty) return error.UnexpectedToken;
+ return token;
+}
+
fn allocate(T: type, allocator: Allocator, t: T) !*T {
const res = try allocator.create(T);
res.* = t;