From b3909efb3a6bf76870b686b5062f9a4282fbdd66 Mon Sep 17 00:00:00 2001 From: Mathias Magnusson Date: Thu, 24 Jul 2025 20:38:56 +0200 Subject: `let x = 1` -> `x := 1` --- fibonacci.hgn | 9 +++++---- src/Lexer.zig | 6 ++++-- src/parse.zig | 35 +++++++++++++++++++---------------- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/fibonacci.hgn b/fibonacci.hgn index 00c0638..01d9333 100644 --- a/fibonacci.hgn +++ b/fibonacci.hgn @@ -1,8 +1,9 @@ -let a = 0 -let b = 1 -let n = read_int(0) +a := 0 +b := 1 +n := 10 +# n := read_int(0) while n > 0 { - let c = a + b + c := a + b a = b b = c n = n - 1 diff --git a/src/Lexer.zig b/src/Lexer.zig index 4665379..4b664fe 100644 --- a/src/Lexer.zig +++ b/src/Lexer.zig @@ -13,6 +13,7 @@ pub const Token = struct { plus, minus, equal, + colon, invalid, eof, identifier, @@ -22,7 +23,6 @@ pub const Token = struct { right_angle_equal, // Keywords - let, @"if", @"else", @"while", @@ -34,6 +34,7 @@ pub const Location = struct { end: usize, pub fn combine(a: Location, b: Location) Location { + if (a.start == b.start and a.end == b.end) return a; std.debug.assert(a.end <= b.start); return .{ .start = @min(a.start, b.start), .end = @max(a.end, b.end) }; } @@ -83,6 +84,7 @@ fn getNext(self: *Self) Token { '+' => self.create(.plus), '-' => self.create(.minus), '=' => self.create(.equal), + ':' => self.create(.colon), '<' => if (self.eatIfEqual('=')) self.create(.left_angle_equal) else @@ -135,7 +137,7 @@ fn identifierOrKeyword(self: *Self) Token { } const value = self.source[self.start..self.pos]; return self.create(switch (std.meta.stringToEnum(Token.Type, value) orelse .invalid) { - .let, .@"if", .@"else", .@"while" => |t| t, + .@"if", .@"else", .@"while" => |t| t, else => .identifier, }); } diff --git a/src/parse.zig b/src/parse.zig index 26f32e9..bd6b000 100644 --- a/src/parse.zig +++ b/src/parse.zig @@ -64,9 +64,9 @@ pub const Stmt = struct { return switch (self.type) { .expr => |expr| writer.print("{}", .{fmt(expr, source, indent)}), .block => |b| writer.print("{}", .{fmt(b, source, indent)}), - .assign_var => |assign_var| writer.print("{s}{s} = {}", .{ - if (assign_var.is_decl) "let " else "", + .assign_var => |assign_var| writer.print("{s} {s} {}", .{ assign_var.ident.getIdent(source), + if (assign_var.is_decl) ":=" else "=", fmt(assign_var.value, source, indent), }), .@"while" => |@"while"| try writer.print("while {} {}", .{ @@ -149,7 +149,13 @@ pub const Expr = struct { } }; -const ParseError = error{ OutOfMemory, ExpectedRightParen, UnexpectedToken, InvalidAssignTarget }; +const ParseError = error{ + OutOfMemory, + ExpectedRightParen, + UnexpectedToken, + InvalidAssignTarget, + ExprStatementMustBeCall, +}; pub fn file(allocator: Allocator, lexer: *Lexer) !Block { var stmts: std.ArrayList(Stmt) = .init(allocator); @@ -177,16 +183,6 @@ fn block(allocator: Allocator, lexer: *Lexer) !Block { fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt { 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); - return .{ - .loc = let.loc.combine(value.loc), - .type = .{ .assign_var = .{ .ident = ident.loc, .is_decl = true, .value = value } }, - }; - }, .left_curly => { const b = try block(allocator, lexer); return .{ @@ -208,7 +204,12 @@ fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt { }, else => { const lhs = try expression(allocator, lexer); - if (lexer.peek().type == .equal) { + + const colon = if (lexer.peek().type == .colon) + try mustEat(lexer, .colon) + else + null; + if (colon != null or lexer.peek().type == .equal) { _ = try mustEat(lexer, .equal); const value = try expression(allocator, lexer); if (lhs.type != .identifier) { @@ -216,9 +217,11 @@ fn statement(allocator: Allocator, lexer: *Lexer) ParseError!Stmt { return error.InvalidAssignTarget; } return .{ - .loc = lhs.loc, - .type = .{ .assign_var = .{ .ident = lhs.loc, .is_decl = false, .value = value } }, + .loc = lhs.loc.combine(value.loc), + .type = .{ .assign_var = .{ .ident = lhs.loc, .is_decl = colon != null, .value = value } }, }; + } else if (lhs.type != .call) { + return error.ExprStatementMustBeCall; } return .{ .loc = lhs.loc, -- cgit v1.2.3