from itertools import product delta = """ S := AB | ABA A := aA | a B := Bb | eps """ class rule: __slots__ = ['left', 'right'] def __init__(self, left, right, sep=""): self.left = left self.right = [c for c in right] if right != "eps" else [] def __str__(self): return self.left + " := " + ''.join(self.right) def __hash__(self): return hash(str(self)) def __eq__(self, other): return self.left == other.left and self.right == other.right def parse(grammer): grammer = grammer.strip() terminals = set() non_terms = set() rules = set() for line in grammer.split("\n"): N, rule_list = line.split(":=") rules |= {rule(N.strip(), right.strip()) for right in rule_list.split("|")} non_terms |= {N} for r in rules: if r.right != 'eps': terminals |= {T for T in r.right if T.islower()} return rules, terminals, non_terms P, T, N = parse(delta) # print(('\n'.join(map(str, P)))) # print() letters_to_kill = {p.left for p in P if not p.right} new_P = set() | P for p in P: for l in letters_to_kill: n = p.right.count(l) r = ''.join(p.right).replace(l, "{}") # 0 is a placeholder for empty string for prod in product(l + "0", repeat=n): new_P |= {rule(p.left, r.format(*prod).replace("0", ""))} P = {p for p in new_P if p.right} # print(('\n'.join(map(str, P)))) # print() for t in T: P |= {rule("T_" + t, t)} # print(T) new_P = set() | P for p in P: p.right = ["T_" + p if p in T else p for p in p.right] P = new_P # print(('\n'.join(map(str, P)))) # print() new_P = set() | P for p in P: if len(p.right) > 2: pass ### END OF SCRIPT ############################################################## meta = { "type" : "GAP", "title" : "Grammatik in Chomsky Normalform umwandeln", "author" : "Jan Maximilian Michal", "gapLength" : 10, "question" : "Empty", "solution" : "TODO", }