diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-05-15 17:49:24 +0200 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-05-15 17:49:24 +0200 |
| commit | 0273079fa0004f9f93ae96615f97934b832f8c51 (patch) | |
| tree | 07a2d68d856efc24e80d3c0b77dbc1dbb54d9d14 /src/grammar.zig | |
| parent | f67e7524859f0b5462065a23c4334c97710f4f84 (diff) | |
minor optimization: add a first set to each rule variant
Diffstat (limited to 'src/grammar.zig')
| -rw-r--r-- | src/grammar.zig | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/src/grammar.zig b/src/grammar.zig index ab51275..2169fe7 100644 --- a/src/grammar.zig +++ b/src/grammar.zig @@ -80,21 +80,23 @@ fn generate_first(self: *Self) void { modified = false; for (self.non_terminals) |*non_terminal| { - for (non_terminal.rules()) |rule| { - switch (rule[0]) { + for (non_terminal.rules()) |*rule| { + switch (rule.items[0]) { .terminal => |t| { modified = modified or !non_terminal.first.is_set(t); non_terminal.first.set(t); + rule.first.set(t); }, .non_terminal, .epsilon => { var insert_epsilon = true; - for (rule) |*char| { + for (rule.items) |*char| { switch (char.*) { .terminal => |t| { modified = modified or !non_terminal.first.is_set(t); non_terminal.first.set(t); + rule.first.set(t); insert_epsilon = false; break; }, @@ -105,6 +107,7 @@ fn generate_first(self: *Self) void { modified = modified or (!non_terminal.first.is_set(index) and child_first); non_terminal.first.set_if(index, child_first); + rule.first.set_if(index, child_first); } if (!first.is_set(Character.EPSILON)) { @@ -119,6 +122,7 @@ fn generate_first(self: *Self) void { if (insert_epsilon and !non_terminal.first.is_set(Character.EPSILON)) { modified = true; non_terminal.first.set(Character.EPSILON); + rule.first.set(Character.EPSILON); } }, } @@ -135,14 +139,14 @@ fn generate_follows(self: *Self) void { for (self.non_terminals) |*non_terminal| { for (non_terminal.rules()) |rule| { - for (0..rule.len) |character_index| { + for (0..rule.items.len) |character_index| { - switch (rule[character_index]) { + switch (rule.items[character_index]) { .non_terminal => |n| { const current_non_terminal = self.non_terminal_by_id(n); const ends_with_epsilon = brk: { - for (character_index + 1..rule.len) |peek_index| { - switch (rule[peek_index]) { + for (character_index + 1..rule.items.len) |peek_index| { + switch (rule.items[peek_index]) { .terminal => |t| { modified = modified or !current_non_terminal.follows.is_set(t); current_non_terminal.follows.set(t); |