lib/chant/src/parse/state/start.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const chant = @import("../../root.zig");
3 const ast = @import("../../ast/root.zig");
4 const types = @import("types.zig");
5 const cursor = @import("cursor.zig");
6 const typedef = @import("typedef.zig");
7
8 const Token = chant.token.Token;
9 const Parser = types.Parser;
10
11 pub fn declaration(parser: *const Parser) bool {
12 return switch (cursor.peek(parser).kind) {
13 .kw_void,
14 .kw_char,
15 .kw_short,
16 .kw_int,
17 .kw_long,
18 .kw_float,
19 .kw_double,
20 .kw_decimal32,
21 .kw_decimal64,
22 .kw_decimal128,
23 .kw_signed,
24 .kw_unsigned,
25 .kw_bitint,
26 .kw_bool,
27 .kw_const,
28 .kw_volatile,
29 .kw_restrict,
30 .kw_static,
31 .kw_extern,
32 .kw_inline,
33 .kw_register,
34 .kw_auto,
35 .kw_constexpr,
36 .kw_typedef,
37 .kw_alignas,
38 .kw_thread_local,
39 .kw_typeof,
40 .kw_typeof_unqual,
41 .kw_struct,
42 .kw_union,
43 .kw_enum,
44 => true,
45 .lbracket => cursor.ahead(parser, 1).kind == .lbracket,
46 .identifier => typedef.isName(parser, cursor.peek(parser).text),
47 else => false,
48 };
49 }
50
51 pub fn typename(parser: *const Parser, offset: usize) bool {
52 const tok = cursor.ahead(parser, offset);
53 return switch (tok.kind) {
54 .kw_void,
55 .kw_char,
56 .kw_short,
57 .kw_int,
58 .kw_long,
59 .kw_float,
60 .kw_double,
61 .kw_decimal32,
62 .kw_decimal64,
63 .kw_decimal128,
64 .kw_signed,
65 .kw_unsigned,
66 .kw_bitint,
67 .kw_bool,
68 .kw_const,
69 .kw_volatile,
70 .kw_typeof,
71 .kw_typeof_unqual,
72 .kw_struct,
73 .kw_union,
74 .kw_enum,
75 => true,
76 .identifier => typedef.isName(parser, tok.text),
77 else => false,
78 };
79 }
80
81 test "start detects declarations and type names" {
82 var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);
83 defer arena_state.deinit();
84 const arena = arena_state.allocator();
85
86 const tokens = [_]Token{
87 .{ .kind = .identifier, .text = "size_t", .file = "test.c", .line = 1, .column = 1 },
88 .{ .kind = .identifier, .text = "value", .file = "test.c", .line = 1, .column = 8 },
89 .{ .kind = .eof, .text = "", .file = "test.c", .line = 1, .column = 13 },
90 };
91 var parser = try @import("test.zig").initParser(arena, &tokens);
92
93 try typedef.register(&parser, "size_t", &ast.types.ulong_type);
94 try std.testing.expect(declaration(&parser));
95 try std.testing.expect(typename(&parser, 0));
96 try std.testing.expect(!typename(&parser, 1));
97 }