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 }