94 lines
2.4 KiB
Zig
94 lines
2.4 KiB
Zig
|
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;
|
||
|
}
|
||
|
};
|