forked from benclmnt/zig-interpreter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lexer_minimal.zig
70 lines (66 loc) · 2.02 KB
/
lexer_minimal.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
const std = @import("std");
const Token = struct {
tag: Tag,
start: usize,
end: usize,
const Tag = enum { eof, illegal, identifier };
};
const Lexer = struct {
input: []const u8,
pos: usize = 0,
fn init(input: []const u8) Lexer {
return Lexer{ .input = input };
}
const State = enum { start, identifier };
fn next(self: *Lexer) Token {
var token = Token{ .tag = .eof, .start = self.pos, .end = undefined };
var state: State = .start;
while (true) : (self.pos += 1) {
if (self.pos == self.input.len) break;
const c = self.input[self.pos];
switch (state) {
.start => switch (c) {
' ', '\n' => {
token.start = self.pos + 1;
},
'a'...'z' => {
token.tag = .identifier;
state = .identifier;
},
else => {
token.tag = .illegal;
self.pos += 1;
break;
},
},
.identifier => switch (c) {
'a'...'z' => {},
else => {
break;
},
},
}
}
token.end = self.pos;
return token;
}
};
test "next" {
const input =
\\indexoutofbounds
\\let five = 5;
;
var l = Lexer.init(input);
const Expectation = struct { tag: Token.Tag, literal: []const u8 };
const expectations = [_]Expectation{
.{ .tag = .identifier, .literal = "indexoutofbounds" },
.{ .tag = .identifier, .literal = "let" },
.{ .tag = .identifier, .literal = "five" },
.{ .tag = .illegal, .literal = "=" },
};
for (expectations) |e| {
const t = l.next();
try std.testing.expectEqual(e.tag, t.tag);
try std.testing.expectEqualStrings(e.literal, input[t.start..t.end]);
}
}