summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorburaq <buraq@epfl.ch>2003-09-30 10:52:54 +0000
committerburaq <buraq@epfl.ch>2003-09-30 10:52:54 +0000
commit3ec4228dafa6d7e6735a7288bbb94429b1edb487 (patch)
treec8c647494f765287a8db5cce85bdd870f4bdb676 /sources
parent179b3f78929a10e8f7d051016d61bd7ee0902e8c (diff)
downloadscala-3ec4228dafa6d7e6735a7288bbb94429b1edb487.tar.gz
scala-3ec4228dafa6d7e6735a7288bbb94429b1edb487.tar.bz2
scala-3ec4228dafa6d7e6735a7288bbb94429b1edb487.zip
dtd2scala reimplemented in scala
Diffstat (limited to 'sources')
-rw-r--r--sources/scala/tools/dtd2scala/DeclToScala.scala355
-rw-r--r--sources/scala/tools/dtd2scala/Main.scala119
-rw-r--r--sources/scala/tools/dtd2scala/MainHandler.scala115
-rw-r--r--sources/scala/tools/dtd2scala/XMLDecl.scala14
4 files changed, 603 insertions, 0 deletions
diff --git a/sources/scala/tools/dtd2scala/DeclToScala.scala b/sources/scala/tools/dtd2scala/DeclToScala.scala
new file mode 100644
index 0000000000..cb4ea0e6b8
--- /dev/null
+++ b/sources/scala/tools/dtd2scala/DeclToScala.scala
@@ -0,0 +1,355 @@
+package scala.tools.dtd2scala ;
+
+import java.io.Writer ;
+import java.io.PrintWriter ;
+import java.io.File ;
+import java.io.FileWriter ;
+import java.io.OutputStream ;
+import java.io.OutputStreamWriter ;
+
+import java.io.IOException ;
+
+import java.util.Map ;
+import java.util.Iterator ;
+
+import scalac.util.Name ;
+import scalac.ast.parser.Scanner ;
+
+class DeclToScala(fOut:PrintWriter, moduleName:String) {
+
+ val DEFAULT_moduleName = "myXML";
+
+ final val COMPRESS_DEFAULT:String = "true"; // do hash-consing on load
+
+ final val ATTRIBS_VARDEF:String =
+ "var _at:scala.xml.javaAdapter.Map[String,String] = new HashMap[String,String];";
+ //static final String ATTRIB_MAP = "attribs";
+ //static final String ATTRIB_T = "scala.Map[String,String]";
+
+ 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";
+ //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 GET_CHILDREN_DEF:String = "def getChildren:scala.Seq[scala.xml.Element] = _ch ;";
+ final val SET_CHILDREN_DEF:String = "def setChildren( l:scala.Seq[scala.xml.Element] ):Unit = {_ch = l};";
+ final val GET_ATTRIBS_DEF:String = "def getAttribs:scala.xml.javaAdapter.Map[String,String] = _at ;";
+ final val SET_ATTRIBS_DEF:String = "def setAttribs( m:scala.xml.javaAdapter.Map[String,String] ):Unit = {_at = m};";
+
+ //static final String HASHCODE_DEF = "override def hashCode():int = { getChildren.hashCode() + getAttribs.hashCode() + getName.hashCode() }";
+
+ final val IND_STEP:int = 5;
+/*
+ def this() = { this(new PrintWriter( System.out ), DEFAULT_moduleName) }
+
+ def this( outdir:File, moduleName:String ) = { this(
+ new PrintWriter( new FileWriter( new File( outdir, moduleName+".scala" ))),
+ moduleName) }
+*/
+ var fIndent:int = 0;
+
+ def begin():Unit = {
+ 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.xml.javaAdapter.Map ;");
+ fOut.println("import scala.xml.javaAdapter.HashMap ;");
+ }
+
+ def end():Unit = {
+ 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
+
+ fOut.println( "final def "+clazzName+"(ch:Seq[Element]):"+clazzName+" = new "+clazzName+"( null[scala.Map[String,String]], ch ) ;" );
+
+ printIndent();
+
+ fOut.println( "final def "+clazzName+"( el:Element ):"+clazzName+" = new "+clazzName+"( null[scala.Map[String,String]], el::Nil[Element] ) ;" );
+
+ printIndent();
+
+ // might contain text
+ if( decl.contentModel.indexOf("#PCDATA") != -1 ) {
+
+ fOut.println( "final def "+clazzName+"( text:String ):"+clazzName+" = new "+clazzName+"( PCDATA( text ) );" );
+ 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( SET_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 = {
+ for (val i<-List.range(0, fIndent)) do {
+ fOut.print(' ');
+ }
+ }
+
+ /**
+ * @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.put(\"" );
+ 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( " ) ;");
+ }
+
+ def printFactory( elemMap:Map ):Unit = {
+
+ printIndent();
+ fOut.println(
+ "val _factory: scala.xml.javaAdapter.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 scala.xml.javaAdapter.HashMap[String, scala.Seq[scala.xml.Element] => scala.xml.Element] ;");
+ //JAVA: for(Iterator it = elemMap.keySet().iterator(); it.hasNext(); )
+ val it:Iterator = elemMap.keySet().iterator();
+ while( it.hasNext() ) {
+ val decl:ElemDecl = elemMap.get( it.next() ).asInstanceOf[ ElemDecl ];
+ printIndent();
+ fOut.print( "res.put(\"" );
+ fOut.print( decl.name );
+ fOut.print( "\",(x:scala.Seq[scala.xml.Element] => { val res = ");
+ fOut.print( cookedCap( decl.name ));
+ fOut.println("(); res.setChildren(x); res }));");
+ }
+ printIndent();
+ fOut.println("res");
+ printIndent();
+ fOut.println( "}");
+ fIndent = fIndent - IND_STEP;
+
+ }
+
+ def printContainsTextDef( elemMap:Map ):Unit = {
+ printIndent();
+ fOut.println("val _containsMap: scala.xml.javaAdapter.Map[scala.String, boolean] = {");
+ fIndent = fIndent + IND_STEP;
+ printIndent();
+ fOut.println("val res = new scala.xml.javaAdapter.HashMap[scala.String, boolean] ;");
+
+ val it:Iterator = elemMap.keySet().iterator();
+ while( it.hasNext() ) {
+ val decl:ElemDecl = elemMap.get( it.next() ).asInstanceOf[ ElemDecl ];
+ printIndent();
+ fOut.print( "res.put(\"" );
+ fOut.print( decl.name );
+ fOut.print( "\",");
+
+ if( decl.contentModel.indexOf("#PCDATA") != -1 )
+ fOut.print("true");
+ else
+ fOut.print("false");
+
+ 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("val b:scala.Object = fAdapter.loadXML( filename );");
+ printIndent();
+ fOut.println("b.asInstanceOf[Element]");
+ printIndent();
+ fOut.println("};");
+ fIndent = fIndent - IND_STEP;
+ };
+
+ def toScala( elemMap:Map ):Unit = {
+ begin();
+
+ fOut.println("/** the following elements are there");
+
+ val it:Iterator = elemMap.keySet().iterator();
+ while( it.hasNext() ) {
+ val decl:ElemDecl = elemMap.get( it.next() ).asInstanceOf[ ElemDecl ];
+ fOut.print(" * ");
+ fOut.print( decl.name );
+ fOut.print(" : [");
+ fOut.print( decl.contentModel );
+ fOut.println(']');
+ fOut.print(" * ");
+ fOut.println( "attribs: "+decl.attribs.keySet() );
+ }
+ fOut.println("*/");
+
+ val it2:Iterator = elemMap.keySet().iterator();
+ while( it2.hasNext() ) {
+ val decl:ElemDecl = elemMap.get( it2.next() ).asInstanceOf[ ElemDecl ];
+ toScala( decl );
+ }
+
+ printContainsTextDef( elemMap );
+ printFactory( elemMap );
+ printLoaderDef();
+
+ end();
+ }
+
+ def toScala( decl:XMLDecl ):Unit = {
+ decl.match {
+ case ElemDecl( _, _, _) =>
+
+ printClassDef( decl.asInstanceOf[ ElemDecl ] );
+
+ case AttrDecl( name, attrType ) =>
+
+ if( attrType.equals("CDATA") ) {
+ //printSetMethod(name);
+ printGetMethod(name);
+
+ } else { // ignore non-CDATA attribs
+
+ System.err.print("[ignoring attribute \""
+ +name+"\" of type \""
+ +attrType+"\"]");
+ }
+ case _ =>
+ System.err.println("unexpected XMLDecl"); System.exit(-1);
+ }
+}
+
+
+//
+// cooking raw names
+//
+
+def cooked( ckd:StringBuffer, raw:String, off:int ):String = {
+ for( val i <- List.range( off, raw.length()) ) do {
+ val _ = raw.charAt( i ).match {
+ case '-' =>
+ ckd.append( '_' )
+ case ':' =>
+ ckd.append( '_' )
+ case x =>
+ ckd.append( x )
+ };
+ };
+
+ if( toy.isKeyword(raw)) {
+ val _ = ckd.append('$');
+ };
+ ckd.toString()
+
+}
+
+// type -> type$
+// http-equiv -> http_equiv
+
+def cooked( raw:String ):String = {
+ return cooked(new StringBuffer(), raw, 0);
+}
+
+// type -> Type$
+// http-equiv -> Http_equiv
+
+def cookedCap( raw:String ):String = {
+ val ckd:StringBuffer = new StringBuffer();
+ ckd.append( Character.toUpperCase( raw.charAt( 0 ) ));
+ return cooked( ckd, raw, 1);
+}
+
+ val toy:Scanner = new Scanner()
+
+}
diff --git a/sources/scala/tools/dtd2scala/Main.scala b/sources/scala/tools/dtd2scala/Main.scala
new file mode 100644
index 0000000000..0771f59a85
--- /dev/null
+++ b/sources/scala/tools/dtd2scala/Main.scala
@@ -0,0 +1,119 @@
+package scala.tools.dtd2scala ;
+
+import org.xml.sax.SAXParseException;
+import org.xml.sax.SAXException;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.ext.DeclHandler;
+
+import java.io.{File,FileWriter,PrintWriter,StringReader};
+
+import java.util.Map ;
+import java.util.HashMap ;
+import java.util.TreeMap ;
+import java.util.Iterator ;
+
+object Main {
+ // this implementation included in JDK1.4, but cannot resolve relative sysIDs
+ final val DEFAULT_PARSER_NAME:String = "org.apache.crimson.parser.XMLReaderImpl" ;
+
+ // DEFAULT_PARSER_NAME = "org.apache.xerces.parsers.SAXParser" ;
+
+ final val DOC_WRAPPER_FRONT:String = "<!DOCTYPE doc SYSTEM \"";
+ final val DOC_WRAPPER_BACK:String = "\"><doc></doc>";
+
+ /** print usage string
+ */
+ def usage():Unit = {
+ System.out.println("usage: dtd2scala [ -d <dir> ] <sysID> <object name>");
+ System.out.println(" binds a DTD to class definitions");
+ System.out.println(" will create a file [<dir>/]<object name>.scala");
+ System.out.println("<dir> is the output directory [default is the path of <sysID>]");
+ System.out.println("<sysID> is a system ID of an XML DTD");
+ System.out.println("<object name> is the name of the resulting Scala source file ");
+
+ }
+
+ /** main method. parses dtd of doc with <sysID> and translates to scala case
+ * class definitions.
+ * definitions are printed to stdout.
+ * @argv two parameters, sysID and object name
+ */
+
+ def main(argv:Array[String]):Unit /*throws Exception*/ = {
+
+ if ( argv.length == 0 ) {
+ usage();
+ System.exit(-1);
+ }
+
+ if(( argv.length != 2 )
+ &&(( argv.length != 4 )
+ ||(( argv.length == 4 )&&( !argv( 0 ).equals("-d"))))) {
+ //System.out.println( argv.length+"ga"+argv[0].equals("-d") );
+ usage();
+ System.exit(-1);
+ }
+
+ val myH:MainHandler = new MainHandler();
+ val sysID:String = argv( argv.length - 2 );
+ val objname:String = argv( argv.length - 1 );
+ var outdir:File = null.asInstanceOf[ File ];
+ if ( argv.length == 4 ) {
+ outdir = new File( argv( 1 ));
+ } else {
+ outdir = new File( sysID ).getParentFile();
+ }
+ val parser:XMLReader =
+ XMLReaderFactory.createXMLReader( DEFAULT_PARSER_NAME );
+
+ try {
+ parser.setProperty("http://xml.org/sax/properties/declaration-handler", myH);
+ }
+ catch{
+ case e:SAXException =>
+ e.printStackTrace(System.err);
+ }
+ try {
+ // create isrc for a fake doc referencing the DTD
+ val isrc:InputSource = new InputSource(
+ new StringReader( DOC_WRAPPER_FRONT
+ + sysID
+ + DOC_WRAPPER_BACK ) );
+ val curDir:String = System.getProperty("user.dir");
+ //String sysID2 = new File( sysID ).getAbsolutePath();
+ //System.err.println( "file:///"+curDir+"/fubar.xml" );
+ isrc.setSystemId( "file:///"+curDir+"/fubar.xml" );
+ parser.parse( isrc );
+ }
+ catch {
+ case e:SAXParseException =>
+ System.err.println("SaxParseEx");
+ e.printStackTrace( System.err );
+ case e:Exception =>
+ System.err.println("error: Parse error occurred - "+e.getMessage());
+ if( e.isInstanceOf[SAXException] ) {
+ e.asInstanceOf[SAXException].getException().printStackTrace(System.err)
+ } else {
+ e.printStackTrace()
+ }
+ }
+
+ // myH.print(); // DEBUG
+
+ // instantiate translator
+ /* does not work due to backend handling of constructors, FIXME
+ val translate:DeclToScala = new DeclToScala( outdir, objname );
+ */
+ val p = new PrintWriter( new FileWriter( new File( outdir, objname+".scala" )));
+ val translate:DeclToScala = new DeclToScala( p, objname );
+ // translate
+ translate.toScala( myH.elemMap );
+
+
+ } // main
+} //object main
+
diff --git a/sources/scala/tools/dtd2scala/MainHandler.scala b/sources/scala/tools/dtd2scala/MainHandler.scala
new file mode 100644
index 0000000000..ff8963d111
--- /dev/null
+++ b/sources/scala/tools/dtd2scala/MainHandler.scala
@@ -0,0 +1,115 @@
+package scala.tools.dtd2scala ;
+
+//import org.xml.sax.SAXParseException;
+//import org.xml.sax.SAXException;
+//import org.xml.sax.InputSource;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.Attributes;
+import org.xml.sax.ext.DeclHandler;
+
+import java.util.Map ;
+import java.util.HashMap ;
+import java.util.TreeMap ;
+import java.util.Iterator ;
+
+/** 2 do :
+ - handle modes of attributes (add #REQUIRED ones, fill in default of #IMPLIED)
+ - allow package prefix to be given !
+ - allow output directory to be given !
+*/
+
+class MainHandler extends DefaultHandler with DeclHandler {
+
+ var elemMap:Map = new HashMap(); // elementName -> elementDecl
+
+ // DTDHandler methods
+
+ /** encountered element declaration
+ */
+ def elementDecl( name:String, contentModel:String ):Unit
+ /* throws SAXException */ ={
+
+ val decl:ElemDecl = elemMap.get( name ).asInstanceOf[ ElemDecl ];
+
+ if( decl == null ) {
+ val _ = elemMap.put( name, new ElemDecl( name,
+ contentModel,
+ new HashMap() ));
+ } else {
+ val newDecl = ElemDecl( decl.name, contentModel, decl.attribs );
+ val _ = elemMap.put( name, newDecl );
+ }
+
+ } // elementDecl(String,String)
+
+ /** encountered attribute declaration.
+ */
+ def attributeDecl(elementName:String,
+ attributeName:String,
+ tpe:String,
+ valueDefault:String,
+ value:String ) /*throws SAXException*/ = {
+ var attribs:Map = null.asInstanceOf[ Map ];
+
+ val decl:ElemDecl = elemMap.get( elementName ).asInstanceOf[ ElemDecl ];
+
+ if( decl == null )
+ {
+ attribs = new TreeMap();
+ elemMap.put( elementName,
+ new ElemDecl( elementName,
+ null,
+ attribs ));
+ }
+ else
+ attribs = decl.attribs;
+
+
+ val _ = attribs.put( attributeName, new AttrDecl(attributeName,
+ tpe ));
+
+ } // attributeDecl(String,String,String,String,String)
+
+
+ /** Internal entity declaration.
+ */
+ def internalEntityDecl( name:String, text:String ):Unit
+ /*throws SAXException*/ = {
+ // ignore
+ }
+
+ /** External entity declaration.
+ */
+ def externalEntityDecl( name:String,
+ publicId:String ,
+ systemId:String ):Unit
+ /*throws SAXException*/ = {
+ // ignore
+ }
+
+ /*
+
+ // for debugging
+
+ public void print() {
+ for(Iterator it = elemMap.keySet().iterator(); it.hasNext(); ) {
+ ElemDecl decl = (ElemDecl) elemMap.get( it.next() );
+ System.out.print(decl.name);
+ AttrDecl adecl = null;
+ System.out.print("{");
+ for(Iterator it2 = decl.attribs.keySet().iterator();
+ it2.hasNext(); ) {
+ if(adecl != null)
+ System.out.print(",");
+ adecl = (AttrDecl) decl.attribs.get( it2.next() );
+ System.out.print(adecl.name+":"+adecl.type);
+ }
+ System.out.println("}");
+ }
+
+
+ }
+ */
+
+} // class MyDTDHandler
+
diff --git a/sources/scala/tools/dtd2scala/XMLDecl.scala b/sources/scala/tools/dtd2scala/XMLDecl.scala
new file mode 100644
index 0000000000..a13cad461d
--- /dev/null
+++ b/sources/scala/tools/dtd2scala/XMLDecl.scala
@@ -0,0 +1,14 @@
+package scala.tools.dtd2scala ;
+
+import java.util.Map ;
+
+abstract class XMLDecl ;
+
+case class ElemDecl( name:String ,
+ contentModel:String ,
+ attribs:Map ) extends XMLDecl; /*AttrDecl[]*/
+
+// ignore default values 4 now
+case class AttrDecl( name:String,
+ tpe:String ) extends XMLDecl;
+