summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorburaq <buraq@epfl.ch>2004-11-18 11:11:08 +0000
committerburaq <buraq@epfl.ch>2004-11-18 11:11:08 +0000
commit499b0279b75970abd747f4518f5e67de09e49d7b (patch)
tree2b97f2532729bb385d1134c8e03dbad923a02e25 /sources
parent55fb705ed917a21b8553c2cc6e82e351da6e5c82 (diff)
downloadscala-499b0279b75970abd747f4518f5e67de09e49d7b.tar.gz
scala-499b0279b75970abd747f4518f5e67de09e49d7b.tar.bz2
scala-499b0279b75970abd747f4518f5e67de09e49d7b.zip
hello
Diffstat (limited to 'sources')
-rw-r--r--sources/scala/xml/transform/BasicTransformer.scala124
-rw-r--r--sources/scala/xml/transform/RewriteRule.scala13
-rw-r--r--sources/scala/xml/transform/RuleTransformer.scala14
3 files changed, 151 insertions, 0 deletions
diff --git a/sources/scala/xml/transform/BasicTransformer.scala b/sources/scala/xml/transform/BasicTransformer.scala
new file mode 100644
index 0000000000..bf8f4b24f6
--- /dev/null
+++ b/sources/scala/xml/transform/BasicTransformer.scala
@@ -0,0 +1,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.namespace, n.label, n.attributes, 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);
+}
+*/
diff --git a/sources/scala/xml/transform/RewriteRule.scala b/sources/scala/xml/transform/RewriteRule.scala
new file mode 100644
index 0000000000..c00d33aa96
--- /dev/null
+++ b/sources/scala/xml/transform/RewriteRule.scala
@@ -0,0 +1,13 @@
+package scala.xml.transform ;
+
+/** a RewriteRule, when applied to a term, yields either
+ * the resulting of rewriting or the term itself it the rule
+ * is not applied
+ */
+abstract class RewriteRule extends BasicTransformer {
+ /** a name for this rewrite rule */
+ val name = this.toString();
+ override def transform(ns:Seq[Node]): Seq[Node] = super.transform(ns);
+ override def transform(n:Node): Seq[Node] = n;
+}
+
diff --git a/sources/scala/xml/transform/RuleTransformer.scala b/sources/scala/xml/transform/RuleTransformer.scala
new file mode 100644
index 0000000000..6a967105e7
--- /dev/null
+++ b/sources/scala/xml/transform/RuleTransformer.scala
@@ -0,0 +1,14 @@
+package scala.xml.transform;
+
+class RuleTransformer(rules:RewriteRule*) extends BasicTransformer {
+ override def transform(n:Node): Seq[Node] = {
+ var m: Seq[Node] = super.transform(n);
+ val it = rules.elements; while(it.hasNext) {
+ val rule = it.next;
+ val m2 = rule.transform(m);
+ //if(!m2.eq(m)) Console.println("applied rule \""+rule.name+"\"");
+ m = m2;
+ }
+ m
+ }
+}