aboutsummaryrefslogtreecommitdiff
path: root/src/grammar.zig
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2025-05-13 15:45:50 +0200
committerNathan Reiner <nathan@nathanreiner.xyz>2025-05-13 15:45:50 +0200
commit76f808ea98313dc847f634b2d8e31066b7a1c68d (patch)
treeceead1140f66547bb26cd3af364d37913b380398 /src/grammar.zig
parenteff19cc15a9bf4df60e7f90c3a7ee525c65266c0 (diff)
make it work sometimes
Diffstat (limited to 'src/grammar.zig')
-rw-r--r--src/grammar.zig45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/grammar.zig b/src/grammar.zig
index 298932c..b3785ba 100644
--- a/src/grammar.zig
+++ b/src/grammar.zig
@@ -51,6 +51,12 @@ pub fn parse(entry: []const u8, buffer: []const u8, allocator: std.mem.Allocator
self.generate_first();
self.generate_follows();
+ for (self.non_terminals) |non_terminal| {
+ std.debug.print("{s} := {}\n", .{non_terminal.name, non_terminal.follows});
+ }
+
+ std.debug.print("{}\n", .{self});
+
return self;
}
@@ -181,6 +187,45 @@ fn generate_follows(self: *Self) void {
}
}
+pub fn is_next_char(self: *const Self, rule_slice: []Character, current: usize, char: u8) bool {
+ var is_char_in_first = false;
+ var is_epsilon_in_first = true;
+
+ for (rule_slice) |character| {
+ switch(character) {
+ .terminal => |c| {
+ is_char_in_first = c == char;
+ break;
+ },
+ .non_terminal => |n| {
+ is_char_in_first = self.non_terminals[n].first.is_set(char);
+
+ if (is_char_in_first or !self.non_terminals[n].first.is_set(Character.EPSILON)) {
+ break;
+ }
+ },
+ else => {},
+ }
+ }
+
+ for (rule_slice) |character| {
+ switch(character) {
+ .terminal => is_epsilon_in_first = false,
+ .non_terminal => |n| {
+ if (!self.non_terminals[n].first.is_set(Character.EPSILON)) {
+ is_epsilon_in_first = false;
+ break;
+ }
+ },
+ else => {},
+ }
+ }
+
+ const result = is_char_in_first or (is_epsilon_in_first and self.non_terminals[current].follows.is_set(char));
+
+ return result;
+}
+
pub fn format(
self: *const Self,
comptime fmt: []const u8,