def init(): from collections import defaultdict from Skoarcery.dragonsets import FIRST, FOLLOW from Skoarcery.terminals import Empty, EOF global M # M[ Nonterm, Term ] = Production M = defaultdict(dict) # (1) For each production A -> alpha # for A in nonterminals.nonterminals.values(): for P in A.production_rules: alpha = P.production # (2) for a in FIRST(alpha): if a != Empty: X = M[A, a] if X: raise Not_LL_1 M[A, a] = P # (3) else: for b in FOLLOW(A): X = M[A, b] if X: raise Not_LL_1 M[A, b] = P
def test_PY_rdpp(self): from Skoarcery.dragonsets import FIRST, FOLLOW from Skoarcery.terminals import Empty fd = open("SkoarPyon/rdpp.py", "w") PY = emissions.PY PY.fd = fd # Header # Imports # class SkoarParseException # class SkoarParser: # __init__ # fail self.code_start() PY.tab += 1 N = nonterminals.nonterminals.values() # precompute desirables PY.method("init_desirables") for A in N: R = A.production_rules PY.nl() PY.cmt(str(A)) # each production for P in R: if P.derives_empty: continue # A -> alpha alpha = P.production desires = FIRST(alpha) if Empty in desires: desires.discard(Empty) desires.update(FOLLOW(A)) i = 0 n = len(desires) PY.dict_set("self.desirables", str(P), "[", end="") for toke in desires: PY.raw(toke.toker_name) i += 1 if i != n: if i % 5 == 0: PY.raw(",\n") PY.stmt(" ", end="") else: PY.raw(", ") else: PY.raw("]\n") PY.end() # write each nonterminal as a function for A in N: R = A.production_rules #PY.cmt(str(A)) PY.stmt("def " + A.name + "(self, parent):") PY.tab += 1 PY.stmt("self.tab += 1") if A.intermediate: PY.var("noad", "parent") else: PY.var("noad", PY.v_new("SkoarNoad", PY.v_sym(A.name), "parent")) PY.nl() #PY.code_line("print('" + A.name + "')") for P in R: if P.derives_empty: continue # A -> alpha alpha = P.production PY.stmt("desires = " + PY.v_dict_get("self.desirables", str(P))) PY.if_("self.toker.sees(desires)") #PY.print(str(P)) for x in alpha: if isinstance(x, Terminal): PY.stmt("noad.add_toke('" + x.toker_name + "', self.toker.burn(" + x.toker_name + "))") #PY.print("burning: " + x.name) else: if x.intermediate: PY.stmt("self." + x.name + "(noad)") else: PY.stmt("noad.add_noad(self." + x.name + "(noad))") else: PY.return_("noad") PY.tab -= 1 PY.nl() if A.derives_empty: PY.cmt("<e>") #PY.print("burning empty") PY.return_("noad") else: PY.cmt("Error State") PY.stmt("self.fail()") PY.tab -= 1 PY.nl() PY.tab -= 1 fd.close()
def test_sc_rdpp(self): from Skoarcery.dragonsets import FIRST, FOLLOW from Skoarcery.terminals import Empty fd = open("../../SuperCollider/Skoar/rdpp.sc", "w") ____SC = SC = emissions.SC SC.fd = fd # Header # Imports # class SkoarParseException # class SkoarParser: # init # fail self.code_start() SC.tab += 1 N = nonterminals.nonterminals.values() # precompute desirables SC.method("init_desirables") for A in N: R = A.production_rules SC.nl() SC.cmt(str(A)) # each production for P in R: if P.derives_empty: continue # A -> alpha alpha = P.production desires = FIRST(alpha) if Empty in desires: desires.discard(Empty) desires.update(FOLLOW(A)) i = 0 n = len(desires) SC.dict_set("desirables", str(P), "[", end="") for toke in desires: SC.raw(toke.toker_name) i += 1 if i != n: if i % 5 == 0: SC.raw(",\n") SC.stmt(" ", end="") else: SC.raw(", ") else: SC.raw("]);\n") SC.end() # write each nonterminal as a function for A in N: R = A.production_rules #SC.cmt(str(A)) SC.method(A.name, "parent") if A.intermediate: SC.var("noad", "parent") else: SC.var("noad", SC.v_new("SkoarNoad", SC.v_sym(A.name), "parent")) SC.var("desires", SC.null) SC.nl() SC.stmt("deep = deep + 1") SC.if_("deep > 100") ____SC.stmt("this.fail_too_deep") SC.end_if() # each production for P in R: if P.derives_empty: continue # A -> alpha alpha = P.production SC.stmt("desires = " + SC.v_dict_get("desirables", str(P))) SC.cmt(str(P)) SC.if_("toker.sees(desires).notNil") # debugging #SC.print(str(P)) for x in alpha: if isinstance(x, Terminal): SC.stmt('noad.add_toke(' + SC.v_sym(x.toker_name) + ', toker.burn(' + x.toker_name + '))') # debugging #SC.print("burning: " + x.name) else: if x.intermediate: SC.stmt(SC.this + "." + x.name + "(noad)") else: SC.stmt("noad.add_noad(this." + x.name + "(noad))") else: SC.stmt("deep = deep - 1") SC.return_("noad") SC.end_if() if A.derives_empty: SC.cmt("<e>") # debugging #SC.print("burning empty") SC.stmt("deep = deep - 1") SC.return_("noad") else: SC.cmt("Error State") SC.stmt("this.fail") SC.end() SC.end() fd.close()
def test_pyrdpp(self): from Skoarcery.dragonsets import FIRST, FOLLOW from Skoarcery.terminals import Empty fd = open("../SkoarPyon/rdpp.py", "w") PY = emissions.PY PY.fd = fd # Header # Imports # class SkoarParseException # class SkoarParser: # __init__ # fail self.code_start() PY.tab += 1 N = nonterminals.nonterminals.values() # precompute desirables PY.method("init_desirables") for A in N: R = A.production_rules PY.nl() PY.cmt(str(A)) # each production for P in R: if P.derives_empty: continue # A -> alpha alpha = P.production desires = FIRST(alpha) if Empty in desires: desires.discard(Empty) desires.update(FOLLOW(A)) i = 0 n = len(desires) PY.dict_set("self.desirables", str(P), "[", end="") for toke in desires: PY.raw(toke.toker_name) i += 1 if i != n: if i % 5 == 0: PY.raw(",\n") PY.stmt(" ", end="") else: PY.raw(", ") else: PY.raw("]\n") PY.end() # write each nonterminal as a function for A in N: R = A.production_rules #PY.cmt(str(A)) PY.stmt("def " + A.name + "(self, parent):") PY.tab += 1 PY.stmt("self.tab += 1") if A.intermediate: PY.var("noad", "parent") else: PY.var("noad", PY.v_new("SkoarNoad", PY.v_sym(A.name), "parent")) PY.nl() #PY.code_line("print('" + A.name + "')") for P in R: if P.derives_empty: continue # A -> alpha alpha = P.production PY.stmt("desires = " + PY.v_dict_get("self.desirables", str(P))) PY.if_("self.toker.sees(desires)") #PY.print(str(P)) for x in alpha: if isinstance(x, Terminal): PY.stmt("noad.add_toke('" + x.toker_name + "', self.toker.burn(" + x.toker_name + "))") #PY.print("burning: " + x.name) else: if x.intermediate: PY.stmt("self." + x.name + "(noad)") else: PY.stmt("noad.add_noad(self." + x.name + "(noad))") else: PY.return_("noad") PY.tab -= 1 PY.nl() if A.derives_empty: PY.cmt("<e>") #PY.print("burning empty") PY.return_("noad") else: PY.cmt("Error State") PY.stmt("self.fail()") PY.tab -= 1 PY.nl() PY.tab -= 1 fd.close()
def test_make_table(self): from collections import defaultdict from Skoarcery.dragonsets import FIRST, FOLLOW from Skoarcery.terminals import Empty, EOF # M[ Nonterm, Term ] = Production M = defaultdict(dict) duplicates = 0 # (1) For each production A -> alpha # print("for each production P = A -> alpha:") for A in nonterminals.nonterminals.values(): M[A] = [] for P in A.production_rules: alpha = P.production print("\n P = " + str(P)) # # (2) # print(" for a in FIRST(alpha):") for a in FIRST(alpha): if a != Empty: X = M[A, a] if X: print("") print( " #### Grammar is not LL(1). Whoopsiedaisies. ####-----------------------" ) print("") print(" M[{}, {}]:".format(A.name, a.name)) print(" " + str(X)) print(" " + str(P)) print("") #print("X = {}\nP = {}\nA = {}\na = {}".format(str(X), str(P), str(A), str(a))) duplicates += 1 print(" M[A,a] = M[{}, {}] = P".format( A.name, a.name)) M[A, a] = P # (3) else: print(" <e>, so for b in FOLLOW(A):") for b in FOLLOW(A): X = M[A, b] if X: print("") print( " #### Grammar is not LL(1). Whoopsiedaisies. ####-----------------------" ) print("") print(" M[{}, {}]:".format( A.name, b.name)) print(" " + str(X)) print(" " + str(P)) print("") #print("X = {}\nP = {}\nA = {}\nb = {}".format(str(X), str(P), str(A), str(b))) #raise AssertionError("3) Grammar is not LL(1). F**k.") duplicates += 1 print(" M[A,b] = M[{}, {}] = P".format( A.name, b.name)) M[A, b] = P self.assertTrue( duplicates is 0, str(duplicates) + " duplicate entries: Grammar is not LL(1).")