diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-04-24 15:10:14 +0200 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-04-24 15:10:14 +0200 |
| commit | 9456f4e2b569b393d6c01784a4545b11b32e16ef (patch) | |
| tree | 7b4eeab3d0dd4c273de025db19f6be52d9cd1f1d /src/char-set.zig | |
Implement grammar parser
This implements the grammar struct together with
some other helpful structures like char-set and character.
The grammar struct parses a grammar file and also generates
the FIRST and FOLLOWS tables.
Diffstat (limited to 'src/char-set.zig')
| -rw-r--r-- | src/char-set.zig | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/char-set.zig b/src/char-set.zig new file mode 100644 index 0000000..d244540 --- /dev/null +++ b/src/char-set.zig @@ -0,0 +1,90 @@ +const std = @import("std"); + +const Character = @import("character.zig").Character; + +const Self = @This(); + +charset: [256]bool = std.mem.zeroes([256]bool), + +pub inline fn is_set(self: *const Self, c: usize) bool { + return self.charset[c]; +} + +pub inline fn set(self: *Self, c: usize) void { + self.charset[c] = true; +} + +pub inline fn reset(self: *Self, c: usize) void { + self.charset[c] = false; +} + +pub inline fn set_if(self: *Self, c: usize, flag: bool) void { + self.charset[c] = self.charset[c] or flag; +} + +pub fn format( + self: *const Self, + comptime fmt: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, +) !void { + _ = fmt; + _ = options; + + try writer.print("{{ ", .{}); + + for (self.charset, 0..) |is_first, index| { + if (is_first) { + if (index == Character.EPSILON) { + try writer.print("{} ", .{Character { .epsilon = void{} }}); + } else if (index == Character.END) { + try writer.print("$ ", .{}); + } else { + try writer.print("'{c}' ", .{@as(u8, @truncate(index))}); + } + } + } + + try writer.print("}}", .{}); +} + +pub fn expect(self: *const Self, expected: []const u8) !void { + var matrix = std.mem.zeroes([255]bool); + + for (expected) |c| { + matrix[c] = true; + } + + for (matrix, 0..) |contained, index| { + if (self.is_set(index) != contained) { + std.debug.print("expected {{ ", .{}); + + for (expected) |c| { + if (c == Character.EPSILON) { + std.debug.print("{} ", .{Character { .epsilon = void{} }}); + } else if (c == Character.END) { + std.debug.print("$ ", .{}); + } else { + std.debug.print("'{c}' ", .{c}); + } + } + + std.debug.print("}} but got {} (", .{self}); + + if (index == Character.EPSILON) { + std.debug.print("{}", .{Character { .epsilon = void{} }}); + } else if (index == Character.END) { + std.debug.print("$", .{}); + } else { + std.debug.print("'{c}'", .{@as(u8, @truncate(index))}); + } + if (contained) { + std.debug.print(" missing)\n", .{}); + } else { + std.debug.print(" not expected)\n", .{}); + } + + return error.ExpectEqualError; + } + } +} |