aboutsummaryrefslogtreecommitdiff
path: root/src/lexer.zig
diff options
context:
space:
mode:
authorMathias Magnusson <mathias@magnusson.space>2025-05-31 22:54:26 +0200
committerMathias Magnusson <mathias@magnusson.space>2025-05-31 22:54:26 +0200
commit5749be69125dc87ac50742295272a7e21f4f472e (patch)
treecf0aa4776eda997f94ef35e06e41f16678aedebd /src/lexer.zig
parent590a76edb6a88f754a43e96f16f2fc73845238b5 (diff)
downloadhuginn-5749be69125dc87ac50742295272a7e21f4f472e.tar.gz
codegen integer literals correctly
This was not as easy as one would expect ☠️
Diffstat (limited to 'src/lexer.zig')
-rw-r--r--src/lexer.zig28
1 files changed, 26 insertions, 2 deletions
diff --git a/src/lexer.zig b/src/lexer.zig
index 67beec9..8586765 100644
--- a/src/lexer.zig
+++ b/src/lexer.zig
@@ -1,3 +1,5 @@
+const std = @import("std");
+
pub const Token = struct {
loc: Location,
type: Type,
@@ -20,6 +22,16 @@ pub const Location = struct {
if (a.end > b.start) unreachable;
return .{ .start = @min(a.start, b.start), .end = @max(a.end, b.end) };
}
+
+ /// Assumes that the location comes directly from an `integer_literal` token.
+ pub fn getInt(self: Location, file_source: []const u8) u64 {
+ var value: u64 = 0;
+ for (file_source[self.start..self.end]) |c| {
+ std.debug.assert('0' <= c and c <= '9');
+ value = value * 10 + (c - '0');
+ }
+ return value;
+ }
};
source: []const u8,
@@ -41,10 +53,22 @@ pub fn next(self: *Self) ?Token {
}
fn integerLiteral(self: *Self) Token {
- while (digitValue(self.peek()) != null) {
+ var value: ?u64 = 0;
+ while (digitValue(self.peek())) |v| {
+ var nxt: ?u64 = null;
+ if (value) |val|
+ if (std.math.mul(u64, val, 10) catch null) |p|
+ if (std.math.add(u64, p, v) catch null) |s| {
+ nxt = s;
+ };
+
+ value = nxt;
_ = self.eat();
}
- return self.create(.{ .integer_literal = {} });
+ return if (value != null)
+ self.create(.{ .integer_literal = {} })
+ else
+ self.create(.{ .invalid = {} });
}
fn create(self: *Self, tajp: Token.Type) Token {