This is could be a very basic thing that I still haven't got the grips of. I'm basically seeing two different outputs depending on where I log the struct, and I'm not exactly sure why.
Here's the main part of this code, and the confusion is around the output of the method next_token.
pub const Lexer = struct {
input: string,
position: usize = 0,
read_position: usize = 0,
ch: u8 = 0,
const Self = @This();
pub fn init(input: string) Self {
var l = Self{
.input = input,
};
l.read_char();
return l;
}
// Reads the next character if possible
fn read_char(self: *Self) void {
if (self.read_position >= self.input.len) {
self.ch = 0;
} else {
self.ch = self.input[self.read_position];
}
self.position = self.read_position;
self.read_position += 1;
}
fn skip_whitespace(self: *Self) void {
while (
self.ch == ' ' or self.ch == '\t' or self.ch == '\n' or self.ch == '\r'
) {
self.read_char();
}
}
pub fn next_token(self: *Self) token.Token {
self.skip_whitespace();
var tok = switch (self.ch) {
// ---snip---
')' => new_token(token.RPAREN, self.ch),
// ---snip---
};
self.read_char();
std.debug.print("Before return: {any}\n", .{tok.literal});
defer std.debug.print("After return: {any}\n", .{tok.literal});
return tok;
}
}
fn new_token(token_type: token.TokenType, ch: u8) token.Token {
const literal = [_]u8{ ch };
return token.Token{ .token_type = token_type, .literal = &literal};
}
And here's what the invocation site looks like:
pub fn main() !void {
var my_lexer = lexer.Lexer.init(")");
const test_token = my_lexer.next_token();
std.debug.print("At invocation: {any}\n", .{test_token.literal});
}
And this is my output:
> zig build run
Before return: { 41 }
After return: { 41 }
At invocation: { 0 }