const std = @import("std"); const token = @import("token.zig"); const main = @import("main.zig"); const TokenList = std.ArrayList(token.Token); pub const Scanner = struct { source: []u8, tokens: TokenList, start: usize = 0, current: usize = 0, line: usize = 1, pub fn init(allocator: *std.mem.Allocator, data: []u8) Scanner { return Scanner{ .source = data, .tokens = TokenList.init(allocator), }; } fn isAtEnd(self: *Scanner) bool { return self.current >= self.source.len; } fn advance(self: *Scanner) u8 { self.current += 1; return self.source[self.current - 1]; } fn currentLexeme(self: *Scanner) []u8 { return self.source[self.start..self.current]; } fn addSimpleToken(self: *Scanner, ttype: token.TokenType) !void { try self.addToken(token.Token{ .Simple = token.SimpleToken.init( ttype, self.currentLexeme(), self.line, {}, ), }); } fn addToken( self: *Scanner, tok: token.Token, ) !void { try self.tokens.append(tok); } fn scanToken(self: *Scanner) !void { var c = self.advance(); switch (c) { '(' => try self.addSimpleToken(.LEFT_PAREN), ')' => try self.addSimpleToken(.RIGHT_PAREN), '{' => try self.addSimpleToken(.LEFT_BRACE), '}' => try self.addSimpleToken(.RIGHT_BRACE), ',' => try self.addSimpleToken(.COMMA), '.' => try self.addSimpleToken(.DOT), '-' => try self.addSimpleToken(.MINUS), '+' => try self.addSimpleToken(.PLUS), ';' => try self.addSimpleToken(.SEMICOLON), '*' => try self.addSimpleToken(.STAR), else => { try main.doError(self.line, "Unexpected character"); }, } } pub fn scanTokens(self: *Scanner) !TokenList { // while we aren't at the end, we're still consuming // tokens. while (!self.isAtEnd()) { self.start = self.current; try self.scanToken(); } try self.addToken(token.Token{ .Simple = token.SimpleToken.init( .EOF, "", self.line, {}, ), }); return self.tokens; } };