diff options
Diffstat (limited to 'src/grammar.zig')
| -rw-r--r-- | src/grammar.zig | 45 |
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, |