use package core.string.reader as reader
// nt -> t
-Unit :: struct {
+Term :: struct {
nt : u32;
t : u8; // character
}
// nt0 -> nt1
-Solo :: struct {
+Unit :: struct {
nt0 : u32;
nt1 : u32;
}
Grammar :: struct {
- unitary_rules : [..] Unit;
- solo_rules : [..] Solo;
+ terminate_rules : [..] Term;
+ unit_rules : [..] Unit;
production_rules : [..] Prod;
max_terminal : u32;
}
grammar_init :: proc (use g: ^Grammar) {
- array.init(^unitary_rules);
- array.init(^solo_rules);
+ array.init(^terminate_rules);
+ array.init(^unit_rules);
array.init(^production_rules);
max_terminal = 0;
}
+grammar_free :: proc (use g: ^Grammar) {
+ array.free(^terminate_rules);
+ array.free(^unit_rules);
+ array.free(^production_rules);
+}
+
grammar_prepare :: proc (use g: ^Grammar) {
// Not full-proof, but good enough for AOC.
- for ^solo: solo_rules {
+ for ^solo: unit_rules {
for ^prod: production_rules {
if prod.nt0 == solo.nt1 {
array.push(^production_rules, Prod.{ solo.nt0, prod.nt1, prod.nt2 });
}
}
- for ^unit: unitary_rules {
+ for ^unit: terminate_rules {
if unit.nt == solo.nt1 {
- array.push(^unitary_rules, Unit.{ solo.nt0, unit.t });
+ array.push(^terminate_rules, Term.{ solo.nt0, unit.t });
}
}
}
- array.sort(^unitary_rules, proc (a: Unit, b: Unit) -> i32 {
+ array.sort(^terminate_rules, proc (a: Term, b: Term) -> i32 {
return (cast(i32) a.nt) - (cast(i32) b.nt);
});
max_terminal = math.max(
production_rules[production_rules.count - 1].nt0,
- unitary_rules[unitary_rules.count - 1].nt) + 1;
+ terminate_rules[terminate_rules.count - 1].nt) + 1;
}
-cyk_algorithm :: proc (use grammar: ^Grammar, input: str) -> bool #export "CYK" {
+cyk_algorithm :: proc (use grammar: ^Grammar, input: str) -> bool {
dim_0 := input.count * max_terminal;
dim_1 := max_terminal;
dim_2 := 1;
memory.set(T, mem_size, ~~false);
for s: 0 .. input.count {
- for ^unit: unitary_rules {
- if unit.t == input[s] {
- T[0 * dim_0 + s * dim_1 + unit.nt * dim_2] = true;
+ for ^term: terminate_rules {
+ if term.t == input[s] {
+ T[0 * dim_0 + s * dim_1 + term.nt * dim_2] = true;
}
}
}
grammar : Grammar;
grammar_init(^grammar);
+ defer grammar_free(^grammar);
while *file.data != #char "\n" {
nt0 := reader.read_u32(^file);
reader.skip_bytes(^file, 1); // '"'
t := reader.read_byte(^file);
- array.push(^grammar.unitary_rules, Unit.{ ~~nt0, t });
+ array.push(^grammar.terminate_rules, Term.{ nt0, t });
} else {
while true {
nt1 := reader.read_u32(^file);
if *file.data == #char "\n" {
- array.push(^grammar.solo_rules, Solo.{ ~~nt0, ~~nt1 });
+ array.push(^grammar.unit_rules, Unit.{ nt0, nt1 });
break;
} else {
if next_ch := *file.data; next_ch >= #char "0" && next_ch <= #char "9" {
nt2 := reader.read_u32(^file);
- array.push(^grammar.production_rules, Prod.{ ~~nt0, ~~nt1, ~~nt2 });
+ array.push(^grammar.production_rules, Prod.{ nt0, nt1, nt2 });
if *file.data == #char " " do reader.skip_bytes(^file, 1);
} else {
- array.push(^grammar.solo_rules, Solo.{ ~~nt0, ~~nt1 });
+ array.push(^grammar.unit_rules, Unit.{ nt0, nt1 });
}
if *file.data == #char "|" {
grammar_prepare(^grammar);
- for ^p: grammar.production_rules do printf("%i -> %i %i\n", p.nt0, p.nt1, p.nt2);
- for ^p: grammar.unitary_rules do printf("%i -> %c\n", p.nt, p.t);
-
valid_count := 0;
-
reader.advance_line(^file);
while !reader.empty(^file) {
line := reader.read_line(^file);
-
- is_valid := cyk_algorithm(^grammar, line);
- if is_valid do valid_count += 1;
+ if cyk_algorithm(^grammar, line) do valid_count += 1;
}
printf("Valid count: %i\n", valid_count);