summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorburaq <buraq@epfl.ch>2003-11-17 10:59:53 +0000
committerburaq <buraq@epfl.ch>2003-11-17 10:59:53 +0000
commit4cf8078dabdf96dd47b512b928ef77ebac2d2a93 (patch)
tree88502c2c086fdd2ae804424885b08757ba5ddcb4
parent8e28c8583d74c4f356b7ea4a7cb55e164b3a1c0b (diff)
downloadscala-4cf8078dabdf96dd47b512b928ef77ebac2d2a93.tar.gz
scala-4cf8078dabdf96dd47b512b928ef77ebac2d2a93.tar.bz2
scala-4cf8078dabdf96dd47b512b928ef77ebac2d2a93.zip
changes to XML API and parameterized binding in...
changes to XML API and parameterized binding in dtd2scala better names changes to test suite
-rw-r--r--Makefile12
-rw-r--r--config/list/dtd2scala.lst2
-rw-r--r--config/list/library.lst9
-rw-r--r--sources/scala/tools/dtd2scala/DeclToScala.scala294
-rw-r--r--sources/scala/tools/dtd2scala/XMLDecl.scala7
-rw-r--r--sources/scala/xml/BindingFactoryAdapter.scala71
-rw-r--r--sources/scala/xml/FactoryAdapter.scala110
-rw-r--r--sources/scala/xml/Generic.scala158
-rw-r--r--sources/scala/xml/Node.scala36
-rw-r--r--sources/scala/xml/ScalaFactoryAdapter.scala78
-rw-r--r--sources/scala/xml/Text.scala24
-rw-r--r--sources/scala/xml/Utility.scala67
-rw-r--r--sources/scala/xml/nobinding/Element.scala17
-rw-r--r--sources/scala/xml/path/Expression.scala6
-rw-r--r--sources/scala/xml/path/Parser.scala9
-rw-r--r--support/emacs/scala-mode.el2
-rw-r--r--test/files/xml/lnk.scala7
-rw-r--r--test/files/xml/xhtml.scala12
18 files changed, 394 insertions, 527 deletions
diff --git a/Makefile b/Makefile
index 978388aca9..5360c2a5b2 100644
--- a/Makefile
+++ b/Makefile
@@ -110,10 +110,12 @@ SCALADOC_RSRC_FILES += $(SCALADOC_RSRC_LIST:%=$(SCALADOC_ROOT)/%)
SCALADOC_RSRC_OUTPUTDIR = $(PROJECT_OUTPUTDIR)/scala/tools/scaladoc
# dtd2scala
-DTD2SCALA_ROOT = $(PROJECT_SOURCEDIR)/scala/tools/dtd2scala
+DTD2SCALA_PATH = scala/tools/dtd2scala
+DTD2SCALA_ROOT = $(PROJECT_SOURCEDIR)/$(DTD2SCALA_PATH)
DTD2SCALA_LIST = $(call READLIST,$(PROJECT_LISTDIR)/dtd2scala.lst)
DTD2SCALA_SOURCES += $(DTD2SCALA_LIST:%=$(DTD2SCALA_ROOT)/%)
-DTD2SCALA_SC_FILES = $(DTD2SCALA_SOURCES)
+DTD2SCALA_SC_FILES = $(filter %.scala,$(DTD2SCALA_SOURCES))
+DTD2SCALA_XML_FILES = $(filter %.xml,$(DTD2SCALA_SOURCES))
# scalap
SCALAP_ROOT = $(PROJECT_SOURCEDIR)/scala/tools/scalap
@@ -344,8 +346,10 @@ cvs-fix-perms :
$(SCALADOC_RSRC_OUTPUTDIR))
touch $@
-.latest-dtd2scala-sc : $(DTD2SCALA_SC_FILES)
- @$(make) sc target=DTD2SCALA DTD2SCALA_SC_FILES='$?'
+.latest-dtd2scala-sc : $(DTD2SCALA_SC_FILES) $(DTD2SCALA_XML_FILES)
+ @$(make) sc target=DTD2SCALA DTD2SCALA_SC_FILES='$(filter %.scala,$?)'
+ @mkdir -p $(PROJECT_OUTPUTDIR)/$(DTD2SCALA_PATH)/template
+ cp $(DTD2SCALA_XML_FILES) $(PROJECT_OUTPUTDIR)/$(DTD2SCALA_PATH)/template/
touch $@
.latest-scalap-sc : $(SCALAP_SC_FILES)
diff --git a/config/list/dtd2scala.lst b/config/list/dtd2scala.lst
index b90ced5e54..3071e8fbf0 100644
--- a/config/list/dtd2scala.lst
+++ b/config/list/dtd2scala.lst
@@ -20,4 +20,6 @@ regexp/Star.scala
regexp/Eps.scala
regexp/PCDATA_.scala
+template/ObjectTemplate.scala.xml
+template/CommentTemplate.scala.xml
##############################################################################
diff --git a/config/list/library.lst b/config/list/library.lst
index b276d1875c..9e91812c9c 100644
--- a/config/list/library.lst
+++ b/config/list/library.lst
@@ -131,11 +131,12 @@ runtime/ScalaRunTime.scala
testing/UnitTest.scala
-xml/Element.scala
+xml/Node.scala
xml/FactoryAdapter.scala
-xml/Generic.scala
-xml/PCDATA.scala
-xml/ScalaFactoryAdapter.scala
+xml/Text.scala
+xml/BindingFactoryAdapter.scala
+
+xml/nobinding/Element.scala
xml/path/Expression.scala
xml/path/Tokens.scala
diff --git a/sources/scala/tools/dtd2scala/DeclToScala.scala b/sources/scala/tools/dtd2scala/DeclToScala.scala
index 1b1210dae1..f5c8191159 100644
--- a/sources/scala/tools/dtd2scala/DeclToScala.scala
+++ b/sources/scala/tools/dtd2scala/DeclToScala.scala
@@ -3,16 +3,94 @@ package scala.tools.dtd2scala ;
import java.io.PrintWriter ;
import scala.collection.Map ;
+import scala.collection.mutable.HashMap ;
import scalac.util.Name ;
-import scalac.ast.parser.Scanner ; // for keywords
+import scalac.ast.parser.Scanner ; /* for keywords */
+
+import scala.xml._ ;
+import scala.xml.nobinding.{Element,XML} ;
/** transforms a set of DTD declaraion to a scala source file.
+ * 2do: parameterize with destination package.
*/
class DeclToScala(fOut:PrintWriter,
moduleName:String,
elemMap:Map[ String, ElemDecl ] ) {
- final val DEFAULT_moduleName = "myXML";
+ abstract class objectTemplate {
+ val objectName : String = "myXML"; /* DEFAULT MODULE NAME */
+ val package_ : String = "";
+ val compress : boolean = true;
+ final val tmplFile = "scala/tools/dtd2scala/template/CommentTemplate.scala.xml";
+ final val tmpl:Node = XML.load( ClassLoader.getSystemResource(tmplFile) );
+
+ val lookup : HashMap[String,String] = new HashMap[String,String]();
+ var curAttribs: Map[String,AttrDecl] = null ; /* of current elem */
+
+ def write:Unit = {
+ def writeNode( n:Node ):Unit = {
+ n.label match {
+ case "template" => {
+ lookup.update("objectName", objectName);
+ lookup.update("compressDefault", compress.toString());
+ n.children.elements.foreach { n => writeNode(n) }
+ }
+ case "elementBinding" => {
+ for( val decl <- elemMap.values.elements ) do {
+ fOut.println();
+ printIndent();
+ lookup += "elementName" -> decl.name;
+ lookup += "elementContainsText" -> decl.containsText.toString();
+ lookup += "elementContentModel" -> decl.contentModel;
+ curAttribs = decl.attribs;
+ n.children.elements.foreach{ n => writeNode( n ) }
+ }
+ curAttribs = null;
+ lookup -= "elementName";
+ lookup -= "elementContainsText";
+ }
+
+ case "attributeAssign" => {
+ for( val aDecl <- curAttribs.keys.elements ) do {
+ lookup += "attributeName" -> aDecl;
+ n.children.elements.foreach{ n => writeNode( n ) }
+ }
+ lookup -= "attributeName";
+ }
+
+ case "attributeBinding" => {
+ for( val aDecl <- curAttribs.keys.elements ) do {
+ lookup += "attributeName" -> aDecl;
+ Console.println("attributeName is "+aDecl+" = "+lookup("attributeName"));
+ n.children.elements.foreach{ n => writeNode( n ) }
+ }
+ lookup -= "attributeName";
+ }
+ case "ccstring" => {
+ Console.println("ccstring ref=\""+n.attributes("ref")+"\"");
+ fOut.print( cookedCap( lookup( n.attributes("ref") ) ));
+ }
+ case "string" => {
+ Console.println("string ref=\""+n.attributes("ref")+"\"");
+ fOut.print( lookup( n.attributes("ref") ) );
+ }
+ case "qstring" => {
+ Console.println("qstring ref=\""+n.attributes("ref")+"\"");
+
+ fOut.print("\"");
+ fOut.print( lookup( n.attributes("ref") ) );
+ fOut.print("\"");
+ }
+ case "br" => { fOut.println(); printIndent() }
+ case "inc" => fIndent = fIndent + IND_STEP
+ case "dec" => fIndent = fIndent - IND_STEP
+ case "#PCDATA" => fOut.print( n.asInstanceOf[Text].text )
+ case _ => error("what shall I do with a \""+n.label+"\" node ?")
+ }
+ }
+ writeNode( tmpl )
+ }
+ }
final val COMPRESS_DEFAULT:String = "true"; // do hash-consing on load
@@ -23,15 +101,15 @@ class DeclToScala(fOut:PrintWriter,
final val CHILDREN_VALDEF:String =
"var _ch:scala.Seq[scala.xml.Element] = if( children == null ) { scala.Nil } else children ;";
- final val CHILDREN_SEQ:String = "children";
+ final val CHILDREN_SEQ:String = "ch";
//static final String CHILDREN_T = "scala.Seq[Element]";
final val CHILDREN_T:String = "Element*";
- final val RAW_NAME_DEF:String = "def getName:String = ";
+ final val RAW_NAME_DEF:String = "def label:String = ";
- final val GET_CHILDREN_DEF:String = "def getChildren:scala.Seq[scala.xml.Element] = _ch ;";
- final val GET_ATTRIBS_DEF:String = "def getAttribs:Map[String,String] = _at ;";
- final val SET_ATTRIBS_DEF:String = "def setAttribs( m:Map[String,String] ):Unit = {_at = m};";
+ final val GET_CHILDREN_DEF:String = "def children:scala.Seq[scala.xml.Element] = ch ;";
+ //final val GET_ATTRIBS_DEF:String = "def getAttribs:Map[String,String] = _at ;";
+ //final val SET_ATTRIBS_DEF:String = "def setAttribs( m:Map[String,String] ):Unit = {_at = m};";
//static final String HASHCODE_DEF = "override def hashCode():int = { getChildren.hashCode() + getAttribs.hashCode() + getName.hashCode() }";
@@ -39,33 +117,8 @@ class DeclToScala(fOut:PrintWriter,
var fIndent:int = 0;
- def begin = {
- fOut.println( "// this file is generated from a DTD");
- fOut.print( "object " );
- fOut.print( moduleName );
- fOut.println(" {");
- fIndent = IND_STEP;
- printIndent();
- fOut.println("import scala.xml._ ;");
- fOut.println("import scala.collection.Map ;");
- fOut.println("import scala.collection.mutable.HashMap ;");
- }
-
- def end = {
- fOut.println("}");
- fOut.flush();
- fOut.close();
- }
+ /*
- /**
- * @name - (raw) name of the Element
- */
- def printClassDef( decl:ElemDecl ):Unit = {
- val clazzName:String = cookedCap( decl.name );
-
- printIndent();
-
- /* // DISABLED
// convenience ! overloaded constructors, have to appear *before*
// the class def and need the "final" modifier
@@ -84,44 +137,9 @@ class DeclToScala(fOut:PrintWriter,
printIndent();
}
- */
-
-
- fOut.print( "case class " );
-
- fOut.print( clazzName );
-
- fOut.print('(');
- //fOut.print( ATTRIB_MAP ); fOut.print(':'); fOut.print( ATTRIB_T );
- //fOut.print(',');
- fOut.print( CHILDREN_SEQ ); fOut.print(':'); fOut.print( CHILDREN_T );
- fOut.print(')');
- fOut.println(" extends Element {");
- fIndent = fIndent + IND_STEP ;
-
- printIndent();
- fOut.print( RAW_NAME_DEF );
- fOut.print('"'); fOut.print( decl.name ); fOut.print('"');
- fOut.println(';');
-
- printIndent(); fOut.println( CHILDREN_VALDEF );
- printIndent(); fOut.println( GET_CHILDREN_DEF );
- printIndent(); fOut.println( ATTRIBS_VARDEF );
- printIndent(); fOut.println( GET_ATTRIBS_DEF );
- printIndent(); fOut.println( SET_ATTRIBS_DEF );
- //printIndent(); fOut.println( HASHCODE_DEF );
-
- /*
- for( Iterator it = decl.attribs.keySet().iterator(); it.hasNext() ; )
- toScala( (AttrDecl) decl.attribs.get( it.next() ));
*/
- fIndent = fIndent - IND_STEP ;
- printIndent();
- fOut.println("}");
- fOut.flush();
- }
/** Prints the indent. */
def printIndent():Unit = {
@@ -130,141 +148,15 @@ class DeclToScala(fOut:PrintWriter,
}
}
- /**
- * @name - (raw) name of the attribute
- */
- def printSetMethod( name:String ):Unit = {
- printIndent();
-
- fOut.print( "def " );
- fOut.print( cooked( name ));
- fOut.print( "( arg:String ):Unit = _at.update(\"" );
- fOut.print( name );
- fOut.println( "\", arg ) ;");
- }
-
- /**
- * @name - (raw) name of the attribute
- */
- def printGetMethod( name:String ):Unit = {
- printIndent();
-
- fOut.print( "def " );
- fOut.print( cooked( name ));
- fOut.print( ":String = _at.get( ");
- fOut.print( '"' );fOut.print( name );fOut.print( '"' );
- fOut.println( " ).match { Some(x) => x };");
- }
-
- def printFactory:Unit = {
-
- printIndent();
- fOut.println(
- "val _factory: Map[String, scala.Seq[scala.xml.Element] => scala.xml.Element] = {");
- fIndent = fIndent + IND_STEP;
- printIndent();
- fOut.println(
- //"val res = new scala.HashMap[String,(scala.Map[String,String],scala.Seq[Element])=>Element] ;");
- "val res = new HashMap[String, scala.Seq[scala.xml.Element] => scala.xml.Element] ;");
- //JAVA: for(Iterator it = elemMap.keySet().iterator(); it.hasNext(); )
- for( val decl <- elemMap.values.elements ) do {
- printIndent();
- fOut.print( "res.update(\"" );
- fOut.print( decl.name );
- fOut.print( "\",(x:scala.Seq[scala.xml.Element] => ");
- fOut.print( cookedCap( decl.name ));
- fOut.println("( x:_* ) ));");
- };
- printIndent();
- fOut.println("res");
- printIndent();
- fOut.println( "}");
- fIndent = fIndent - IND_STEP;
-
- }
-
- def printContainsTextDef:Unit = {
- printIndent();
- fOut.println("val _containsMap: Map[scala.String, boolean] = {");
- fIndent = fIndent + IND_STEP;
- printIndent();
- fOut.println("val res = new HashMap[scala.String, boolean] ;");
-
- for( val decl <- elemMap.values.elements ) do {
- printIndent();
- fOut.print( "res.update(\"" );
- fOut.print( decl.name );
- fOut.print( "\",");
- fOut.print( decl.containsText ); //write a boolean literal
- fOut.println(");");
- };
- printIndent();
- fOut.println("res");
- fIndent = fIndent - IND_STEP;
- printIndent();
- fOut.println( "}");
- }
-
- def printLoaderDef:Unit = {
- printIndent();
- fOut.print("def load( filename:String ):Element = load( filename, ");
- fOut.print( COMPRESS_DEFAULT );
- fOut.println(");");
- printIndent();
- fOut.println("def load( filename:String, _compress:boolean ):Element = {");
- fIndent = fIndent + IND_STEP;
- printIndent();
- fOut.println("val fAdapter = new ScalaFactoryAdapter {");
- fIndent = fIndent + IND_STEP;
- printIndent();
- fOut.println("val f = _factory ;");
- printIndent();
- fOut.println("val g = _containsMap ; ");
- printIndent();
- fOut.println("val compress = _compress ; ");
- printIndent();
- fOut.println("};");
- fIndent = fIndent - IND_STEP;
- printIndent();
- fOut.println("fAdapter.loadXML( filename );");
- printIndent();
- fOut.println("};");
- fIndent = fIndent - IND_STEP;
- };
-
-def comment = {
- fOut.println("/** the following elements are there");
-
- for( val decl <- elemMap.values.elements ) do {
- fOut.print(" * ");
- fOut.print( decl.name );
- fOut.print(" : [");
- fOut.print( decl.contentModel );
- fOut.println(']');
- fOut.print(" * ");
- fOut.println( "attribs: "+decl.attribs );
- };
- fOut.println("*/");
-}
-
+ /** runs translation. */
def run:Unit = {
- begin;
- comment;
- for( val decl <- elemMap.values.elements ) do toScala( decl );
- printContainsTextDef;
- printFactory;
- printLoaderDef;
- end;
+ new objectTemplate {
+ override val objectName = moduleName
+ }.write;
+ fOut.flush();
+ fOut.close();
}
- def toScala( decl:XMLDecl ):Unit = decl.match {
-
- case x:ElemDecl => printClassDef( x );
- case AttrDecl( name, "CDATA" ) => printGetMethod(name);
- case AttrDecl( name, tpe ) => warning_attrib( name, tpe )
- case _ => error("unexpected decl:"+decl);
- } // toScala
-
private def warning_attrib(name:String,tpe:String) = {
System.err.print( "[ignoring attribute \"" );
System.err.print( name );
@@ -277,7 +169,7 @@ def comment = {
//
// cooking raw names
//
-
+/* replace dash, colons with underscore, keywords with appended $ */
private def cooked( ckd:StringBuffer, raw:String, off:int ):String = {
for( val i <- List.range( off, raw.length()) ) do {
val _ = raw.charAt( i ).match {
diff --git a/sources/scala/tools/dtd2scala/XMLDecl.scala b/sources/scala/tools/dtd2scala/XMLDecl.scala
index 50edccf8a0..4e17124a39 100644
--- a/sources/scala/tools/dtd2scala/XMLDecl.scala
+++ b/sources/scala/tools/dtd2scala/XMLDecl.scala
@@ -10,8 +10,7 @@ case class ElemDecl( name:String ,
extends XMLDecl {
def containsText = contentModel.indexOf("#PCDATA") != -1 ;
-}; /*AttrDecl[]*/
+};
-// ignore default values 4 now
-case class AttrDecl( name:String,
- tpe:String ) extends XMLDecl;
+/* ignore default values 4 now */
+case class AttrDecl( name:String, tpe:String ) extends XMLDecl;
diff --git a/sources/scala/xml/BindingFactoryAdapter.scala b/sources/scala/xml/BindingFactoryAdapter.scala
new file mode 100644
index 0000000000..ea3a1ca19a
--- /dev/null
+++ b/sources/scala/xml/BindingFactoryAdapter.scala
@@ -0,0 +1,71 @@
+package scala.xml ;
+
+import scala.collection.Map ;
+import scala.collection.mutable.HashMap ;
+//import scala.xml.javaAdapter.Map ;
+//import scala.xml.javaAdapter.HashMap ;
+
+/** a Scala specific dtd2scala.FactoryAdapter, which plays the SAX content
+* handler for the SAX parser. It implements the three callback methods
+* elementContainsText, createNode and createPCDATA. DTDs imported with
+* the dtd2scala tool all use this class as interface to the SAX XML parser,
+* by giving concrete values for the factory maps f and g.
+*/
+
+abstract class BindingFactoryAdapter extends FactoryAdapter() {
+
+ /** mapping from element names to an element constructor
+ * (constr:Seq[Node],HashMap[String,String] => Node)
+ */
+ val f: Map[ String, (Seq[Node],HashMap[String,String]) => Node ];
+
+ /** mapping from element names to a truth value indicating
+ * whether the corresponding element may have text children
+ */
+ val g: Map[ String, boolean ] ;
+
+ /** if true, create only elements not created before */
+ val compress: boolean ;
+
+ /** looks up whether an element may have text children */
+ def nodeContainsText( name:java.lang.String ):boolean =
+ g.get( name ).match { case Some(x) => x };
+
+ // if compress is set, used for hash-consing
+ val cache = new HashMap[int,Node];
+ //var cacheCount = 0;
+
+ /** creates an element. see also compress */
+ def createNode(elemName:String,
+ attribs:HashMap[String,String],
+ children:List[Node] ):Node = {
+ // 2do:optimize
+ if( !compress ) {
+ // get constructor
+ val c = f.get( elemName ).match{ case Some(x) => x };
+ c( children, attribs );
+ } else { // do hash-consing
+
+ val ahc = attribs.toList.hashCode();
+ val h = Utility.hashCode( elemName, ahc, children );
+ cache.get( h ).match {
+
+ case Some(cachedElem) =>
+ //cacheCount = cacheCount + 1;
+ //System.err.println("[ScalaFactoryAdapter: cache hit "+cacheCount+"]");
+ cachedElem
+
+ case None =>
+ // get constructor
+ val c = f.get( elemName ).match{ case Some(x) => x };
+ val el = c( children, attribs );
+ cache.update( h, el );
+ el
+ }
+ }
+ } // createNode
+
+ /** creates PCDATA element */
+ def createText( text:String ):Text = new Text( text );
+
+} // BindingFactoryAdapter
diff --git a/sources/scala/xml/FactoryAdapter.scala b/sources/scala/xml/FactoryAdapter.scala
index dbe332283b..2d6e5464c5 100644
--- a/sources/scala/xml/FactoryAdapter.scala
+++ b/sources/scala/xml/FactoryAdapter.scala
@@ -1,11 +1,10 @@
package scala.xml ;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
+import java.io.{OutputStream,OutputStreamWriter,PrintWriter,Writer};
import java.io.UnsupportedEncodingException;
-import java.io.Writer;
+import java.net.URL;
+
/*import java.util.Map;
import java.util.HashMap;
@@ -13,8 +12,7 @@ import java.util.LinkedList;
import java.util.Stack;
import java.util.Iterator;
*/
-import scala.collection.mutable.Stack;
-import scala.collection.mutable.HashMap;
+import scala.collection.mutable.{HashMap,Stack};
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
@@ -53,7 +51,7 @@ abstract class FactoryAdapter
val buffer = new StringBuffer();
val attribStack = new Stack[HashMap[String,String]];
- val hStack = new Stack[Element]; // [ element ] contains siblings
+ val hStack = new Stack[Node]; // [ element ] contains siblings
val tagStack = new Stack[String]; // [String]
var curTag : String = null ;
@@ -64,23 +62,23 @@ abstract class FactoryAdapter
/** Tests if an XML element contains text.
* @return true if element named <code>localName</code> contains text.
*/
- def elementContainsText( localName:String ):boolean ; // abstract
+ def nodeContainsText( localName:String ):boolean ; // abstract
- /** Creates an new XML element.
+ /** creates an new non-text(tree) node.
* @param elemName
* @param attribs
* @param chIter
* @return a new XML element.
*/
- def createElement(elemName:String ,
- attribs:HashMap[String,String] ,
- chIter:List[Element] ):Element; //abstract
+ def createNode(elemName:String ,
+ attribs:HashMap[String,String] ,
+ chIter:List[Node] ):Node; //abstract
- /** Creates an PCDATA element.
+ /** creates a Text node.
* @param text
- * @return a new PCDATA element.
+ * @return a new Text node.
*/
- def createPCDATA( text:String ):PCDATA; // abstract
+ def createText( text:String ):Text; // abstract
//
// ContentHandler methods
@@ -88,26 +86,22 @@ abstract class FactoryAdapter
/** Set document locator.
* @param locator
+ def setDocumentLocator( locator:Locator ):Unit = {}
*/
- //def setDocumentLocator( locator:Locator ):Unit = {}
/** Start document.
* @throws org.xml.sax.SAXException if ..
+ def startDocument():Unit = {}
*/
- //def startDocument():Unit /*throws SAXException*/ = {}
/** Characters.
* @param ch
* @param offset
* @param length
*/
- override def characters(ch:Array[char] , offset:int , length:int ):Unit
- /*throws SAXException*/ = {
+ override def characters( ch:Array[char] , offset:int , length:int ):Unit = {
var ws:boolean = false;
-
- //System.err.println( "before \""+buffer+"\"" );
-
if (capture) {
var i:int = offset;
while (i < offset + length) {
@@ -126,38 +120,36 @@ abstract class FactoryAdapter
//System.err.println( "after \""+buffer+"\"" );
//System.err.println();
- } // characters(char[],int,int)
+ }
/** Ignorable whitespace.
+ def ignorableWhitespace(ch:Array[char] , offset:int , length:int ):Unit = {}
*/
- //def ignorableWhitespace(ch:Array[char] , offset:int , length:int ):Unit
- // /*throws SAXException*/ = {}
/** End document.
*/
- //def endDocument():Unit /*throws SAXException*/ = {}
+ //def endDocument():Unit = {}
//var elemCount = 0; //STATISTICS
- //
- // ContentHandler methods
- //
- /** Start prefix mapping.
- */
- //def startPrefixMapping( prefix:String , uri:String ):Unit
- // /*throws SAXException*/ = {}
+ /* ContentHandler methods */
- /** Start element.
+ /* Start prefix mapping - use default impl.
+ def startPrefixMapping( prefix:String , uri:String ):Unit = {}
*/
- override def startElement( uri:String , localName:String , qname:String ,
- attributes:Attributes ):Unit /*throws SAXException*/ = {
- //elemCount = elemCount + 1; //STATISTICS
+
+ /* Start element. */
+ override def startElement(uri:String,
+ localName:String,
+ qname:String ,
+ attributes:Attributes ):Unit = {
+ /*elemCount = elemCount + 1; STATISTICS */
captureText();
tagStack.push(curTag);
curTag = localName ;
- capture = elementContainsText(localName) ;
+ capture = nodeContainsText(localName) ;
hStack.push( null );
var map:HashMap[String,String] = null:HashMap[String,String];
@@ -192,7 +184,7 @@ abstract class FactoryAdapter
if (capture == true) {
val text = buffer.toString();
if(( text.length() > 0 )&&( !( text.equals(" ")))) {
- val _ = hStack.push( createPCDATA( text ) );
+ val _ = hStack.push( createText( text ) );
}
}
buffer.setLength(0);
@@ -212,65 +204,59 @@ abstract class FactoryAdapter
val attribMap = attribStack.top; attribStack.pop;
// reverse order to get it right
- var v:List[Element] = Nil;
- var child:Element = hStack.top; hStack.pop;
+ var v:List[Node] = Nil;
+ var child:Node = hStack.top; hStack.pop;
while( child != null ) {
v = child::v;
child = hStack.top; hStack.pop;
}
// create element
- rootElem = createElement( localName, attribMap, v );
+ rootElem = createNode( localName, attribMap, v );
hStack.push(rootElem);
// set
curTag = tagStack.top; tagStack.pop;
if (curTag != null) // root level
- capture = elementContainsText(curTag);
+ capture = nodeContainsText(curTag);
else
capture = false;
} // endElement(String,String,String)
/** End prefix mapping.
+ def endPrefixMapping(prefix:String ):Unit = {}
*/
- //def endPrefixMapping(prefix:String ):Unit /*throws SAXException*/ = {}
/** Skipped entity.
+ def skippedEntity(name:String ):Unit /*throws SAXException*/ = {}
*/
- //def skippedEntity(name:String ):Unit /*throws SAXException*/ = {}
//
// ErrorHandler methods
//
/** Warning.*/
- override def warning(ex:SAXParseException ):Unit
- /*throws SAXException*/ = {
+ override def warning(ex:SAXParseException ):Unit = {
// ignore warning, crimson warns even for entity resolution!
//printError("Warning", ex);
}
/** Error. */
- override def error(ex:SAXParseException ):Unit
- /*throws SAXException*/ = {
+ override def error(ex:SAXParseException ):Unit = {
printError("Error", ex);
}
- /** Fatal error.
- */
- override def fatalError(ex:SAXParseException ):Unit
- /*throws SAXException*/ = {
+ /** Fatal error.*/
+ override def fatalError(ex:SAXParseException ):Unit = {
printError("Fatal Error", ex);
- /*throw ex;*/
}
//
// Protected methods
//
- /** Prints the error message.
- */
+ /** Prints the error message */
protected def printError( errtype:String , ex:SAXParseException ):Unit = {
System.err.print("[");
@@ -294,19 +280,21 @@ abstract class FactoryAdapter
System.err.println();
System.err.flush();
- } // printError(String,SAXParseException)
- //} // class FA_ErrorHandler
- var rootElem : Element = null:Element;
+ }
+
+ var rootElem : Node = null:Node;
//FactoryAdapter
// MAIN
//
+ def loadXML( url:URL ):Node = loadXML( url.getFile() );
+
/** load XML document
* @param fileName
* @return a new XML document object
*/
- def loadXML( fileName:String ):Element = {
+ def loadXML( fileName:String ):Node = {
// variables
//PrintWriter out = new PrintWriter(System.out);
@@ -364,7 +352,7 @@ abstract class FactoryAdapter
}
} // catch
//System.err.println("[FactoryAdapter: total #elements = "+elemCount+"]");
- rootElem;
+ rootElem
} // loadXML
diff --git a/sources/scala/xml/Generic.scala b/sources/scala/xml/Generic.scala
index 6cd16c6742..f4a85f7ce5 100644
--- a/sources/scala/xml/Generic.scala
+++ b/sources/scala/xml/Generic.scala
@@ -1,159 +1 @@
package scala.xml;
-
-import scala.collection.Map ;
-import scala.collection.mutable.HashMap ;
-
-/** Generic.load( <fileName> ) will load the xml document from file and
- * create a tree with scala.Labelled, PCDATA and scala.Symbol objects.
- * Text can appear within PCDATA at the leaves.
- */
-
-object Generic {
-
- // utility functions
-
- /** TEMPORARY converting Java iterators to scala List
-
- def iterToList[ a ]( iter:java.util.Iterator ):List[a] =
- if( !iter.hasNext() )
- Nil
- else
- (iter.next().asInstanceOf[ a ])::iterToList( iter ) ;
-
- */
-
- /** TEMPORARY converting Java maps to javaAdapter maps
-
- def mapToMap[a,b]( map:java.util.Map ):Map[a,b] = {
-
- val keys:java.util.Iterator = map.keySet().iterator();
- val res = new HashMap[a,b] ;
-
- def iterToMap:Unit =
- if( keys.hasNext() ) {
- val key = keys.next();
- val value = map.get( key ).asInstanceOf[ b ];
- res.put( key.asInstanceOf[ a ], value.asInstanceOf[ b ]);
- iterToMap
- } else
- () ;
-
- iterToMap;
- res
- }
- */
-
- /** turns a Map that contains attributes into XML like att1="val1" att2="val2"
- */
-
- def toXML( attrib:Map[ String, String ] ):String = {
- def iterate( keys:Iterator[String] ) =
- if( keys.hasNext ) {
- val key = keys.next;
- " " + key + "=\"" + attrib.get( key ).match{ case Some(x) => x } + "\"";
- } else {
- ""
- }
-
- if( attrib != null ) iterate( attrib.keys.elements ) else "";
- }
-
- // attributes
-
- /** this trait is mixed in with Labelled in order to provide attributes
- */
-
- trait Attribbed {
-
- // only CDATA / String attributes for now
- def attribs : Map[String,String] ;
-
- }
- // functions for generic xml loading, saving
-
- /** will load the given file and return a generic XML representation
- */
-
- def load( filename:String ):Labelled = {
- val b = new GenericFactoryAdapter().loadXML( filename );
- b.asInstanceOf[Labelled]
- };
-
- /** will save a generic XML representation doc to filename. Uses NIO classes of JDK 1.4 for character conversion,
- * encoding is fixed to ISO-8859-1 for now.
- */
-
- def save( filename:String, doc:Any ):Unit = {
- import java.io.{FileOutputStream,Writer};
- import java.nio.channels.{Channels,FileChannel};
- def toXMLList( xs: List[Any], fc:Writer ):Unit = xs match {
- case _::ys =>
- toXML( xs.head, fc );
- toXMLList( ys, fc );
- case _ => ()
- }
- def toXML( doc: Any, fc:Writer ):Unit = doc match {
- case PCDATA( s ) =>
- fc.write( (doc.asInstanceOf[ PCDATA ]).toXML );
- case Labelled( Symbol( tag ), xs ) =>
- fc.write( "<" );
- fc.write( tag );
- fc.write( Generic.toXML(( doc.asInstanceOf[ Attribbed ])
- .attribs ));
- fc.write( ">" );
- toXMLList( xs, fc );
- fc.write( "</" );
- fc.write( tag );
- fc.write( ">" );
-
- }
- val fos = new FileOutputStream( filename );
- val w = Channels.newWriter( fos.getChannel(), "ISO-8859-1" );
- toXML( doc, w );
- w.close();
- fos.close();
- }
-
- /** this class contains methods called back by the parser to create elements.
- * It implements hash-consing, i.e. identical elemens (same tag, same attributes, same children)
- * are only constructed once !
- */
-
- class GenericFactoryAdapter extends FactoryAdapter() {
-
- def elementContainsText( name:java.lang.String ):boolean = true;
-
- // default behaviour is hash-consing
- val cache = new HashMap[Element,Element];
-
- def createElement( elemName: String,
- attrs: HashMap[String,String],
- children: List[Element] ):Element = {
-
- val el = new Labelled( Symbol( elemName ), children )
- with Attribbed with Element {
- def getName = elemName;
- def getChildren = children;
- def attribs = attrs ; // ?! not needed anymore
- def getAttribs = attrs;
- def setAttribs( m:Map[ String, String ] ) = {
- /* FIXME throw error */ };
- };
-
- cache.get( el ).match{
- case Some(cachedElem) =>
- System.err.println("[using cached elem!]");
- cachedElem
- case None =>
- cache.update( el, el );
- el
- }
- }; // createElement
-
- def createPCDATA( text:String ):PCDATA = {
- new PCDATA( text );
- };
-
- } // GenericFactoryAdapter
-
-} //Generic
diff --git a/sources/scala/xml/Node.scala b/sources/scala/xml/Node.scala
new file mode 100644
index 0000000000..0ae73a7618
--- /dev/null
+++ b/sources/scala/xml/Node.scala
@@ -0,0 +1,36 @@
+package scala.xml ;
+
+import scala.collection.Map;
+
+/** superclass for specific representation of XML elements. These are created by
+** a xxx2scala binding tool
+**/
+abstract class Node {
+
+ def label: String;
+ def children: Seq[ Node ];
+
+ /** returns a mapping from all present attributes to values */
+ def attributes: Map[String,String];
+
+ protected val attribHashCode: int;
+
+ /** hashcode for this node*/
+ override def hashCode() = Utility.hashCode( label, attribHashCode, children );
+
+ def toXML: String = Utility.toXML( this );
+
+ def toXML_( elems:Seq[Node] ):String = elems match {
+ case head :: tail => head.toXML + toXML_( tail );
+ case Nil => "";
+ }
+
+ override def toString() = {
+ var s = new StringBuffer( label );
+ s.append("(");
+ s.append( children.toString() );
+ s.append(")");
+ s.toString();
+ }
+
+}
diff --git a/sources/scala/xml/ScalaFactoryAdapter.scala b/sources/scala/xml/ScalaFactoryAdapter.scala
deleted file mode 100644
index 0d77ee7370..0000000000
--- a/sources/scala/xml/ScalaFactoryAdapter.scala
+++ /dev/null
@@ -1,78 +0,0 @@
-package scala.xml ;
-
-import scala.collection.Map ;
-import scala.collection.mutable.HashMap ;
-//import scala.xml.javaAdapter.Map ;
-//import scala.xml.javaAdapter.HashMap ;
-
-/** a Scala specific dtd2scala.FactoryAdapter, which plays the SAX content
-* handler for the SAX parser. It implements the three callback methods
-* elementContainsText, createElement and createPCDATA. DTDs imported with
-* the dtd2scala tool all use this class as interface to the SAX XML parser,
-* by giving concrete values for the factory maps f and g.
-*/
-
-abstract class ScalaFactoryAdapter
- extends FactoryAdapter() {
-
- /** subclasses need to provide a mapping from a element name (string) to an element constructor
- * (constr:Seq[Element] => Element)
- */
- val f: Map[ String, Seq[Element] => Element ];
-
- /** subclasses need to provide a mapping from an element name (string) to a truth value indicating
- * whether text (PCDATA) may appear as
- */
-
- val g: Map[ String, boolean ] ;
-
- /** subclasses need to tell whether they want to use hash-consing, which creates only non-identical elements
- */
- val compress: boolean ;
-
- /** looks up in g whether an element may contain text (PCDATA)
- */
-
- def elementContainsText( name:java.lang.String ):boolean =
- g.get( name ).match { case Some(x) => x };
-
- // if compress is set, used for hash-consing
- val cache = new HashMap[int,Element];
- //var cacheCount = 0;
- /** creates an element. uses hash-consing if compress == true
- */
- def createElement(elemName:String,
- attribs:HashMap[String,String],
- children:List[Element] ):Element = {
- // 2do:optimize
- if( !compress ) {
- // get constructor
- val c = f.get( elemName ).match{ case Some(x) => x };
- val el = c( children );
- el.setAttribs( attribs );
- el
- } else { // do hash-consing
-
- val h = Element.hashValue( elemName, attribs, children );
- cache.get( h ).match {
-
- case Some(cachedElem) =>
- //cacheCount = cacheCount + 1;
- //System.err.println("[ScalaFactoryAdapter: cache hit "+cacheCount+"]");
- cachedElem
-
- case None =>
- // get constructor
- val c = f.get( elemName ).match{ case Some(x) => x };
- val el = c( children );
- el.setAttribs( attribs );
- cache.update( h, el );
- el
- }
- }
- } // createElement
-
- /** creates PCDATA element */
- def createPCDATA( text:String ):PCDATA = new PCDATA( text );
-
-} // ScalaFactoryAdapter
diff --git a/sources/scala/xml/Text.scala b/sources/scala/xml/Text.scala
new file mode 100644
index 0000000000..1070ded922
--- /dev/null
+++ b/sources/scala/xml/Text.scala
@@ -0,0 +1,24 @@
+/* BE */
+package scala.xml;
+
+import scala.collection.Map ;
+
+/** a text node. Used in both unsafe and typed XML representation
+**/
+
+case class Text( text:String ) extends Node {
+
+ def label = "#PCDATA";
+
+ def children = Nil;
+ def attributes = null;
+
+ protected val attribHashCode = 0;
+
+ override def toXML = Utility.escape( text );
+
+ override def hashCode() = text.hashCode(); /* could be done at parse time */
+ override def toString() = "Text("+text+")";
+
+} // Text
+
diff --git a/sources/scala/xml/Utility.scala b/sources/scala/xml/Utility.scala
new file mode 100644
index 0000000000..6e65dd104d
--- /dev/null
+++ b/sources/scala/xml/Utility.scala
@@ -0,0 +1,67 @@
+package scala.xml ;
+
+import java.lang.StringBuffer ; /* Java dependency! */
+import scala.collection.Map ;
+import scala.xml.nobinding.Element ;
+/** Utility functions for processing instances of bound and not bound XML classes.
+**/
+
+object Utility {
+
+ /** representation of text in a string that is well-formed XML.
+ ** the characters &lt; &gt; &amp; and &quot; are escaped
+ */
+ def escape( text:String ) = {
+ val s = new StringBuffer();
+ for( val c <- new IterableString(text).elements ) do c match {
+ case '<' => val _ = s.append("&lt;");
+ case '>' => val _ = s.append("&gt;");
+ case '&' => val _ = s.append("&amp;");
+ case '"' => val _ = s.append("&quot;");
+ case _ => val _ = s.append( c );
+ }
+ s.toString();
+ }
+
+ /** serializes an instance of Node to a string that contains well-formed XML **/
+ def toXML( n:Node ):String = n match {
+ case Text( t ) => escape( t );
+ case _ =>
+ val s = new StringBuffer();
+ s.append("<");
+ s.append( n.label );
+ if( null != n.attributes ) {
+ s.append( attr2xml( n.attributes.elements ) );{}
+ }
+ s.append(">");
+ s.append( toXML( n.children.elements ) );
+ s.append("</");
+ s.append( n.label );
+ s.append(">");
+ s.toString()
+ }
+
+ def toXML( ch:Iterator[Node] ):String = {
+ ch.foldLeft ("") { (s:String,n:Node) => { val t:String = toXML( n ); s + t }}
+ }
+
+ /** for a Node n, returns string representation of n.attributes **/
+ def attr2xml( attrib:Iterator[Pair[String, String]] ):String = {
+ attrib.foldLeft ("") { (s:String,x:Pair[String,String]) => {
+ val t = new StringBuffer(" ");
+ t.append( s );
+ t.append( x._1 );
+ t.append("=\"");
+ t.append( x._2 );
+ t.append("\"");
+ t.toString()
+ }
+ }
+ }
+
+ /** returns a hashcode for the given constituents of a node */
+ def hashCode( label:String, attribHashCode:int, children:Seq[Node] ) = {
+ label.hashCode() + attribHashCode + children.hashCode()
+ }
+
+}
diff --git a/sources/scala/xml/nobinding/Element.scala b/sources/scala/xml/nobinding/Element.scala
new file mode 100644
index 0000000000..5213ee8944
--- /dev/null
+++ b/sources/scala/xml/nobinding/Element.scala
@@ -0,0 +1,17 @@
+package scala.xml.nobinding;
+
+import scala.collection.Map ;
+import scala.xml.Node ;
+
+/** an XML node. use this when data binding is not desired.
+**/
+case class Element( symbol: Symbol, ch: List[Node] ) extends Node {
+
+ def label = symbol.name;
+ def children = ch;
+
+ protected val attribHashCode = 0; /* overriden at parse time */
+ def attributes : Map[String,String] = null ; /* overriden at parse time */
+
+}
+
diff --git a/sources/scala/xml/path/Expression.scala b/sources/scala/xml/path/Expression.scala
index d9f81d5836..0289582ffe 100644
--- a/sources/scala/xml/path/Expression.scala
+++ b/sources/scala/xml/path/Expression.scala
@@ -1,9 +1,9 @@
package scala.xml.path;
-import scala.xml.Element ;
+import scala.xml.Node ;
object Expression {
- def evaluate(expr:Expression):List[Element] = {
+ def evaluate(expr:Expression):List[Node] = {
Nil; // to do
}
}
@@ -19,7 +19,7 @@ case class Node[T<:Element]( conds:Condition* ) extends Expression {
}
};
*/
-case class Node( label:String, cond:Option[List[List[Expression]]] ) extends Expression ;
+case class PathNode( label:String, cond:Option[List[List[Expression]]] ) extends Expression ;
case class Attribute( name:String ) extends Expression;
diff --git a/sources/scala/xml/path/Parser.scala b/sources/scala/xml/path/Parser.scala
index e7828fe716..b675e4396f 100644
--- a/sources/scala/xml/path/Parser.scala
+++ b/sources/scala/xml/path/Parser.scala
@@ -22,9 +22,12 @@ class Parser( it:Iterator[char] ) with Scanner( it ) {
case DOT =>
nextToken; acc( SLASH );
- case IDENT =>
- val label = value; nextToken; val cs = conds; es = Node( label, cs ) :: es ;
-
+ case IDENT => {
+ val label = value;
+ nextToken;
+ val cs = conds;
+ es = PathNode( label, cs ) :: es
+ }
case SLASH =>
nextToken;
diff --git a/support/emacs/scala-mode.el b/support/emacs/scala-mode.el
index c203f00abb..71e7897fb5 100644
--- a/support/emacs/scala-mode.el
+++ b/support/emacs/scala-mode.el
@@ -4,7 +4,7 @@
;;; TODO
(require 'easymenu)
-(require 'newcomment)
+;;(require 'newcomment)
(require 'cl)
(require 'regexp-opt)
diff --git a/test/files/xml/lnk.scala b/test/files/xml/lnk.scala
index b338724c89..6a449d8ac4 100644
--- a/test/files/xml/lnk.scala
+++ b/test/files/xml/lnk.scala
@@ -1,7 +1,6 @@
// $Id$
-import scala.xml.PCDATA;
-import scala.xml.Element;
+import scala.xml.Node;
import dtd._;
object Test {
@@ -9,11 +8,11 @@ object Test {
// 3 ways to construct your data
def main(args:Array[String]) = {
// construct data using original Element name
- val b: Element = dtd._factory.get("link").match { case Some(x) => x(Nil)}; // safe
+ //val b: Node = dtd._factory.get("link").match { case Some(x) => x(Nil,null)}; // safe
// !!! System.out.println(b.toXML);
// construct data using constructor
- val c = Link(Name(PCDATA("hello-link")));
+ val c = Link(Name(scala.xml.Text("hello-link")));
//c.getAttribs.update("target", "http://www.scala.org");
System.out.println(c.toXML);
diff --git a/test/files/xml/xhtml.scala b/test/files/xml/xhtml.scala
index 0a6fc72d56..06f857612b 100644
--- a/test/files/xml/xhtml.scala
+++ b/test/files/xml/xhtml.scala
@@ -1,22 +1,22 @@
// $Id$
-import scala.xml.PCDATA;
+import scala.xml.Text;
import dtd._;
object Test {
def main( argv:Array[String] ) = {
- val link = A(PCDATA("link"));
+ val link = A(Text("link"));
//val m = new scala.collection.mutable.HashMap[String, String];
//m.put("href","http://lampwww.epfl.ch");
//link.setAttribs(m);
val body = Body(
- H1(PCDATA("Welcome to xhtml in scala")),
- P(PCDATA( "a paragraph")),
- P(PCDATA("another one, with a "),link,PCDATA(" to the LAMP homepage.")));
- val page = Html(Head(Title(PCDATA("a basic xhtml page"))), body);
+ H1(Text("Welcome to xhtml in scala")),
+ P(Text( "a paragraph")),
+ P(Text("another one, with a "),link,Text(" to the LAMP homepage.")));
+ val page = Html(Head(Title(Text("a basic xhtml page"))), body);
System.out.println(page.toXML) ;
val doc = load(argv(0));