1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
package scala.xml.transform ;
/** a trait for XML transformations */
trait BasicTransformer with Function1[Node,Node] {
protected case class NeedsCopy(result:Seq[Node]) extends java.lang.Throwable;
/** returns a new node buffer with the first pos elements from ns */
protected def buffer(pos:Int, ns:Seq[Node]): NodeBuffer = {
val nb = new NodeBuffer();
var jt = ns.elements;
var j = 0; while( j < pos-1 ) {
nb.append(jt.next);
j = j + 1;
}
nb
}
/** turns a nodebuffer into a sequence, so hashcode works */
protected def freeze(nb:NodeBuffer):Seq[Node] = {
val arr = new Array[Node](nb.length);
var i = 0;
val it = nb.elements; while( it.hasNext ) {
arr(i) = it.next;
i = i + 1;
}
val seq: Seq[Node] = arr;
seq
}
protected def single(ns:Seq[Node]) = {
(1 == ns.length)
}
protected def unchanged(n:Node, ns:Seq[Node]) = {
single(ns) && (ns.elements.next.eq(n))
}
/** call transform(Node) for each node in ns, append results
* to NodeBuffer */
def transform(it: Iterator[Node], nb:NodeBuffer): Seq[Node] = {
while( it.hasNext )
nb ++ transform( it.next );
freeze(nb);
}
/**
* call transform(Node) to each node in ns, yield ns if nothing changes,
* otherwise a new sequence of concatenated results
*/
def transform(ns: Seq[Node]): Seq[Node] = {
var i = 0;
val it = ns.elements;
try {
while( it.hasNext ) {
val n = it.next;
val n2 = transform(n);
if(!unchanged(n,n2)) {
throw NeedsCopy(n2)
}
i = i + 1;
}
ns
} catch {
case NeedsCopy(n2) =>
val nb = buffer(i, ns);
nb ++ n2;
transform(it, nb);
}
}
def transform(n: Node): Seq[Node] = {
if (n.typeTag$ < 0)
n
else {
val ch = n.child;
val nch = transform(ch);
if(ch.eq(nch))
n
else
Elem(n.prefix, n.label, n.attributes, n.scope, nch:_*)
}
}
def apply(n: Node): Node = {
val seq = transform(n);
if( !single(seq) )
error("transform must return single node for root");
else seq.elements.next;
}
}
/*
class IdentityTransformer extends BasicTransformer {
override def transform(n: Node): Seq[Node] = n.match {
case <world/> => <xml-world/>
case _ => super.transform(n);
}
}
object Foo with Application {
val tr = new IdentityTransformer;
val n = tr( <hello><world/></hello> );
Console.println(n);
val tr2 = new RewriteRule {
final override val name = "A rule";
override def transform(n: Node) = n.match {
case <a/> => <b/><c/>
case _ => n
}
}
val tr3 = new RewriteRule {
final override val name = "E rule";
override def transform(n: Node) = n.match {
case <e/> => <f><f/></f>
case _ => n
}
}
val tr4 = new RuleTransformer(tr2, tr3);
val m = tr4( <hello><a/><e/></hello> );
Console.println(m);
}
*/
|