diff options
Diffstat (limited to 'src/grammar.zig')
| -rw-r--r-- | src/grammar.zig | 95 |
1 files changed, 53 insertions, 42 deletions
diff --git a/src/grammar.zig b/src/grammar.zig index 3c586f3..9b794a0 100644 --- a/src/grammar.zig +++ b/src/grammar.zig @@ -1,12 +1,12 @@ const std = @import("std"); +const Rule = @import("rule.zig"); const Character = @import("character.zig").Character; const NonTerminal = @import("non-terminal.zig"); const Self = @This(); non_terminals: []NonTerminal, -entry_id: usize, allocator: std.mem.Allocator, pub fn parse(entry: []const u8, buffer: []const u8, allocator: std.mem.Allocator) !Self { @@ -18,19 +18,30 @@ pub fn parse(entry: []const u8, buffer: []const u8, allocator: std.mem.Allocator const name = try NonTerminal.parse_name(line); if (!names.contains(name)) { - try names.put(name, names.count()); + try names.put(name, names.count() + 1); } } lines = std.mem.tokenizeScalar(u8, buffer, '\n'); var self = Self { - .non_terminals = try allocator.alloc(NonTerminal, names.count()), - .entry_id = names.get(entry) orelse return error.MissingRule, + .non_terminals = try allocator.alloc(NonTerminal, names.count() + 1), .allocator = allocator, }; errdefer self.deinit(); { + self.non_terminals[0] = try NonTerminal.init("_start", 0, allocator); + const init_rule = try allocator.alloc(Character, 1); + init_rule[0] = Character { + .non_terminal = names.get(entry) orelse return error.MissingRule, + }; + + try self.non_terminals[0].add_rule(Rule { + .items = init_rule + }); + } + + { var iterator = names.iterator(); while (iterator.next()) |name_entry| { self.non_terminals[name_entry.value_ptr.*] = try NonTerminal.init( @@ -68,7 +79,7 @@ pub inline fn non_terminal_by_id(self: *Self, id: usize) *NonTerminal { } pub inline fn entry_point(self: *Self) *NonTerminal { - return self.non_terminal_by_id(self.entry_id); + return self.non_terminal_by_id(0); } fn generate_first(self: *Self) void { @@ -254,17 +265,17 @@ test "expr" { var grammar = try Self.parse("S", text, allocator); defer grammar.deinit(); - try grammar.non_terminal_by_id(0).first.expect(&[_]u9 { '(', 'a', 'b' }); - try grammar.non_terminal_by_id(1).first.expect(&[_]u9 { '+', Character.EPSILON }); - try grammar.non_terminal_by_id(2).first.expect(&[_]u9 { '(', 'a', 'b' }); - try grammar.non_terminal_by_id(3).first.expect(&[_]u9 { '*', Character.EPSILON }); - try grammar.non_terminal_by_id(4).first.expect(&[_]u9 { '(', 'a', 'b' }); + try grammar.non_terminal_by_id(1).first.expect(&[_]u9 { '(', 'a', 'b' }); + try grammar.non_terminal_by_id(2).first.expect(&[_]u9 { '+', Character.EPSILON }); + try grammar.non_terminal_by_id(3).first.expect(&[_]u9 { '(', 'a', 'b' }); + try grammar.non_terminal_by_id(4).first.expect(&[_]u9 { '*', Character.EPSILON }); + try grammar.non_terminal_by_id(5).first.expect(&[_]u9 { '(', 'a', 'b' }); - try grammar.non_terminal_by_id(0).follows.expect(&[_]u9 { ')', Character.END }); try grammar.non_terminal_by_id(1).follows.expect(&[_]u9 { ')', Character.END }); - try grammar.non_terminal_by_id(2).follows.expect(&[_]u9 { '+', ')', Character.END }); + try grammar.non_terminal_by_id(2).follows.expect(&[_]u9 { ')', Character.END }); try grammar.non_terminal_by_id(3).follows.expect(&[_]u9 { '+', ')', Character.END }); - try grammar.non_terminal_by_id(4).follows.expect(&[_]u9 { '*', '+', ')', Character.END }); + try grammar.non_terminal_by_id(4).follows.expect(&[_]u9 { '+', ')', Character.END }); + try grammar.non_terminal_by_id(5).follows.expect(&[_]u9 { '*', '+', ')', Character.END }); } test "sample 0" { @@ -279,15 +290,15 @@ test "sample 0" { var grammar = try Self.parse("S", text, allocator); defer grammar.deinit(); - try grammar.non_terminal_by_id(0).first.expect(&[_]u9 { 'd', 'g', 'h', 'b', 'a', Character.EPSILON }); - try grammar.non_terminal_by_id(1).first.expect(&[_]u9 { 'd', 'g', 'h', Character.EPSILON }); - try grammar.non_terminal_by_id(2).first.expect(&[_]u9 { 'g', Character.EPSILON }); - try grammar.non_terminal_by_id(3).first.expect(&[_]u9 { 'h', Character.EPSILON }); + try grammar.non_terminal_by_id(1).first.expect(&[_]u9 { 'd', 'g', 'h', 'b', 'a', Character.EPSILON }); + try grammar.non_terminal_by_id(2).first.expect(&[_]u9 { 'd', 'g', 'h', Character.EPSILON }); + try grammar.non_terminal_by_id(3).first.expect(&[_]u9 { 'g', Character.EPSILON }); + try grammar.non_terminal_by_id(4).first.expect(&[_]u9 { 'h', Character.EPSILON }); - try grammar.non_terminal_by_id(0).follows.expect(&[_]u9 { Character.END }); - try grammar.non_terminal_by_id(1).follows.expect(&[_]u9 { 'g', 'h', Character.END }); - try grammar.non_terminal_by_id(2).follows.expect(&[_]u9 { 'a', 'g', 'h', Character.END }); - try grammar.non_terminal_by_id(3).follows.expect(&[_]u9 { 'b', 'g', 'h', Character.END }); + try grammar.non_terminal_by_id(1).follows.expect(&[_]u9 { Character.END }); + try grammar.non_terminal_by_id(2).follows.expect(&[_]u9 { 'g', 'h', Character.END }); + try grammar.non_terminal_by_id(3).follows.expect(&[_]u9 { 'a', 'g', 'h', Character.END }); + try grammar.non_terminal_by_id(4).follows.expect(&[_]u9 { 'b', 'g', 'h', Character.END }); } test "sample 1" { @@ -303,13 +314,13 @@ test "sample 1" { var grammar = try Self.parse("S", text, allocator); defer grammar.deinit(); - try grammar.non_terminal_by_id(0).first.expect(&[_]u9 { 'a' }); - try grammar.non_terminal_by_id(1).first.expect(&[_]u9 { 'c', Character.EPSILON }); - try grammar.non_terminal_by_id(2).first.expect(&[_]u9 { 'd', Character.EPSILON }); + try grammar.non_terminal_by_id(1).first.expect(&[_]u9 { 'a' }); + try grammar.non_terminal_by_id(2).first.expect(&[_]u9 { 'c', Character.EPSILON }); + try grammar.non_terminal_by_id(3).first.expect(&[_]u9 { 'd', Character.EPSILON }); - try grammar.non_terminal_by_id(0).follows.expect(&[_]u9 { Character.END }); - try grammar.non_terminal_by_id(1).follows.expect(&[_]u9 { 'b', 'd' }); - try grammar.non_terminal_by_id(2).follows.expect(&[_]u9 { 'b' }); + try grammar.non_terminal_by_id(1).follows.expect(&[_]u9 { Character.END }); + try grammar.non_terminal_by_id(2).follows.expect(&[_]u9 { 'b', 'd' }); + try grammar.non_terminal_by_id(3).follows.expect(&[_]u9 { 'b' }); } test "sample 2" { @@ -329,17 +340,17 @@ test "sample 2" { var grammar = try Self.parse("S", text, allocator); defer grammar.deinit(); - try grammar.non_terminal_by_id(0).first.expect(&[_]u9 { 'a', 'c', 'e' }); - try grammar.non_terminal_by_id(1).first.expect(&[_]u9 { 'a', 'c' }); - try grammar.non_terminal_by_id(2).first.expect(&[_]u9 { 'd' }); - try grammar.non_terminal_by_id(3).first.expect(&[_]u9 { 'e', Character.EPSILON }); - try grammar.non_terminal_by_id(4).first.expect(&[_]u9 { 'f', Character.EPSILON }); + try grammar.non_terminal_by_id(1).first.expect(&[_]u9 { 'a', 'c', 'e' }); + try grammar.non_terminal_by_id(2).first.expect(&[_]u9 { 'a', 'c' }); + try grammar.non_terminal_by_id(3).first.expect(&[_]u9 { 'd' }); + try grammar.non_terminal_by_id(4).first.expect(&[_]u9 { 'e', Character.EPSILON }); + try grammar.non_terminal_by_id(5).first.expect(&[_]u9 { 'f', Character.EPSILON }); - try grammar.non_terminal_by_id(0).follows.expect(&[_]u9 { Character.END }); - try grammar.non_terminal_by_id(1).follows.expect(&[_]u9 { 'd' }); - try grammar.non_terminal_by_id(2).follows.expect(&[_]u9 { Character.END }); + try grammar.non_terminal_by_id(1).follows.expect(&[_]u9 { Character.END }); + try grammar.non_terminal_by_id(2).follows.expect(&[_]u9 { 'd' }); try grammar.non_terminal_by_id(3).follows.expect(&[_]u9 { Character.END }); - try grammar.non_terminal_by_id(4).follows.expect(&[_]u9 { 'a' }); + try grammar.non_terminal_by_id(4).follows.expect(&[_]u9 { Character.END }); + try grammar.non_terminal_by_id(5).follows.expect(&[_]u9 { 'a' }); } test "sample 3" { @@ -357,11 +368,11 @@ test "sample 3" { var grammar = try Self.parse("S", text, allocator); defer grammar.deinit(); - try grammar.non_terminal_by_id(0).first.expect(&[_]u9 { 'a', 'b', 'c', Character.EPSILON }); - try grammar.non_terminal_by_id(1).first.expect(&[_]u9 { 'a', 'c' }); - try grammar.non_terminal_by_id(2).first.expect(&[_]u9 { 'a', 'b' }); + try grammar.non_terminal_by_id(1).first.expect(&[_]u9 { 'a', 'b', 'c', Character.EPSILON }); + try grammar.non_terminal_by_id(2).first.expect(&[_]u9 { 'a', 'c' }); + try grammar.non_terminal_by_id(3).first.expect(&[_]u9 { 'a', 'b' }); - try grammar.non_terminal_by_id(0).follows.expect(&[_]u9 { 'd', Character.END }); - try grammar.non_terminal_by_id(1).follows.expect(&[_]u9 { 'a', 'b', 'c', 'd' }); - try grammar.non_terminal_by_id(2).follows.expect(&[_]u9 { 'a', 'b', 'c', 'd', Character.END }); + try grammar.non_terminal_by_id(1).follows.expect(&[_]u9 { 'd', Character.END }); + try grammar.non_terminal_by_id(2).follows.expect(&[_]u9 { 'a', 'b', 'c', 'd' }); + try grammar.non_terminal_by_id(3).follows.expect(&[_]u9 { 'a', 'b', 'c', 'd', Character.END }); } |