diff --git a/shared/rascal/src/export/BNF.rsc b/shared/rascal/src/export/BNF.rsc index 57101784..e3016aef 100644 --- a/shared/rascal/src/export/BNF.rsc +++ b/shared/rascal/src/export/BNF.rsc @@ -21,7 +21,7 @@ public str pp(BGFProdList ps) public str pp(BGFProduction p) = (p.label!="" ? "[] " : "") - + " ::= "; + + " ::= ;"; public str pp(BGFExprList es) { diff --git a/shared/rascal/src/lib/Rascalware.rsc b/shared/rascal/src/lib/Rascalware.rsc index 77fad351..95ab8f32 100644 --- a/shared/rascal/src/lib/Rascalware.rsc +++ b/shared/rascal/src/lib/Rascalware.rsc @@ -8,14 +8,14 @@ import List; import IO; // one length to rule them all -public int len(list[&T] l) = List::size(l); -public int len(set[&T] l) = Set::size(l); -public int len(rel[&T,&T] l) = Relation::size(l); +public int len(list[&T] x) = List::size(x); +public int len(set[&T] x) = Set::size(x); +public int len(rel[&T,&T] x) = Relation::size(x); // one isempty to rule them all -public bool isEmpty(list[&T] l) = List::isEmpty(l); -public bool isEmpty(set[&T] l) = Set::isEmpty(l); -public bool isEmpty(rel[&T,&T] l) = Relation::isEmpty(l); +public bool isEmpty(list[&T] x) = List::isEmpty(x); +public bool isEmpty(set[&T] x) = Set::isEmpty(x); +public bool isEmpty(rel[&T,&T] x) = Relation::isEmpty(x); public void print(str s) = IO::print(s); public void println(str s) = IO::println(s); @@ -26,3 +26,6 @@ public str joinStrings(list[str] ss, str w) = (ss[0] | it + w + s | s <- tail(ss //public bool multiseteq(list[&T] xs, list[&T] ys) = sort(xs) == sort(ys); public bool multiseteq(list[&T] xs, list[&T] ys) = sort(xs) == sort(ys); //} + +public set[&T] toSet(list[&T] x) = List::toSet(x); +public list[&T] toList(set[&T] x) = Set::toList(x); diff --git a/shared/rascal/src/normal/ANF.rsc b/shared/rascal/src/normal/ANF.rsc index 088c17e3..fb90df2d 100644 --- a/shared/rascal/src/normal/ANF.rsc +++ b/shared/rascal/src/normal/ANF.rsc @@ -8,12 +8,12 @@ import syntax::CBGF; import transform::CBGF; import transform::XBGF; import analyse::Metrics; -import Set; -import List; -import IO; //debug +import lib::Rascalware; import io::WriteBGF; // batch import io::WriteCBGF; // batch import io::ReadBGF; // batch +import export::BNF; +import IO; CBGFSequence normalise(BGFGrammar g) = (topNs(g) - leafNs(g) == toSet(g.roots) @@ -32,7 +32,7 @@ CBGFSequence normAllStages(BGFGrammar gr) dropAllLabels, dropAllSelectors, dropAllTerminals, - dropAllHorizontals, + //dropAllHorizontals, dropAllUnknowns, dropAllChains ]) @@ -45,7 +45,58 @@ CBGFSequence normAllStages(BGFGrammar gr) } c += c1; } while (!isEmpty(c1)); - return c; + // TODO check for horizontal/vertical issue + // now g is normalised, but with possibly multiple productions per nonterminal + for (n <- definedNs(g)) + { + ps = prodsOfN(n,g.prods); + //println(""); + if (len(ps)>1) + { + // go over all vertical production rules + for (p <- ps) + if (nonterminal(_) !:= p.rhs) + { + c2 = [extract_inline(production("",uniqueName(n,allNs(g)),p.rhs),innt(n))]; + // global extract can introduce conflicts with subsequent extracts, + // that's why we need to transform immediately + g = transform(forward(c2),g); + c1 += c2; + } + c1 += horizontal_vertical(innt(n)); + } + elseif (production(_,n,choice(L)) := ps[0]) + { + //println("Horizontal!"); + // go over all horizontal production rules + for (e <- L) + if (nonterminal(_) !:= e) + { + c2 = [extract_inline(production("",uniqueName(n,allNs(g)),e),innt(n))]; + // global extract can introduce conflicts with subsequent extracts, + // that's why we need to transform immediately + g = transform(forward(c2),g); + c1 += c2; + } + } + //else + // iprintln(ps); + } + //iprintln(c1); + // now we can have constuctions like this: + // expression ::= (expression1 | expression2 | expression3 | expression | id | number) ; + // with cleverly hidden reflexive chain rules + for (p <- g.prods, production(str l,str n,choice(L)) := p, [*L1,nonterminal(n),*L2] := L) + // the last expression is a traceable variant of "nonterminal(n) in L" + c1 += removeH_addH(production(l,n,choice([*L1, marked(nonterminal(n)), *L2]))); + return c+c1; +} + +str uniqueName(str n, set[str] nts) +{ + int cx = 1; + while ("" in nts) cx += 1; + return ""; } CBGFSequence dropAllLabels(BGFGrammar g) = [unlabel_designate(p) | p <- g.prods, p.label != ""]; @@ -59,7 +110,7 @@ CBGFSequence dropAllUnknowns(BGFGrammar g) { CBGFSequence cbgf = []; set[str] used = usedNs(g.prods); - for (p <- {q | q <- g.prods, epsilon() := q.rhs}) + for (p <- {q | q <- g.prods, (epsilon() := q.rhs || empty() := q.rhs)}) if (p.lhs in used) cbgf += undefine_define([p]); else @@ -85,7 +136,7 @@ BGFProduction markAllTerminals(BGFProduction p) = visit(p) {case terminal(t) => public void main() { for (src <- ["antlr","dcg","ecore","emf","jaxb","om","python","rascal-a","rascal-c","sdf","txl","xsd"]) - //for (src <- ["python"]) + //for (src <- ["txl"]) { println("Reading ..."); BGFGrammar g = readBGF(|home:///projects/slps/topics/convergence/guided/bgf/.bgf|); @@ -96,5 +147,7 @@ public void main() g = transform(forward(c),g); println("Writing output to ..."); writeBGF(g,|home:///projects/slps/topics/convergence/guided/bgf/.normal.bgf|); + writeFile(|home:///projects/slps/topics/convergence/guided/bgf/.normal.bnf|,pp(g)); + //println(pp(g)); } }