lib/chant/src/parse/state/cursor.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 const chant = @import("../../root.zig");
 3 const types = @import("types.zig");
 4 const diagnostic = @import("diagnostic.zig");
 5 const Error = @import("../root.zig").Error;
 6 
 7 const Token = chant.token.Token;
 8 const Kind = chant.token.Kind;
 9 const Parser = types.Parser;
10 
11 pub fn peek(parser: *const Parser) Token {
12     return parser.tokens[parser.index];
13 }
14 
15 pub fn ahead(parser: *const Parser, offset: usize) Token {
16     const at = @min(parser.index + offset, parser.tokens.len - 1);
17     return parser.tokens[at];
18 }
19 
20 pub fn advance(parser: *Parser) Token {
21     const tok = parser.tokens[parser.index];
22     if (tok.kind != .eof) parser.index += 1;
23     return tok;
24 }
25 
26 pub fn consume(parser: *Parser, expected: Kind) bool {
27     if (peek(parser).kind == expected) {
28         _ = advance(parser);
29         return true;
30     }
31     return false;
32 }
33 
34 pub fn expect(parser: *Parser, expected: Kind) Error!Token {
35     if (peek(parser).kind != expected) {
36         return diagnostic.fail(parser, error.UnexpectedToken, "unexpected token");
37     }
38     return advance(parser);
39 }
40 
41 test "cursor moves through tokens" {
42     var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);
43     defer arena_state.deinit();
44     const arena = arena_state.allocator();
45 
46     const tokens = [_]Token{
47         .{ .kind = .kw_int, .text = "int", .file = "test.c", .line = 1, .column = 1 },
48         .{ .kind = .identifier, .text = "value", .file = "test.c", .line = 1, .column = 5 },
49         .{ .kind = .eof, .text = "", .file = "test.c", .line = 1, .column = 10 },
50     };
51     var parser = try @import("test.zig").initParser(arena, &tokens);
52 
53     try std.testing.expectEqual(.identifier, ahead(&parser, 1).kind);
54     try std.testing.expect(consume(&parser, .kw_int));
55     _ = try expect(&parser, .identifier);
56 }