Skip to content

Commit

Permalink
atomic, narrow/widen, chain/unchain, replace (only cases natural to R…
Browse files Browse the repository at this point in the history
…ascal visitor) (re)done
  • Loading branch information
grammarware committed Jun 2, 2012
1 parent a3da9b3 commit d170127
Show file tree
Hide file tree
Showing 17 changed files with 395 additions and 118 deletions.
160 changes: 123 additions & 37 deletions shared/rascal/src/transform/XBGF.rsc
Expand Up @@ -110,12 +110,15 @@ BGFGrammar runAddV(BGFProduction p1, grammar(roots, ps))
{
if (production(_,str x,_) := p1)
{
<ps1,ps2,ps3> = splitN(ps,x);
<ps1,ps2,ps3> = splitPbyW(ps,innt(x));
//ps2 = [p | p <- ps, production(_,x,_) := p];
if (isEmpty(ps2))
throw "Nonterminal <x> must be defined.";
if (p1 in ps2)
throw "Production rule <p1> is already present.";
if (production(str l,_,_) := p1 && l != "")
if (production(str l,_,_) <- ps)
throw "Another production rule with label <l> is already present.";
return grammar(roots, ps1 + ps2 + p1 + ps3);
}
}
Expand All @@ -140,10 +143,19 @@ BGFGrammar runAppear(BGFProduction p1, grammar(roots, ps))
return grammar(roots, ps - p2 + unmark(p1));
}
BGFGrammar runChain(BGFProduction p, BGFGrammar g)
BGFGrammar runChain(BGFProduction p, grammar(roots, ps))
{
// TODO
return g;
if (production(str l,str n1,nonterminal(str n2)) := p)
{
if (n1 == n2) throw "Do not introduce reflexive chain productions with chain, use detour instead.";
if (n2 in allNs(ps)) throw "Nonterminal <n2> must be fresh.";
list[BGFProduction] ps1,ps2,ps3;
if (l != "") <ps1,ps2,ps3> = splitPbyW(ps,inlabel(l));
else <ps1,ps2,ps3> = splitPbyW(ps,innt(n1));
if ([production(l,n1,e)] := ps2) return grammar(roots, ps1 + p + production("",n2,e) + ps3);
else throw "Production rule <ps2> has unexpected form.";
}
else throw "Production <p> must be a chain production.";
}
BGFGrammar runClone(str x, str y, XBGFContext w, BGFGrammar g)
Expand Down Expand Up @@ -305,10 +317,11 @@ BGFGrammar runMassage(BGFExpression e1, BGFExpression e2, XBGFContext w, BGFGram
return g;
}
BGFGrammar runNarrow(BGFExpression e1, BGFExpression e2, XBGFContext w, BGFGrammar g)
BGFGrammar runNarrow(BGFExpression e1, BGFExpression e2, XBGFContext w, g)
{
// TODO
return g;
if (!narrowing(e1,e2))
throw "<e1> and <e2> are not in narrowing relation.";
return runReplace(e1,e2,w,g);
}
BGFGrammar runPermute(BGFProduction p, BGFGrammar g)
Expand Down Expand Up @@ -351,7 +364,7 @@ BGFGrammar runRemoveV(BGFProduction p1, grammar(roots, ps))
{
if (production(_,str x,_) := p1)
{
<_,ps2,_> = splitN(ps,x);
<_,ps2,_> = splitPbyW(ps,innt(x));
if (isEmpty(ps2))
throw "Nonterminal <x> must be defined.";
if (p1 notin ps2)
Expand Down Expand Up @@ -386,10 +399,16 @@ BGFGrammar runRenameT(str x, str y, XBGFContext w, BGFGrammar g)
return g;
}
BGFGrammar runReplace(BGFExpression e1, BGFExpression e2, XBGFContext w, BGFGrammar g)
BGFGrammar runReplace(BGFExpression e1, BGFExpression e2, XBGFContext w, grammar(roots, ps))
{
// TODO
return g;
<ps1,ps2,ps3> = splitPbyW(ps,w);
e3 = normalise(e1);
e4 = normalise(e2);
//println(ps);
ps4 = visit(ps2){case e3 => e4};
if (ps2 == ps4)
throw "Vacuous replace of <e3> by <e4> in context <w>.";
return grammar(roots, ps1 + ps4 + ps3);
}
BGFGrammar runReroot(list[str] xs, BGFGrammar g)
Expand All @@ -410,12 +429,23 @@ BGFGrammar runSplitT(str x, list[str] ys, XBGFContext w, BGFGrammar g)
return g;
}
BGFGrammar runUnchain(BGFProduction p, BGFGrammar g)
BGFGrammar runUnchain(BGFProduction p, grammar(roots, ps))
{
// TODO
return g;
if (production(str l,str n1,nonterminal(str n2)) := p)
{
if (n1 == n2) throw "Do not remove reflexive chain productions with chain, use abridge instead.";
if (n2 in roots) throw "Nonterminal <n2> must not be root.";
if (p notin ps) throw "<p> not found.";
//if (n2 in allNs(ps)) throw "Nonterminal <n2> must be fresh.";
list[BGFProduction] ps1,ps2,ps3;
<ps1,ps2,ps3> = splitPbyW(ps - p,innt(n2));
if (size(ps2) != 1) throw "Nonterminal <n2> must occur exactly once.";
if (l == "") l = n2;
if ([production(_,n2,e)] := ps2) return grammar(roots, ps1 + production(l,n1,e) + ps3);
else throw "Production rule <ps2> has unexpected form.";
}
else throw "Production <p> must be a chain production.";
}
BGFGrammar runUndefine(list[str] xs, BGFGrammar g)
{
// TODO
Expand Down Expand Up @@ -454,8 +484,9 @@ BGFGrammar runVertical(XBGFContext w, BGFGrammar g)
BGFGrammar runWiden(BGFExpression e1, BGFExpression e2, XBGFContext w, BGFGrammar g)
{
// TODO
return g;
if (!narrowing(e2,e1))
throw "<e2> and <e1> are not in widening relation.";
return runReplace(e1,e2,w,g);
}
BGFGrammar runYaccify(list[BGFProduction] ps, BGFGrammar g)
Expand All @@ -464,11 +495,7 @@ BGFGrammar runYaccify(list[BGFProduction] ps, BGFGrammar g)
return g;
}
BGFGrammar runAtomic(list[XBGFCommand] steps, BGFGrammar g)
{
// TODO
return g;
}
BGFGrammar runAtomic(list[XBGFCommand] steps, BGFGrammar g) = transform(steps,g);
BGFGrammar runStrip(str a, BGFGrammar g)
{
Expand Down Expand Up @@ -512,22 +539,81 @@ BGFProduction demarkS (BGFProduction p1)
return normalise(p2);
}
tuple[list[BGFProduction],list[BGFProduction],list[BGFProduction]] splitN(list[BGFProduction] ps, str x)
{
//tuple[list[BGFProduction],list[BGFProduction],list[BGFProduction]] splitN(list[BGFProduction] ps, str x)
//{
// bool hit = false;
// list[BGFProduction] ps1 = [];
// list[BGFProduction] ps2 = [];
// list[BGFProduction] ps3 = [];
// for (p <- ps)
// if (production (_,x,_) := p)
// {
// hit = true;
// ps2 += p;
// }
// elseif (hit)
// ps3 += p;
// else
// ps1 += p;
// return <ps1,ps2,ps3>;
//}
// order-preserving splitting of production rules
// returns <prods before context; prods in context; prods after context>
tuple[list[BGFProduction],list[BGFProduction],list[BGFProduction]] splitPbyW(list[BGFProduction] ps, XBGFContext w)
{
if (globally() := w)
return <[],ps,[]>;
if (inlabel(str x) := w && x == "")
throw "Empty label is not a proper context.";
bool hit = false;
list[BGFProduction] ps1 = [];
list[BGFProduction] ps2 = [];
list[BGFProduction] ps3 = [];
for (p <- ps)
if (production (_,x,_) := p)
{
hit = true;
ps2 += p;
}
elseif (hit)
ps3 += p;
else
ps1 += p;
list[BGFProduction] ps1 = [], ps2 = [], ps3 = [];
if (innt(str x) := w)
for (p <- ps)
if (production (_,x,_) := p)
{
hit = true;
ps2 += p;
}
elseif (hit)
ps3 += p;
else
ps1 += p;
elseif (inlabel(str x) := w)
for (p <- ps)
if (production (x,_,_) := p)
{
hit = true;
ps2 += p;
}
elseif (hit)
ps3 += p;
else
ps1 += p;
else throw "Unknown context <w>.";
if (isEmpty(ps2))
throw "Context <w> not found.";
return <ps1,ps2,ps3>;
}
// narrow-equivalence (the reverse, widen-equivalence, is hereby also implicitly defined)
bool narrowing(anything(),_) = true;
bool narrowing(star(e),plus(e)) = true;
bool narrowing(star(e),optional(e)) = true;
bool narrowing(star(e),e) = true;
bool narrowing(plus(e),e) = true;
bool narrowing(optional(e),e) = true;
bool narrowing(_,_) = false;
list[str] allNs(list[BGFProduction] ps)
{
list[str] ns = [];
// defined
for (production(_,str s,_) <- ps)
if (s notin ns) ns += s;
// used
for (/nonterminal(str s) := ps)
if (s notin ns) ns += s;
return ns;
}
10 changes: 6 additions & 4 deletions shared/rascal/src/transform/XBGFTest.rsc
Expand Up @@ -15,9 +15,10 @@ test bool test_add_vertical_middle() { return transform([addV(production("","exp
test bool test_add_vertical_scattered() { return transform([addV(production("","expr",nonterminal("id")))],grammar([],[production("","foo",terminal("1")),production("","expr",nonterminal("int")),production("","bar",terminal("2")),production("","expr",nonterminal("real")),production("","wez",terminal("3"))]))==grammar([],[production("","foo",terminal("1")),production("","expr",nonterminal("int")),production("","expr",nonterminal("real")),production("","expr",nonterminal("id")),production("","bar",terminal("2")),production("","wez",terminal("3"))]); }
test bool test_anonymize_multiple() { return transform([anonymize(production("","A",sequence([selectable("first",terminal("a")),marked(selectable("second",terminal("a"))),marked(selectable("third",terminal("a")))])))],grammar([],[production("","A",sequence([selectable("first",terminal("a")),selectable("second",terminal("a")),selectable("third",terminal("a"))]))]))==grammar([],[production("","A",sequence([selectable("first",terminal("a")),terminal("a"),terminal("a")]))]); }
test bool test_anonymize_single() { return transform([anonymize(production("unary","expr",sequence([marked(selectable("op",nonterminal("unary_op"))),nonterminal("expr")])))],grammar([],[production("binary","expr",sequence([terminal("("),nonterminal("expr"),selectable("op",nonterminal("binary_op")),nonterminal("expr"),terminal(")")])),production("unary","expr",sequence([selectable("op",nonterminal("unary_op")),nonterminal("expr")]))]))==grammar([],[production("binary","expr",sequence([terminal("("),nonterminal("expr"),selectable("op",nonterminal("binary_op")),nonterminal("expr"),terminal(")")])),production("unary","expr",sequence([nonterminal("unary_op"),nonterminal("expr")]))]); }
test bool test_appear_q() { return transform([appear(production("","foo",sequence([nonterminal("bar"),marked(optional(nonterminal("qux")))])))],grammar([],[production("","foo",sequence([nonterminal("bar")]))]))==grammar([],[production("","foo",sequence([nonterminal("bar"),optional(nonterminal("qux"))]))]); }
test bool test_appear_s() { return transform([appear(production("","foo",sequence([nonterminal("bar"),marked(star(nonterminal("qux")))])))],grammar([],[production("","foo",sequence([nonterminal("bar")]))]))==grammar([],[production("","foo",sequence([nonterminal("bar"),star(nonterminal("qux"))]))]); }
test bool test_chain() { return transform([chain(production("binary","expr",nonterminal("binexpr")))],grammar([],[production("constant","expr",nonterminal("int")),production("binary","expr",sequence([nonterminal("expr"),nonterminal("op"),nonterminal("expr")]))]))==grammar([],[production("constant","expr",nonterminal("int")),production("binary","expr",nonterminal("binexpr")),production("","binexpr",sequence([nonterminal("expr"),nonterminal("op"),nonterminal("expr")]))]); }
test bool test_appear_q() { return transform([appear(production("","foo",sequence([nonterminal("bar"),marked(optional(nonterminal("qux")))])))],grammar([],[production("","foo",nonterminal("bar"))]))==grammar([],[production("","foo",sequence([nonterminal("bar"),optional(nonterminal("qux"))]))]); }
test bool test_appear_s() { return transform([appear(production("","foo",sequence([nonterminal("bar"),marked(star(nonterminal("qux")))])))],grammar([],[production("","foo",nonterminal("bar"))]))==grammar([],[production("","foo",sequence([nonterminal("bar"),star(nonterminal("qux"))]))]); }
test bool test_chain_l() { return transform([chain(production("binary","expr",nonterminal("binexpr")))],grammar([],[production("constant","expr",nonterminal("int")),production("binary","expr",sequence([nonterminal("expr"),nonterminal("op"),nonterminal("expr")]))]))==grammar([],[production("constant","expr",nonterminal("int")),production("binary","expr",nonterminal("binexpr")),production("","binexpr",sequence([nonterminal("expr"),nonterminal("op"),nonterminal("expr")]))]); }
test bool test_chain_n() { return transform([chain(production("","ClassDeclaration",nonterminal("NormalClassDeclaration")))],grammar([],[production("","ClassDeclaration",sequence([terminal("class"),nonterminal("Identifier"),nonterminal("ClassBody")])),production("","ClassBody",sequence([terminal("{"),optional(nonterminal("ClassBodyDeclarations")),terminal("}")]))]))==grammar([],[production("","ClassDeclaration",nonterminal("NormalClassDeclaration")),production("","NormalClassDeclaration",sequence([terminal("class"),nonterminal("Identifier"),nonterminal("ClassBody")])),production("","ClassBody",sequence([terminal("{"),optional(nonterminal("ClassBodyDeclarations")),terminal("}")]))]); }
test bool test_concretize() { return transform([concretize(production("","A",sequence([nonterminal("b"),marked(terminal("x")),nonterminal("c")])))],grammar([],[production("","A",sequence([nonterminal("b"),nonterminal("c")]))]))==grammar([],[production("","A",sequence([nonterminal("b"),terminal("x"),nonterminal("c")]))]); }
test bool test_deanonymize_multiple() { return transform([deanonymize(production("","A",sequence([selectable("first",terminal("a")),marked(selectable("second",terminal("a"))),marked(selectable("third",terminal("a")))])))],grammar([],[production("","A",sequence([selectable("first",terminal("a")),terminal("a"),terminal("a")]))]))==grammar([],[production("","A",sequence([selectable("first",terminal("a")),selectable("second",terminal("a")),selectable("third",terminal("a"))]))]); }
test bool test_deanonymize_single() { return transform([deanonymize(production("unary","expr",sequence([marked(selectable("op",nonterminal("unary_op"))),nonterminal("expr")])))],grammar([],[production("constant","expr",selectable("value",nonterminal("int"))),production("binary","expr",sequence([terminal("("),nonterminal("expr"),selectable("op",nonterminal("binary_op")),nonterminal("expr"),terminal(")")])),production("unary","expr",sequence([nonterminal("unary_op"),nonterminal("expr")]))]))==grammar([],[production("constant","expr",selectable("value",nonterminal("int"))),production("binary","expr",sequence([terminal("("),nonterminal("expr"),selectable("op",nonterminal("binary_op")),nonterminal("expr"),terminal(")")])),production("unary","expr",sequence([selectable("op",nonterminal("unary_op")),nonterminal("expr")]))]); }
Expand Down Expand Up @@ -125,7 +126,8 @@ test bool test_split3() { return transform([splitN("foo",[production("D","bar",n
test bool test_split4() { return transform([splitN("foo",[production("D","bar",nonterminal("foo"))],inlabel("B"))],grammar([],[production("A","foo",terminal("a")),production("B","foo",nonterminal("foo")),production("D","foo",nonterminal("foo"))]))==grammar([],[production("A","foo",terminal("a")),production("B","foo",nonterminal("bar")),production("D","bar",nonterminal("foo"))]); }
test bool test_strip2() { return transform([strip("allLabels")],grammar([],[production("constant","expr",selectable("value",nonterminal("int"))),production("binary","expr",sequence([terminal("("),nonterminal("expr"),selectable("op",nonterminal("binary_op")),nonterminal("expr"),terminal(")")])),production("unary","expr",sequence([selectable("op",nonterminal("unary_op")),nonterminal("expr")]))]))==grammar([],[production("","expr",selectable("value",nonterminal("int"))),production("","expr",sequence([terminal("("),nonterminal("expr"),selectable("op",nonterminal("binary_op")),nonterminal("expr"),terminal(")")])),production("","expr",sequence([selectable("op",nonterminal("unary_op")),nonterminal("expr")]))]); }
test bool test_strip4() { return transform([strip("allSelectors")],grammar([],[production("constant","expr",selectable("value",nonterminal("int"))),production("binary","expr",sequence([terminal("("),nonterminal("expr"),selectable("op",nonterminal("binary_op")),nonterminal("expr"),terminal(")")])),production("unary","expr",sequence([selectable("op",nonterminal("unary_op")),nonterminal("expr")]))]))==grammar([],[production("constant","expr",nonterminal("int")),production("binary","expr",sequence([terminal("("),nonterminal("expr"),nonterminal("binary_op"),nonterminal("expr"),terminal(")")])),production("unary","expr",sequence([nonterminal("unary_op"),nonterminal("expr")]))]); }
test bool test_unchain() { return transform([unchain(production("binary","expr",nonterminal("binexpr")))],grammar([],[production("constant","expr",nonterminal("int")),production("binary","expr",nonterminal("binexpr")),production("","binexpr",sequence([nonterminal("expr"),nonterminal("op"),nonterminal("expr")]))]))==grammar([],[production("constant","expr",nonterminal("int")),production("binary","expr",sequence([nonterminal("expr"),nonterminal("op"),nonterminal("expr")]))]); }
test bool test_unchain_l() { return transform([unchain(production("binary","expr",nonterminal("binexpr")))],grammar([],[production("constant","expr",nonterminal("int")),production("binary","expr",nonterminal("binexpr")),production("","binexpr",sequence([nonterminal("expr"),nonterminal("op"),nonterminal("expr")]))]))==grammar([],[production("constant","expr",nonterminal("int")),production("binary","expr",sequence([nonterminal("expr"),nonterminal("op"),nonterminal("expr")]))]); }
test bool test_unchain_n() { return transform([unchain(production("","ClassDeclaration",nonterminal("NormalClassDeclaration")))],grammar([],[production("","ClassDeclaration",nonterminal("NormalClassDeclaration")),production("","NormalClassDeclaration",sequence([terminal("class"),nonterminal("Identifier"),nonterminal("ClassBody")])),production("","ClassBody",sequence([terminal("{"),optional(nonterminal("ClassBodyDeclarations")),terminal("}")]))]))==grammar([],[production("NormalClassDeclaration","ClassDeclaration",sequence([terminal("class"),nonterminal("Identifier"),nonterminal("ClassBody")])),production("","ClassBody",sequence([terminal("{"),optional(nonterminal("ClassBodyDeclarations")),terminal("}")]))]); }
test bool test_undefine1() { return transform([undefine(["op"])],grammar([],[production("","expr",nonterminal("int")),production("","expr",sequence([nonterminal("expr"),nonterminal("op"),nonterminal("expr")])),production("","op",terminal("+")),production("","op",terminal("-"))]))==grammar([],[production("","expr",nonterminal("int")),production("","expr",sequence([nonterminal("expr"),nonterminal("op"),nonterminal("expr")]))]); }
test bool test_undefine2() { return transform([undefine(["bar","qux"])],grammar([],[production("","foo",nonterminal("bar")),production("","bar",nonterminal("wez")),production("","wez",nonterminal("qux")),production("","qux",nonterminal("foo"))]))==grammar([],[production("","foo",nonterminal("bar")),production("","wez",nonterminal("qux"))]); }
test bool test_unfold() { return transform([unfold("bar",globally())],grammar([],[production("l1","foo",nonterminal("bar")),production("l2","qux",nonterminal("bar")),production("","bar",star(nonterminal("wez")))]))==grammar([],[production("l1","foo",star(nonterminal("wez"))),production("l2","qux",star(nonterminal("wez"))),production("","bar",star(nonterminal("wez")))]); }
Expand Down
34 changes: 0 additions & 34 deletions topics/transformation/xbgf/tests/chain.baseline

This file was deleted.

33 changes: 33 additions & 0 deletions topics/transformation/xbgf/tests/chain_l.baseline
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<bgf:grammar xmlns:bgf="http://planet-sl.org/bgf">
<bgf:production>
<label>constant</label>
<nonterminal>expr</nonterminal>
<bgf:expression>
<nonterminal>int</nonterminal>
</bgf:expression>
</bgf:production>
<bgf:production>
<label>binary</label>
<nonterminal>expr</nonterminal>
<bgf:expression>
<nonterminal>binexpr</nonterminal>
</bgf:expression>
</bgf:production>
<bgf:production>
<nonterminal>binexpr</nonterminal>
<bgf:expression>
<sequence>
<bgf:expression>
<nonterminal>expr</nonterminal>
</bgf:expression>
<bgf:expression>
<nonterminal>op</nonterminal>
</bgf:expression>
<bgf:expression>
<nonterminal>expr</nonterminal>
</bgf:expression>
</sequence>
</bgf:expression>
</bgf:production>
</bgf:grammar>
@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<bgf:grammar xmlns:bgf="http://planet-sl.org/bgf">
<bgf:production>
<label>constant</label>
Expand Down
@@ -1,6 +1,5 @@
<xbgf:sequence
xmlns:bgf="http://planet-sl.org/bgf"
xmlns:xbgf="http://planet-sl.org/xbgf">
<?xml version="1.0" encoding="UTF-8"?>
<xbgf:sequence xmlns:bgf="http://planet-sl.org/bgf" xmlns:xbgf="http://planet-sl.org/xbgf">
<xbgf:chain>
<bgf:production>
<label>binary</label>
Expand Down

0 comments on commit d170127

Please sign in to comment.