aboutsummaryrefslogtreecommitdiff
path: root/src/grammar.zig
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2025-05-15 17:49:24 +0200
committerNathan Reiner <nathan@nathanreiner.xyz>2025-05-15 17:49:24 +0200
commit0273079fa0004f9f93ae96615f97934b832f8c51 (patch)
tree07a2d68d856efc24e80d3c0b77dbc1dbb54d9d14 /src/grammar.zig
parentf67e7524859f0b5462065a23c4334c97710f4f84 (diff)
minor optimization: add a first set to each rule variant
Diffstat (limited to 'src/grammar.zig')
-rw-r--r--src/grammar.zig18
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);