pub const Scanner = struct {
start: usize = 0,
current: usize = 0,
line: usize = 1,
source: []u8,
tokens: std.ArrayList(Token.Token),
const keywords = std.StaticStringMap(Token.TokenType).initComptime(.{
.{ "and", .AND },
// etc
});
For initialization, you can initialize in place:
var scanner = Scanner.Scanner{
.source = src,
.tokens = std.ArrayList(Token.Token).init(allocator),
}
but the convention is to create an init
function to make initializing non-trivial structs more convenient:
pub fn init(allocator: std.mem.Allocator, src: []const u8) Scanner {
return .{
.source = src,
.tokens = std.ArrayList(Token.Token).init(allocator),
};
}
so then you’d just call
var scanner = Scanner.Scanner.init(allocator, src);
On the Scanner.Scanner
thing, you might be interested in taking advantage of the fact that in Zig, files are structs, so you can create a Scanner.zig
like so:
const Scanner = @This();
start: usize = 0,
current: usize = 0,
line: usize = 1,
source: []u8,
tokens: std.ArrayList(Token.Token),
pub fn init(allocator: std.mem.Allocator, src: []const u8) Scanner {
return .{
.source = src,
.tokens = std.ArrayList(Token.Token).init(allocator),
};
}
and then use it like this:
const Scanner = @import("Scanner.zig");
pub fn main() !void {
// ...
var scanner = Scanner.init(allocator, src);
defer scanner.deinit();
}