From ff8ce7198a39af120c143acf3464d402c0fc1468 Mon Sep 17 00:00:00 2001 From: Matthias Zenger Date: Fri, 19 Dec 2003 00:55:09 +0000 Subject: Cleaned up some code and tried to make the vari... Cleaned up some code and tried to make the various parts of the API more consistent. --- sources/scala/Symbol.scala | 99 ++++----- sources/scala/collection/immutable/ListMap.scala | 253 +++++++++++------------ sources/scala/collection/immutable/Map.scala | 179 ++++++++-------- sources/scala/collection/immutable/TreeMap.scala | 17 +- sources/scala/xml/AttributedNode.scala | 60 +++--- sources/scala/xml/Node.scala | 16 +- 6 files changed, 313 insertions(+), 311 deletions(-) diff --git a/sources/scala/Symbol.scala b/sources/scala/Symbol.scala index 594838b12f..1077dbb49d 100644 --- a/sources/scala/Symbol.scala +++ b/sources/scala/Symbol.scala @@ -12,74 +12,81 @@ package scala; import org.xml.sax.InputSource; import scala.xml.{AttributedNode,Node, Text,Utility}; -import scala.collection.Map ; -import scala.collection.immutable.ListMap ; +import scala.collection.Map; +import scala.collection.immutable.ListMap; + /** Instances of Symbol can be created easily with * Scala's built-in quote mechanism. For instance, the Scala term * 'mysym will invoke the constructor of the * Symbol class in the following way: * new Symbol("mysym", Nil). The Scala term 'mysym('foo,'bar) - * will be treated as new Symbol("mysym", List(new Symbol("foo",Nil), new Symbol("bar",Nil) + * will be treated as + * new Symbol("mysym", List(new Symbol("foo",Nil), new Symbol("bar",Nil). * * @author Burak Emir, Martin Odersky - * @version 1.5, 2003-12-08 + * @version 1.5, 08/12/2003 */ case class Symbol(name: String, elems: Any*) extends AttributedNode { - // Node methods - def label = name; - def children:Seq[Node] = List.fromIterator( elems.elements map ( x => x match { - case n:Node => n; - case _ => Text( x.toString() ); - })); - - var attrMap:ListMap[String,String] = ListMap.Empty[String,String]; - - // AttributedNode methods, duplicated because of mixin misery - override def attributes : Map[String,String] = attrMap; - - /** converts this symbol to a string */ - override def toString():String = { - val s = new StringBuffer("'" + name) ; - val it = elems.elements; - if( it.hasNext ) { - s.append("("); - val e1 = it.next.toString(); - s.append( e1 ); - for( val e <- it ) { - s.append(','); s.append( e.toString() ); - } - s.append(")"); - } - s.toString(); - } - - /** this method destructively updates attributes of this symbol. - */ - final def % (attrs:List[AttrDef]):Symbol = { - attrMap = ListMap.Empty[String,String]; - for( val a <- attrs.elements ) { - attrMap = attrMap.update( a.key, a.value ); + /** Returns the symbol name as a string. + */ + def label: String = name; + + /** Returns the list of children of this symbol. + */ + def children: Seq[Node] = List.fromIterator(elems.elements map ( x => x match { + case n:Node => n; + case _ => Text(x.toString()); + })); + + private var attrMap: ListMap[String, String] = ListMap.Empty[String,String]; + + /** Returns a map representing the attributes of this node. + */ + def attributes: Map[String, String] = attrMap; + + /** Converts this symbol to a string + */ + override def toString(): String = { + val s = new StringBuffer("'" + name) ; + val it = elems.elements; + if( it.hasNext ) { + s.append("("); + val e1 = it.next.toString(); + s.append( e1 ); + for( val e <- it ) { + s.append(','); s.append( e.toString() ); + } + s.append(")"); + } + s.toString(); } - this - } - final def <=( value:String ) = new AttrDef( name, value ); - - case class AttrDef( key:String, value:String ); + /** This method destructively updates attributes of this symbol. + */ + final def %(attrs: List[Pair[String, String]]): Symbol = { + attrMap = ListMap.Empty[String,String]; + for(val a <- attrs.elements) { + attrMap = attrMap.update(a._1, a._2); + } + this + } - final def saveTo( filename:String ) = Symbol_IO.save( filename, this ); + final def <=(value: String) = new Pair(name, value); + final def saveTo(filename:String) = Symbol_IO.save(filename, this); } object Symbol_IO { // functions for generic symbol loading, saving - /** loads symbol from a given file*/ + /** loads symbol from a given file + */ def load( source:InputSource ):Symbol = scala.xml.nobinding.XML.load( source ); - /** saves symbol to filename (with encoding ISO-8859-1) */ + /** saves symbol to filename (with encoding ISO-8859-1) + */ def save( filename:String, doc:Symbol ):Unit = scala.xml.nobinding.XML.save( filename, doc ); } diff --git a/sources/scala/collection/immutable/ListMap.scala b/sources/scala/collection/immutable/ListMap.scala index 8089f6681e..5109188a46 100644 --- a/sources/scala/collection/immutable/ListMap.scala +++ b/sources/scala/collection/immutable/ListMap.scala @@ -9,19 +9,16 @@ package scala.collection.immutable; -class ListMapFactory[A] with MapFactory[A] { - def Empty[B] = ListMap.Empty[A,B]; -} object ListMap { - def Empty[A, B] = new ListMap[A, B]; - - /** bug: crashes analzyer with NullPointerException */ - /* - def fromList[A,B]( list:List[Pair[A,B]] ):ListMap[A,B] = - list.foldLeft (Empty[A,B]) { ( x:ListMap[A,B],y:Pair[A,B] ) => - x.update( y._1, y._2 ) }; - */ + def Empty[A, B] = new ListMap[A, B]; + + /** bug: crashes analzyer with NullPointerException */ + /* + def fromList[A,B]( list:List[Pair[A,B]] ):ListMap[A,B] = + list.foldLeft (Empty[A,B]) { ( x:ListMap[A,B],y:Pair[A,B] ) => + x.update( y._1, y._2 ) }; + */ } /** This class implements immutable maps using a list-based data @@ -33,126 +30,126 @@ object ListMap { * @version 1.0, 09/07/2003 */ class ListMap[A, B] with Map[A, B] { - /** A factory to create empty maps of the same type of keys. - */ - val factory = new ListMapFactory[A]; - - /** Returns the number of mappings in this map. - * - * @return number of mappings. - */ - def size: Int = 0; - - /** Check if this map maps key to a value and return the - * value if it exists. - * - * @param key the key of the mapping of interest - * @return the value of the mapping, if it exists - */ - def get(key: A): Option[B] = None; - - /** This method allows one to create a new map with an - * additional mapping from key - * to value. If the map contains already a - * mapping for key, it will be overridden by this - * function. - */ - def update(key: A, value: B): ListMap[A, B] = new Node(key, value); - - /** This creates a new mapping without the given key. - * If the map does not contain a mapping for the given key, the - * method returns the same map. - */ - def -(key: A): ListMap[A, B] = this; - - /** This returns an iterator over key-value pairs. - */ - def elements: Iterator[Pair[A, B]] = toList.elements; - - /** This return a list of key-value pairs. - */ - override def toList: List[Pair[A, B]] = Nil; - - /** Compares two maps for equality. - * Two maps are equal iff they contain exactly the - * same key-value pairs. - */ - override def equals(obj: Any): Boolean = - if (obj.isInstanceOf[scala.collection.Map[A, B]]) { - val that = obj.asInstanceOf[scala.collection.Map[A, B]]; - if (size != that.size) false else toList.forall { - case Pair(key, value) => that.get(key) match { - case None => false; - case Some(v) => v == value; - } - }; - } else - false; + + /** This method returns a new ListMap instance mapping keys of the + * same type to values of type C. + */ + def empty[C] = new ListMap[A, C]; + + /** Returns the number of mappings in this map. + * + * @return number of mappings. + */ + def size: Int = 0; + + /** Check if this map maps key to a value and return the + * value if it exists. + * + * @param key the key of the mapping of interest + * @return the value of the mapping, if it exists + */ + def get(key: A): Option[B] = None; + + /** This method allows one to create a new map with an + * additional mapping from key + * to value. If the map contains already a + * mapping for key, it will be overridden by this + * function. + */ + def update(key: A, value: B): ListMap[A, B] = new Node(key, value); + + /** This creates a new mapping without the given key. + * If the map does not contain a mapping for the given key, the + * method returns the same map. + */ + def -(key: A): ListMap[A, B] = this; + + /** This returns an iterator over key-value pairs. + */ + def elements: Iterator[Pair[A, B]] = toList.elements; + + /** This return a list of key-value pairs. + */ + override def toList: List[Pair[A, B]] = Nil; + + /** Compares two maps for equality. + * Two maps are equal iff they contain exactly the + * same key-value pairs. + */ + override def equals(obj: Any): Boolean = + if (obj.isInstanceOf[scala.collection.Map[A, B]]) { + val that = obj.asInstanceOf[scala.collection.Map[A, B]]; + if (size != that.size) false else toList.forall { + case Pair(key, value) => that.get(key) match { + case None => false; + case Some(v) => v == value; + } + }; + } else + false; override def hashCode(): Int = 0; protected class Node(key: A, value: B) extends ListMap[A, B] { - /** Returns the number of mappings in this map. - * - * @return number of mappings. - */ - override def size: Int = ListMap.this.size + 1; - - /** Is this an empty map? - * - * @return true, iff the map is empty. - */ - override def isEmpty: Boolean = false; - - /** Retrieve the value which is associated with the given key. This - * method throws an exception if there is no mapping from the given - * key to a value. - * - * @param key the key - * @return the value associated with the given key. - */ - override def apply(k: A): B = if (k == key) value else ListMap.this(k); - - /** Check if this map maps key to a value and return the - * value if it exists. - * - * @param key the key of the mapping of interest - * @return the value of the mapping, if it exists - */ - override def get(k: A): Option[B] = - if (k == key) Some(value) else ListMap.this.get(k); - - /** This method allows one to create a new map with an - * additional mapping from key - * to value. If the map contains already a - * mapping for key, it will be overridden by this - * function. - */ - override def update(k: A, v: B): ListMap[A, B] = - if (k == key) { - new ListMap.this.Node(k, v); - } else { - val tail = ListMap.this.update(k,v); new tail.Node(key, value) - } - - /** This creates a new mapping without the given key. - * If the map does not contain a mapping for the given key, the - * method returns the same map. - */ - override def -(k: A): ListMap[A, B] = - if (k == key) - ListMap.this - else { - val tail = ListMap.this - k; new tail.Node(key, value) - } - - /** This return a list of key-value pairs. - */ - override def toList: List[Pair[A, B]] = Pair(key, value) :: ListMap.this.toList; - - override def hashCode(): Int = - (key.hashCode() ^ value.hashCode()) + ListMap.this.hashCode(); + /** Returns the number of mappings in this map. + * + * @return number of mappings. + */ + override def size: Int = ListMap.this.size + 1; + + /** Is this an empty map? + * + * @return true, iff the map is empty. + */ + override def isEmpty: Boolean = false; + + /** Retrieve the value which is associated with the given key. This + * method throws an exception if there is no mapping from the given + * key to a value. + * + * @param key the key + * @return the value associated with the given key. + */ + override def apply(k: A): B = if (k == key) value else ListMap.this(k); + + /** Check if this map maps key to a value and return the + * value if it exists. + * + * @param key the key of the mapping of interest + * @return the value of the mapping, if it exists + */ + override def get(k: A): Option[B] = + if (k == key) Some(value) else ListMap.this.get(k); + + /** This method allows one to create a new map with an + * additional mapping from key + * to value. If the map contains already a + * mapping for key, it will be overridden by this + * function. + */ + override def update(k: A, v: B): ListMap[A, B] = + if (k == key) { + new ListMap.this.Node(k, v); + } else { + val tail = ListMap.this.update(k,v); new tail.Node(key, value) + } + + /** This creates a new mapping without the given key. + * If the map does not contain a mapping for the given key, the + * method returns the same map. + */ + override def -(k: A): ListMap[A, B] = + if (k == key) + ListMap.this + else { + val tail = ListMap.this - k; new tail.Node(key, value) + } + + /** This return a list of key-value pairs. + */ + override def toList: List[Pair[A, B]] = Pair(key, value) :: ListMap.this.toList; + + override def hashCode(): Int = + (key.hashCode() ^ value.hashCode()) + ListMap.this.hashCode(); } } - - diff --git a/sources/scala/collection/immutable/Map.scala b/sources/scala/collection/immutable/Map.scala index 84b79bd813..0dd67df7b1 100644 --- a/sources/scala/collection/immutable/Map.scala +++ b/sources/scala/collection/immutable/Map.scala @@ -9,6 +9,7 @@ package scala.collection.immutable; + /** This trait extends the Map interface of collections that unambiguously map * keys to values (i.e. a key is mapped to at least one value). * This trait defines the interface for functional map implementations @@ -16,71 +17,70 @@ package scala.collection.immutable; * Concrete map implementations have to provide functionality for the * abstract methods in scala.collection.Map as well as for * factory, update, and -. - + * * @author Matthias Zenger, Erik Stenman * @version 1.0, 03/12/2003 */ -trait Map[KEY, VALUE] with scala.collection.Map[KEY, VALUE] { - - /** A factory to create empty maps of the same type of keys. - */ - val factory:MapFactory[KEY]; - - - /** This method allows one to create a new map with an - * additional mapping from key - * to value. If the map contains already a - * mapping for key, it will be overridden by this - * function. - */ - def update(key: KEY, value: VALUE): Map[KEY, VALUE]; - - /** This creates a new mapping without the given key. - * If the map does not contain a mapping for the given key, the - * method returns the same map. - */ - def -(key: KEY): Map[KEY, VALUE]; - - /** This method defines syntactic sugar for adding a - * mapping. It is typically used in the following way: - *
-  *  map + key -> value;
-  *  
- */ - def +(key: KEY): MapTo = new MapTo(key); - - - /** incl can be used to add many mappings at the same time - * to the map. The method assumes that a mapping is represented - * by a Pair object who's first component denotes the - * key, and who's second component refers to the value. - */ - def incl(mappings: Pair[KEY, VALUE]*): Map[KEY, VALUE] = incl(mappings); - - /** incl can be used to add many mappings at the same time - * to the map. The method assumes that each mapping is represented - * by an Iterator over Pair objects who's first component - * denotes the key, and who's second component refers to the value. - */ - def incl(map: Iterable[Pair[KEY, VALUE]]): Map[KEY, VALUE] = { - val iter = map.elements; - var res = this; - while (iter.hasNext) { - val Pair(key, value) = iter.next; - res = res.update(key, value); +trait Map[A, B] with scala.collection.Map[A, B] { + + /** This method returns a new map instance of the same class + * mapping keys of the same type to values of type C. + */ + def empty[C]: Map[A, C]; + + /** This method allows one to create a new map with an + * additional mapping from key + * to value. If the map contains already a + * mapping for key, it will be overridden by this + * function. + */ + def update(key: A, value: B): Map[A, B]; + + /** This creates a new mapping without the given key. + * If the map does not contain a mapping for the given key, the + * method returns the same map. + */ + def -(key: A): Map[A, B]; + + /** This method defines syntactic sugar for adding a + * mapping. It is typically used in the following way: + *
+     *  map + key -> value;
+     *  
+ */ + def +(key: A): MapTo = new MapTo(key); + + /** incl can be used to add many mappings at the same time + * to the map. The method assumes that a mapping is represented + * by a Pair object who's first component denotes the + * key, and who's second component refers to the value. + */ + def incl(mappings: Pair[A, B]*): Map[A, B] = incl(mappings); + + /** incl can be used to add many mappings at the same time + * to the map. The method assumes that each mapping is represented + * by an Iterator over Pair objects who's first component + * denotes the key, and who's second component refers to the value. + */ + def incl(map: Iterable[Pair[A, B]]): Map[A, B] = { + val iter = map.elements; + var res = this; + while (iter.hasNext) { + val Pair(key, value) = iter.next; + res = res.update(key, value); + } + res } - res; - } - - /** This method will return a map where all the mappings - * for the given sequence of keys are removed from the map. - */ - def excl(keys: KEY*): Map[KEY, VALUE] = excl(keys); - - /** This method removes all the mappings for keys provided by an - * iterator over the elements of the keys object. - */ - def excl(keys: Iterable[KEY]): Map[KEY, VALUE] = { + + /** This method will return a map where all the mappings + * for the given sequence of keys are removed from the map. + */ + def excl(keys: A*): Map[A, B] = excl(keys); + + /** This method removes all the mappings for keys provided by an + * iterator over the elements of the keys object. + */ + def excl(keys: Iterable[A]): Map[A, B] = { val iter = keys.elements; var res = this; while (iter.hasNext) { @@ -89,11 +89,11 @@ trait Map[KEY, VALUE] with scala.collection.Map[KEY, VALUE] { res; } - /** This function transforms all the values of mappings contained + /** This function transforms all the values of mappings contained * in this map with function f. */ - def map[C <: Any](f: (KEY, VALUE) => C): Map[KEY, C] = { - var res = factory.Empty[C]; + def map[C](f: (A, B) => C): Map[A, C] = { + var res = empty[C]; elements foreach { case Pair(key, value) => res = res.update(key, f(key, value)); } @@ -103,7 +103,7 @@ trait Map[KEY, VALUE] with scala.collection.Map[KEY, VALUE] { /** This method removes all the mappings for which the predicate * p returns false. */ - def filter(p: (KEY, VALUE) => Boolean): Map[KEY, VALUE] = { + def filter(p: (A, B) => Boolean): Map[A, B] = { var res = this; toList foreach { case Pair(key, value) => if (p(key, value)) { res = res.excl(key); } @@ -127,32 +127,31 @@ trait Map[KEY, VALUE] with scala.collection.Map[KEY, VALUE] { res; } + "}"; - /** Compares two maps for equality. - * Two maps are equal iff they contain exactly the - * same key-value pairs. - */ - override def equals(obj: Any): Boolean = - if (obj.isInstanceOf[scala.collection.Map[KEY, VALUE]]) { - val that = obj.asInstanceOf[scala.collection.Map[KEY, VALUE]]; - if (size != that.size) false else elements.forall { - case Pair(key, value) => that.get(key) match { - case None => false; - case Some(v) => v == value; - } - }; - } else - false; + /** Compares two maps for equality. + * Two maps are equal iff they contain exactly the + * same key-value pairs. + */ + override def equals(obj: Any): Boolean = + if (obj.isInstanceOf[scala.collection.Map[A, B]]) { + val that = obj.asInstanceOf[scala.collection.Map[A, B]]; + if (size != that.size) + false + else + elements forall { + case Pair(key, value) => that.get(key) match { + case None => false; + case Some(v) => v == value; + } + } + } else + false; - /** This method controls how a mapping is represented in the string - * representation provided by method toString. - */ - def mappingToString(p: Pair[KEY, VALUE]) = p._1.toString() + " -> " + p._2; + /** This method controls how a mapping is represented in the string + * representation provided by method toString. + */ + def mappingToString(p: Pair[A, B]) = p._1.toString() + " -> " + p._2; - class MapTo(key: KEY) { - def ->(value: VALUE): Map[KEY, VALUE] = update(key, value); + class MapTo(key: A) { + def ->(value: B): Map[A, B] = update(key, value); } } - -abstract class MapFactory[KEY] { - def Empty[VALUE]:Map[KEY,VALUE]; -} diff --git a/sources/scala/collection/immutable/TreeMap.scala b/sources/scala/collection/immutable/TreeMap.scala index c903721b6b..2473ed9118 100644 --- a/sources/scala/collection/immutable/TreeMap.scala +++ b/sources/scala/collection/immutable/TreeMap.scala @@ -9,20 +9,20 @@ package scala.collection.immutable; -class TreeMapFactory[KEY](order:Order[KEY]) extends MapFactory[KEY] { - def Empty[VALUE] = new TreeMap[KEY,VALUE](order); -} /** This class implements immutable maps using a tree. * * @author Erik Stenman, Matthias Zenger * @version 1.0, 23/07/2003 */ - class TreeMap[KEY,VALUE](order:Order[KEY]) extends Tree[KEY,Pair[KEY,VALUE]](order) with Map[KEY, VALUE] { - override type This = TreeMap[KEY,VALUE]; + class TreeMap[KEY, VALUE](order: Order[KEY]) extends Tree[KEY, Pair[KEY, VALUE]](order) + with Map[KEY, VALUE] { + + override type This = TreeMap[KEY, VALUE]; + /** A factory to create empty maps of the same type of keys. - */ - val factory = new TreeMapFactory[KEY](order); + */ + def empty[C] = new TreeMap[KEY, C](order); /** Returns the key of an entry. * This method has to be defined by concrete implementations @@ -66,9 +66,6 @@ class TreeMapFactory[KEY](order:Order[KEY]) extends MapFactory[KEY] { case _ => None; } - - - /** Retrieve the value which is associated with the given key. This * method throws an exception if there is no mapping from the given * key to a value. diff --git a/sources/scala/xml/AttributedNode.scala b/sources/scala/xml/AttributedNode.scala index 5ee5fce8d5..600c4b532d 100644 --- a/sources/scala/xml/AttributedNode.scala +++ b/sources/scala/xml/AttributedNode.scala @@ -2,34 +2,38 @@ package scala.xml ; import scala.collection.Map; -/** superclass for specific representation of XML elements. These are created by -** a xxx2scala binding tool -**/ -trait AttributedNode extends Node { - - final def apply(key:String):Option[String] = attributes.get(key); - - /** returns a mapping from all present attributes to values */ - def attributes: Map[String,String]; - - /** destructively updated attributes - */ - def % (attrs:List[Symbol#AttrDef]):AttributedNode ; - /** hashcode for this node*/ - override def hashCode() = Utility.hashCode( label, attributes.toList.hashCode(), children ); - - override def toXML:String = Utility.toXML( this ); - - override def toString() = toXML /*{ - var s = new StringBuffer( "AttributedNode('"+label ); - val as = attributes; - if( as != null ) - s.append( Utility.attr2xml( as.elements ) ); - s.append("("); - s.append( children.toString() ); - s.append(")"); - s.toString(); - }*/ +/** Superclass for specific representation of XML elements. These are created by + * a xxx2scala binding tool + */ +trait AttributedNode extends Node { + /** Returns the value for the given attribute. + */ + final def apply(key: String): Option[String] = attributes.get(key); + + /** Returns a mapping from all present attributes to values. + */ + def attributes: Map[String, String]; + + /** Destructively updated attributes. + */ + def %(attrs: List[Pair[String, String]]): AttributedNode; + + /** Returns the hashcode for this node. + */ + override def hashCode() = Utility.hashCode(label, attributes.toList.hashCode(), children); + + override def toXML:String = Utility.toXML(this); + + override def toString() = toXML /*{ + var s = new StringBuffer( "AttributedNode('"+label ); + val as = attributes; + if( as != null ) + s.append( Utility.attr2xml( as.elements ) ); + s.append("("); + s.append( children.toString() ); + s.append(")"); + s.toString(); + }*/ } diff --git a/sources/scala/xml/Node.scala b/sources/scala/xml/Node.scala index 7ce7f44fbf..10a3f75221 100644 --- a/sources/scala/xml/Node.scala +++ b/sources/scala/xml/Node.scala @@ -1,13 +1,11 @@ package scala.xml ; -/** trait for representation of XML elements. These are created by -** a xxx2scala binding tool -**/ -trait Node { - - def label: String; - def children: Seq[ Node ]; - - def toXML: String; +/** Trait for representation of XML elements. These are created by + * a xxx2scala binding tool + */ +trait Node { + def label: String; + def children: Seq[Node]; + def toXML: String; } -- cgit v1.2.3