Skip to content

Commit

Permalink
a sample negotiated grammar transformation
Browse files Browse the repository at this point in the history
  • Loading branch information
grammarware committed Jun 10, 2012
1 parent e2e6bf1 commit 0f87cc5
Show file tree
Hide file tree
Showing 12 changed files with 282 additions and 103 deletions.
38 changes: 13 additions & 25 deletions shared/rascal/src/Main.rsc
Expand Up @@ -5,34 +5,22 @@ import String;
import IO;
import syntax::BGF;
import syntax::XBGF;
import io::ReadBGF;
import io::ReadXBGF;
import io::WriteXBGF;
import transform::XBGF;
//import lang::xml::DOM;
import diff::GDT;
import transform::library::Test;
import transform::NegotiatedXBGF;

public void main()
{
XBGFSequence x;
x = readXBGF(|project://slps/tests/all/abridge.xbgf|);
println(x);
g1 = readBGF(|project://slps/tests/all/abridge.bgf|);
g2 = readBGF(|project://slps/tests/all/abridge.baseline|);
//writeXBGF(x,|project://slps/tests/all/abridge.bgf|);
g3 = transform(x,g1);
<_,g1,g2> = transform::library::Test::test_data["renameN"];
XBGFSequence x = [renameN("expression","exp")];
//XBGFSequence x = [renameN("expr","int")];

<p,a,g3> = transform::NegotiatedXBGF::attemptTransform(x,g1);
iprintln(x);
println(g1);
println(g3);
println(g2);
}

public bool tryAll()
{
loc base = |project://slps/tests/xbgf|;
loc outp = |project://slps/tests/xbgf-res|;
for (f <- listEntries(base))
{
if (f == ".gitignore") continue;
println(f);
writeXBGF(readXBGF(base+f),outp+f);
}
return true;
println(diff::GDT::gdtv(g3,g2));
println(p);
println(a);
}
4 changes: 2 additions & 2 deletions shared/rascal/src/Sync.rsc
Expand Up @@ -15,7 +15,7 @@ public void main()
loc base = |home:///projects/slps/topics/transformation/xbgf/tests|;
str buffer = "@contributor{Super Awesome Automated XBGF Test Suite Synchroniser}
'@contributor{Vadim Zaytsev - vadim@grammarware.net - SWAT, CWI}
'module transform::XBGFTest
'module transform::library::Test
'
'import IO;
'import syntax::BGF;
Expand All @@ -37,6 +37,6 @@ public void main()
buffer2 += "test bool test_<replaceLast(f,".xbgf","")>() { \<xbgf,bgf1,bgf2\> = test_data[\"<replaceLast(f,".xbgf","")>\"]; return gdts(transform(xbgf,bgf1),bgf2); }\n";
buffer3 += "void show_<replaceLast(f,".xbgf","")>() { \<xbgf,bgf1,bgf2\> = test_data[\"<replaceLast(f,".xbgf","")>\"]; println(\"Input \<bgf1\>\");println(\"Transformations: \<xbgf\>\");println(\"Expected output \<bgf2\>\");bgf3=transform(xbgf,bgf1);println(\"Actual output \<bgf3\>\"); gdtv(bgf3,bgf2); }\n";
}
writeFile(|project://slps/src/transform/XBGFTest.rsc|, replaceLast(buffer,",","")+");\n\n"+buffer3+"\n\n"+buffer2);
writeFile(|project://slps/src/transform/library/Test.rsc|, replaceLast(buffer,",","")+");\n\n"+buffer3+"\n\n"+buffer2);
}

156 changes: 156 additions & 0 deletions shared/rascal/src/transform/NegotiatedXBGF.rsc
@@ -0,0 +1,156 @@
@contributor{Vadim Zaytsev - vadim@grammarware.net - SWAT, CWI}
module transform::NegotiatedXBGF

import IO;
import syntax::BGF;
import syntax::XBGF;
//import diff::GDT;
import List;
import String;
import Integer;
import normal::BGF;
import transform::library::Core;
import transform::library::Util;
import transform::XBGF;

data Problem
= noproblem()
| error(str m);

data Advice
= noadvice()
| setadvice(str s, set[str] a);

public tuple[Problem,Advice,BGFGrammar] attemptTransform(XBGFSequence xbgf, BGFGrammar g)
{
BGFGrammar g1 = normalise(g);
Problem p = noproblem();
Advice a = noadvice();
for (XBGFCommand step <- xbgf)
{
switch(step)
{
case abridge(BGFProduction p): g1 = transform::XBGF::runAbridge(p,g1);
case abstractize(BGFProduction p): g1 = transform::XBGF::runAbstractize(p,g1);
case addH(BGFProduction p): g1 = transform::XBGF::runAddH(p,g1);
case addV(BGFProduction p): g1 = transform::XBGF::runAddV(p,g1);
case anonymize(BGFProduction p): g1 = transform::XBGF::runAnonymize(p,g1);
case appear(BGFProduction p): g1 = transform::XBGF::runAppear(p,g1);
case chain(BGFProduction p): g1 = transform::XBGF::runChain(p,g1);
case clone(str x, str y, XBGFScope w): g1 = transform::XBGF::runClone(x,y,w,g1);
case concatT(list[str] xs, str y, XBGFScope w): g1 = transform::XBGF::runConcatT(xs,y,w,g1);
case concretize(BGFProduction p): g1 = transform::XBGF::runConcretize(p,g1);
case deanonymize(BGFProduction p): g1 = transform::XBGF::runDeanonymize(p,g1);
case define(list[BGFProduction] ps): g1 = transform::XBGF::runDefine(ps,g1);
case designate(BGFProduction p): g1 = transform::XBGF::runDesignate(p,g1);
case detour(BGFProduction p): g1 = transform::XBGF::runDetour(p,g1);
case deyaccify(str x): g1 = transform::XBGF::runDeyaccify(x,g1);
case disappear(BGFProduction p): g1 = transform::XBGF::runDisappear(p,g1);
case distribute(XBGFScope w): g1 = transform::XBGF::runDistribute(w,g1);
case downgrade(BGFProduction p1,BGFProduction p2): g1 = transform::XBGF::runDowngrade(p1,p2,g1);
case eliminate(str x): g1 = transform::XBGF::runEliminate(x,g1);
case equate(str x, str y): g1 = transform::XBGF::runEquate(x,y,g1);
case extract(BGFProduction p, XBGFScope w): g1 = transform::XBGF::runExtract(p,w,g1);
case factor(BGFExpression e1, BGFExpression e2, XBGFScope w): g1 = transform::XBGF::runFactor(e1,e2,w,g1);
case fold(str x, XBGFScope w): g1 = transform::XBGF::runFold(x,w,g1);
case horizontal(XBGFScope w): g1 = transform::XBGF::runHorizontal(w,g1);
case importG(list[BGFProduction] ps): g1 = transform::XBGF::runImportG(ps,g1);
case inject(BGFProduction p): g1 = transform::XBGF::runInject(p,g1);
case inline(str x): g1 = transform::XBGF::runInline(x,g1);
case introduce(list[BGFProduction] ps): g1 = transform::XBGF::runIntroduce(ps,g1);
case iterate(BGFProduction p): g1 = transform::XBGF::runIterate(p,g1);
case lassoc(BGFProduction p): g1 = transform::XBGF::runAssoc(p,g1);
case massage(BGFExpression e1, BGFExpression e2, XBGFScope w): g1 = transform::XBGF::runMassage(e1,e2,w,g1);
case narrow(BGFExpression e1, BGFExpression e2, XBGFScope w): g1 = transform::XBGF::runNarrow(e1,e2,w,g1);
case permute(BGFProduction p): g1 = transform::XBGF::runPermute(p,g1);
case project(BGFProduction p): g1 = transform::XBGF::runProject(p,g1);
case rassoc(BGFProduction p): g1 = transform::XBGF::runAssoc(p,g1);
case redefine(list[BGFProduction] ps): g1 = transform::XBGF::runRedefine(ps,g1);
case removeH(BGFProduction p): g1 = transform::XBGF::runRemoveH(p,g1);
case removeV(BGFProduction p): g1 = transform::XBGF::runRemoveV(p,g1);
case renameL(str x, str y): g1 = transform::XBGF::runRenameL(x,y,g1);

case renameN(str x, str y): <p,a,g1> = runRenameN(x,y,g1);

case renameS(str x, str y, XBGFScope w): g1 = transform::XBGF::runRenameS(x,y,w,g1);
case renameT(str x, str y): g1 = transform::XBGF::runRenameT(x,y,g1);
case replace(BGFExpression e1, BGFExpression e2, XBGFScope w): g1 = transform::XBGF::runReplace(e1,e2,w,g1);
case reroot(list[str] xs): g1 = transform::XBGF::runReroot(xs,g1);
case splitN(str x, list[BGFProduction] ps, XBGFScope w): g1 = transform::XBGF::runSplitN(x,ps,w,g1);
case splitT(str x, list[str] ys, XBGFScope w): g1 = transform::XBGF::runSplitT(x,ys,w,g1);
case unchain(BGFProduction p): g1 = transform::XBGF::runUnchain(p,g1);
case undefine(list[str] xs): g1 = transform::XBGF::runUndefine(xs,g1);
case unfold(str x, XBGFScope w): g1 = transform::XBGF::runUnfold(x,w,g1);
case unite(str x, str y): g1 = transform::XBGF::runUnite(x,y,g1);
case unlabel(str x): g1 = transform::XBGF::runUnlabel(x,g1);
case upgrade(BGFProduction p1, BGFProduction p2): g1 = transform::XBGF::runUpgrade(p1,p2,g1);
case vertical(XBGFScope w): g1 = transform::XBGF::runVertical(w,g1);
case widen(BGFExpression e1, BGFExpression e2, XBGFScope w): g1 = transform::XBGF::runWiden(e1,e2,w,g1);
case yaccify(list[BGFProduction] ps): g1 = transform::XBGF::runYaccify(ps,g1);
case atomic(list[XBGFCommand] steps): g1 = transform::XBGF::runAtomic(steps,g1);
case strip(str a): g1 = transform::XBGF::runStrip(a,g1);
default: throw "Unknown XBGF command <step>";
}
if (noproblem() !:= p)
return <p,a,g1>;
}
return <noproblem(),noadvice(),normalise(g1)>;
}

tuple[Problem,Advice,BGFGrammar] runRenameN(str x, str y, grammar(rs, ps))
{
ns = allNs(ps);
if (x notin ns)
return
<
error("Source name <x> for renaming must not be fresh."),
adviseUsedNonterminal(x,allNs(ps)),
grammar(rs, ps)
>;
if (y in ns)
return
<
error("Target name <y> for renaming must be fresh."),
adviseFreshNonterminal(y,allNs(ps)),
grammar(rs, ps)
>;
return <noproblem(),noadvice(),transform::library::Core::performRenameN(x,y,grammar(rs,ps))>;
}

Advice adviseUsedNonterminal(str x, set[str] nts)
{
int minl = 9000;
str mins = "";
good = {z | z <- nts, levenshtein(z,x) == min([levenshtein(s,x) | s <- nts])};
if (good == {})
return noadvice();
else
return setadvice("Did you mean",good);
}

Advice adviseFreshNonterminal(str x, set[str] nts)
{
list[str] low = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y"];
list[str] upp = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y"];
set[str] adv = {};
int cx = 1;
str s = x;
// expr -> expr1
while ("<x><cx>" in nts) cx+=1;
adv += "<x><cx>";
cx = 0;
// expr -> expr_
while (s in nts) s += "_";
adv += s;
// expr -> shjk
s = "";
for (c <- [stringChar(charAt(x,i)) | i <- [0..size(x)-1]])
if (c in low)
s += low[arbInt(size(low))];
elseif (c in upp)
s += upp[arbInt(size(upp))];
else
s += stringChar(c);
adv += s;
return setadvice("Did you mean",adv);
}

0 comments on commit 0f87cc5

Please sign in to comment.