/**
* Implements simplification to a normalized tree grammar (Section 2.1 TATA)
*
* After applying this transformation every production has the
* from A -> f(A1 ... A2) or A -> f()
*
* @author Martin Bravenboer
*/
module stratego/rtg/normalize
imports
stratego/rtg/signature
libstratego-lib
strategies
rtg-remove-nested-trees =
RTG(
Start(id)
, ProdRules(
listtd(repeat(rtg-lift-nested-tree))
)
)
/**
* This might introduces duplicate rules, but the remove-inject-rules
* simplifications turns the productions into a set anyway, so we
* ignore this.
*/
rtg-lift-nested-tree :
[ProdRule(a, [Appl(f, ts)]) | ps]
->
[ProdRule(a, [Appl(f, ts')]), ProdRule(t', [t]) | ps]
where
ts' := <fetch((
Appl(g, ts2) -> Ref(t')
where
?t; t' := <rtg-nested-tree-to-nonterm> t
))> ts
rtg-nested-tree-to-nonterm :
a@Appl(f, ts) -> Generated(a)
strategies
/**
* @todo Rather inefficient: need transitive closure implementation
* with tracing of the transitivity.
*/
rtg-remove-injection-rules :
RTG(Start(starts), ProdRules(prodrules))
->
RTG(Start(starts), ProdRules(prodrules'))
where
let create-hashtable = {tbl:
tbl := <new-hashtable>
; <map(add-production-to-tbl(|tbl))> prodrules
; !tbl
}
add-production-to-tbl(|tbl) = {a, p:
?p@ProdRule(a, _)
; <hashtable-push(|a, p)> tbl
}
is-normalized =
ProdRule(id, [Appl(id, map(Ref(id)))])
is-injection =
ProdRule(id, [Ref(id)])
ensure-injection =
is-injection
<+ log(|Error(), "expected injection production", <id>)
; fail
remove-injection(|ps, tbl) = {a, b, tail, ps' :
?[ProdRule(a, [Ref(b)]) | tail]
; ps' := <hashtable-get(|b); map(make-inlined(|a))> tbl
; <iset-addlist(|<retain-all(is-normalized)> ps')> ps
; <remove-all(is-normalized)> ps'
; map(ensure-injection)
; <conc> (<id>, tail)
}
make-inlined(|a) =
\ ProdRule(b, [alt]) -> ProdRule(a, [alt]) \
in tbl := <create-hashtable>
; ps := <new-iset>
; finally(
<iset-addlist(|<retain-all(is-normalized)> prodrules)> ps
; <remove-all(is-normalized)> prodrules
; map(ensure-injection)
; repeat(remove-injection(|ps, tbl))
; (?[] <+ ?[<id> | _]; debug(!"cannot remove injection: "); fail)
; prodrules' := <iset-elements> ps
, <iset-destroy> ps
; <hashtable-destroy> tbl
)
end