summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorburaq <buraq@epfl.ch>2004-07-20 10:34:48 +0000
committerburaq <buraq@epfl.ch>2004-07-20 10:34:48 +0000
commit8cfefad21f54d8edece6980673f94acc03d9c9d0 (patch)
treec00566120bcb36c2014b8317e2d790eedba045af
parent9ed892ea8fb7c169e4bf41ffe38b612eb6b3f8a0 (diff)
downloadscala-8cfefad21f54d8edece6980673f94acc03d9c9d0.tar.gz
scala-8cfefad21f54d8edece6980673f94acc03d9c9d0.tar.bz2
scala-8cfefad21f54d8edece6980673f94acc03d9c9d0.zip
parsing into lib continues
-rw-r--r--config/list/library.lst1
-rw-r--r--sources/scala/xml/ProcInstr.scala15
-rw-r--r--sources/scala/xml/parsing/ConstructingHandler.scala53
-rw-r--r--sources/scala/xml/parsing/MarkupHandler.scala6
-rw-r--r--sources/scala/xml/parsing/MarkupParser.scala94
-rw-r--r--test/files/jvm/xmlLiterals.scala4
6 files changed, 116 insertions, 57 deletions
diff --git a/config/list/library.lst b/config/list/library.lst
index f7acac0af4..0d7a6d9962 100644
--- a/config/list/library.lst
+++ b/config/list/library.lst
@@ -214,6 +214,7 @@ xml/nobinding/NoBindingFactoryAdapter.scala
xml/nobinding/XML.scala
xml/parsing/AttribValue.scala
+xml/parsing/ConstructingHandler.scala
xml/parsing/FatalError.scala
xml/parsing/MarkupParser.scala
xml/parsing/MarkupHandler.scala
diff --git a/sources/scala/xml/ProcInstr.scala b/sources/scala/xml/ProcInstr.scala
index e253baaaa4..8b9669ab61 100644
--- a/sources/scala/xml/ProcInstr.scala
+++ b/sources/scala/xml/ProcInstr.scala
@@ -16,7 +16,7 @@ package scala.xml;
* @param text text contained in this node, may not contain "?>"
**/
-case class ProcInstr( target:String, text:Option[String] ) extends SpecialNode {
+case class ProcInstr(target:String, text:String) extends SpecialNode {
final override def typeTag$:Int = -2;
@@ -27,11 +27,8 @@ case class ProcInstr( target:String, text:Option[String] ) extends SpecialNode {
}
if( !Parsing.isName( target ) )
throw new IllegalArgumentException(target+" must be an XML Name");
- else text match {
- case Some(txt) => if( txt.indexOf("?>" ) != -1 )
- throw new IllegalArgumentException(txt+" may not contain \"?>\"");
- case _ =>
- }
+ else if( text.indexOf("?>" ) != -1 )
+ throw new IllegalArgumentException(text+" may not contain \"?>\"");
final override def equals(x:Any) = x match {
case x @ ProcInstr( t2, s2 ) => target.equals( t2 ) && text.equals( s2 );
@@ -48,11 +45,9 @@ case class ProcInstr( target:String, text:Option[String] ) extends SpecialNode {
final override def toString() = {
val sb = new StringBuffer("<?");
sb.append(target);
- text match {
- case Some(txt) =>
+ if( text.length() > 0 ) {
sb.append(' ');
- sb.append(txt);
- case _ =>
+ sb.append(text);
};
sb.append("?>");
sb.toString()
diff --git a/sources/scala/xml/parsing/ConstructingHandler.scala b/sources/scala/xml/parsing/ConstructingHandler.scala
new file mode 100644
index 0000000000..33b9480241
--- /dev/null
+++ b/sources/scala/xml/parsing/ConstructingHandler.scala
@@ -0,0 +1,53 @@
+package scala.xml.parsing;
+
+import scala.collection.immutable.Map ;
+import scala.collection.mutable ;
+
+/** @todo: make ConstructingMarkupHandler */
+abstract class ConstructingHandler extends MarkupHandler[Node,String] {
+
+ //def attributeCDataValue(pos: int, str:String): AttribValue[String];
+ //def attributeEmbedded(pos: int, x:MarkupType): AttribValue[String];
+
+ def element(pos: int, label: String, attrMap1: mutable.Map[String,AttribValue[String]], args: mutable.Buffer[Node]) = {
+
+ var attrs = new Array[Attribute](attrMap1.size);
+ {
+ var i = 0;
+ val it = attrMap1.elements;
+ while( it.hasNext ) {
+ val Pair(ke:String, va: AttribValue[String]) = it.next;
+ attrs( i ) = Attribute("",ke,va.value);
+ i = i + 1;
+ }
+ }
+ val attrSeq: Seq[Attribute] = attrs;
+ val nodes = new Array[Node]( args.length );
+ {
+ var i = 0;
+ val it = args.elements;
+ while( i < args.length ) {
+ nodes(i) = it.next;
+ i = i + 1;
+ }
+ }
+ val ch: Seq[Node] = nodes;
+ Elem("", label, AttributeSeq.fromAttrs(attrSeq:_*), ch:_*);
+ };
+
+ def charData(pos: Int, txt: String ) =
+ CharData( txt );
+
+ def procInstr(pos: Int, target: String, txt: String ) =
+ ProcInstr(target, txt);
+
+ def comment(pos: Int, txt: String ) =
+ Comment( txt );
+
+ def entityRef(pos: Int, n: String) =
+ EntityRef( n );
+
+ def text(pos: Int, txt:String) =
+ Text( txt );
+
+}
diff --git a/sources/scala/xml/parsing/MarkupHandler.scala b/sources/scala/xml/parsing/MarkupHandler.scala
index 862a8defb2..aacc05ac93 100644
--- a/sources/scala/xml/parsing/MarkupHandler.scala
+++ b/sources/scala/xml/parsing/MarkupHandler.scala
@@ -10,9 +10,9 @@ abstract class MarkupHandler[MarkupType, AVType] {
def attributeEmbedded(pos: int, x:MarkupType): AttribValue[AVType];
def element(pos: int, label: String, attrMap1: mutable.Map[String,AttribValue[AVType]], args: mutable.Buffer[MarkupType]): MarkupType;
- def charData(pos: Int, charData: scala.xml.CharData ): MarkupType;
- def procInstr(pos: Int, procInstr: scala.xml.ProcInstr ): MarkupType;
- def comment(pos: Int, comment: scala.xml.Comment ): MarkupType;
+ def charData(pos: Int, txt: String ): MarkupType;
+ def procInstr(pos: Int, target: String, txt: String): MarkupType;
+ def comment(pos: Int, comment: String ): MarkupType;
def entityRef(pos: Int, n: String): MarkupType;
def text(pos: Int, txt:String): MarkupType;
diff --git a/sources/scala/xml/parsing/MarkupParser.scala b/sources/scala/xml/parsing/MarkupParser.scala
index 4ba86778a1..c094174b4b 100644
--- a/sources/scala/xml/parsing/MarkupParser.scala
+++ b/sources/scala/xml/parsing/MarkupParser.scala
@@ -5,22 +5,28 @@ import scala.collection.immutable.ListMap;
abstract class MarkupParser[MarkupType, AVType] {
+
+ /** the handler of the markup */
val handle: MarkupHandler[MarkupType, AVType];
- /** character buffer, for names */
- protected val cbuf = new StringBuffer();
+ /** if true, does not remove surplus whitespace */
+ val preserveWS: Boolean;
- /** append Unicode character to name buffer*/
- protected def putChar(c: char) = cbuf.append( c );
+ /** holds the position in the source file */
+ var pos: Int = _;
+
+ /** holds temporary values of pos */
+ var tmppos: Int = _;
/** holds the next character */
var ch: Char = _;
- /** holds the position in the source file */
- var pos: Int = _;
+ /** character buffer, for names */
+ protected val cbuf = new StringBuffer();
+
+ /** append Unicode character to name buffer*/
+ protected def putChar(c: char) = cbuf.append( c );
- /** whether to remove surplus whitespace or not */
- val preserveWS: Boolean;
var xEmbeddedBlock = false;
@@ -30,8 +36,10 @@ abstract class MarkupParser[MarkupType, AVType] {
/** this method should assign the first character of the input to ch */
def init: Unit;
+ val enableEmbeddedExpressions: Boolean;
+
/** report a syntax error */
- def xSyntaxError(str:String): Unit;
+ def reportSyntaxError(str:String): Unit;
/** munch expected XML token, report syntax error for unexpected
*/
@@ -39,14 +47,15 @@ abstract class MarkupParser[MarkupType, AVType] {
if( ch == that )
nextch;
else
- xSyntaxError("'" + that + "' expected instead of '" + ch + "'");
+ reportSyntaxError("'" + that + "' expected instead of '" + ch + "'");
}
/** checks whether next character starts a Scala block, if yes, skip it.
* @return true if next character starts a scala block
*/
def xCheckEmbeddedBlock:Boolean = {
- xEmbeddedBlock = ( ch == '{' ) && { nextch;( ch != '{' ) };
+ xEmbeddedBlock =
+ enableEmbeddedExpressions && ( ch == '{' ) && { nextch;( ch != '{' ) };
return xEmbeddedBlock;
}
@@ -69,16 +78,16 @@ abstract class MarkupParser[MarkupType, AVType] {
val tmp = xAttributeValue( delim );
nextch;
handle.attributeCDataValue( pos1, tmp );
- case '{' =>
+ case '{' if enableEmbeddedExpressions =>
nextch;
handle.attributeEmbedded(pos1, xEmbeddedExpr);
case _ =>
- xSyntaxError( "' or \" delimited attribute value or '{' scala-expr '}' expected" );
+ reportSyntaxError( "' or \" delimited attribute value or '{' scala-expr '}' expected" );
handle.attributeCDataValue( pos1, "<syntax-error>" )
};
// well-formedness constraint: unique attribute names
if( aMap.contains( key ))
- xSyntaxError( "attribute "+key+" may only be defined once" );
+ reportSyntaxError( "attribute "+key+" may only be defined once" );
aMap.update( key, value );
if(( ch != '/' )&&( ch != '>' ))
xSpace;
@@ -99,7 +108,7 @@ abstract class MarkupParser[MarkupType, AVType] {
// @todo: normalize attribute value
// well-formedness constraint
if( str.indexOf('<') != -1 ) {
- xSyntaxError( "'<' not allowed in attrib value" ); ""
+ reportSyntaxError( "'<' not allowed in attrib value" ); ""
} else {
str
}
@@ -124,7 +133,7 @@ abstract class MarkupParser[MarkupType, AVType] {
def xEndTag(n: String) = {
xToken('/');
val m = xName;
- if(n != m) xSyntaxError( "expected closing tag of " + n/* +", not "+m*/);
+ if(n != m) reportSyntaxError( "expected closing tag of " + n/* +", not "+m*/);
xSpaceOpt;
xToken('>')
}
@@ -133,7 +142,7 @@ abstract class MarkupParser[MarkupType, AVType] {
*
* see [15]
*/
- def xCharData:scala.xml.CharData = {
+ def xCharData: MarkupType = {
xToken('[');
xToken('C');
xToken('D');
@@ -141,6 +150,7 @@ abstract class MarkupParser[MarkupType, AVType] {
xToken('T');
xToken('A');
xToken('[');
+ val pos1 = pos;
val sb:StringBuffer = new StringBuffer();
while (true) {
if( ch==']' &&
@@ -148,11 +158,11 @@ abstract class MarkupParser[MarkupType, AVType] {
{ sb.append( ch ); nextch; ch == '>' } ) {
sb.setLength( sb.length() - 2 );
nextch;
- return scala.xml.CharData( sb.toString() );
+ return handle.charData( pos1, sb.toString() );
} else sb.append( ch );
nextch;
}
- return null; // this cannot happen;
+ throw FatalError("this cannot happen");
};
/** CharRef ::= "&#" '0'..'9' {'0'..'9'} ";"
@@ -171,12 +181,12 @@ abstract class MarkupParser[MarkupType, AVType] {
case 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
| 'A' | 'B' | 'C' | 'D' | 'E' | 'F' =>
if( !hex )
- xSyntaxError("hex char not allowed in decimal char ref\n"
+ reportSyntaxError("hex char not allowed in decimal char ref\n"
+"Did you mean to write &#x ?");
else
i = i * base + Character.digit( ch, base );
case _ =>
- xSyntaxError("character '"+ch+" not allowed in char ref\n");
+ reportSyntaxError("character '"+ch+" not allowed in char ref\n");
}
nextch;
}
@@ -188,7 +198,7 @@ abstract class MarkupParser[MarkupType, AVType] {
*
* see [15]
*/
- def xComment:scala.xml.Comment = {
+ def xComment: MarkupType = {
val sb:StringBuffer = new StringBuffer();
xToken('-');
xToken('-');
@@ -197,11 +207,11 @@ abstract class MarkupParser[MarkupType, AVType] {
sb.setLength( sb.length() - 1 );
nextch;
xToken('>');
- return scala.xml.Comment( sb.toString() );
+ return handle.comment( pos, sb.toString() );
} else sb.append( ch );
nextch;
}
- return null; // this cannot happen;
+ throw FatalError("this cannot happen");
};
def appendText(pos: int, ts:mutable.Buffer[MarkupType], txt:String):Unit = {
@@ -221,21 +231,22 @@ abstract class MarkupParser[MarkupType, AVType] {
if( xEmbeddedBlock ) {
ts.append( xEmbeddedExpr );
} else {
- val pos2 = pos;
+ tmppos = pos;
ch match {
case '<' => // another tag
nextch;
ch match {
- case '/' => exit = true; // end tag
+ case '/' =>
+ exit = true; // end tag
case '!' =>
nextch;
if( '[' == ch ) // CDATA
- ts.append(handle.charData( pos2, xCharData ));
- else // comment
- ts.append(handle.comment( pos2, xComment ));
- case '?' => // PI
+ ts.append( xCharData );
+ else // comment
+ ts.append( xComment );
+ case '?' => // PI
nextch;
- ts.append(handle.procInstr( pos2, xProcInstr ));
+ ts.append( xProcInstr );
case _ =>
ts.append( element ); // child
}
@@ -246,8 +257,7 @@ abstract class MarkupParser[MarkupType, AVType] {
} else {
val str = new StringBuffer("{");
str.append( xText );
- appendText(pos2, ts, str.toString());
- //@todo
+ appendText(tmppos, ts, str.toString());
}
// postcond: xEmbeddedBlock == false!
case '&' => // EntityRef or CharRef
@@ -255,16 +265,16 @@ abstract class MarkupParser[MarkupType, AVType] {
ch match {
case '#' => // CharacterRef
nextch;
- val theChar = handle.text( pos2, xCharRef );
+ val theChar = handle.text( tmppos, xCharRef );
xToken(';');
ts.append( theChar );
case _ => // EntityRef
val n = xName ;
xToken(';');
- ts.append( handle.entityRef( pos2, n ) );
+ ts.append( handle.entityRef( tmppos, n ) );
}
case _ => // text content
- appendText(pos2, ts, xText);
+ appendText(tmppos, ts, xText);
// here xEmbeddedBlock might be true
}
}
@@ -306,7 +316,7 @@ abstract class MarkupParser[MarkupType, AVType] {
cbuf.setLength( 0 );
n
} else {
- xSyntaxError( "name expected" );
+ reportSyntaxError( "name expected" );
new String();
}
}
@@ -323,7 +333,7 @@ abstract class MarkupParser[MarkupType, AVType] {
if( xml.Parsing.isSpace( ch ) ) {
nextch; xSpaceOpt
} else {
- xSyntaxError("whitespace expected");
+ reportSyntaxError("whitespace expected");
}
}
@@ -331,7 +341,7 @@ abstract class MarkupParser[MarkupType, AVType] {
*
* see [15]
*/
- def xProcInstr:scala.xml.ProcInstr = {
+ def xProcInstr: MarkupType = {
val sb:StringBuffer = new StringBuffer();
val n = xName;
if( xml.Parsing.isSpace( ch ) ) {
@@ -340,7 +350,7 @@ abstract class MarkupParser[MarkupType, AVType] {
if( ch=='?' && { sb.append( ch ); nextch; ch == '>' } ) {
sb.setLength( sb.length() - 1 );
nextch;
- return scala.xml.ProcInstr( n.toString(), Some(sb.toString()) );
+ return handle.procInstr(tmppos, n.toString(), sb.toString());
} else
sb.append( ch );
nextch;
@@ -348,13 +358,13 @@ abstract class MarkupParser[MarkupType, AVType] {
};
xToken('?');
xToken('>');
- scala.xml.ProcInstr( n.toString(), None );
+ return handle.procInstr(tmppos, n.toString(), sb.toString());
}
/** parse character data.
* precondition: xEmbeddedBlock == false (we are not in a scala block)
*/
- def xText:String = {
+ def xText: String = {
if( xEmbeddedBlock ) throw FatalError("internal error: encountered embedded block"); // assert
if( xCheckEmbeddedBlock )
diff --git a/test/files/jvm/xmlLiterals.scala b/test/files/jvm/xmlLiterals.scala
index d68a61ab62..6df8082c0c 100644
--- a/test/files/jvm/xmlLiterals.scala
+++ b/test/files/jvm/xmlLiterals.scala
@@ -144,9 +144,9 @@ object Test {
val rows3 = <tr> a <!-- an XML comment --> b <?pinotext?> c <?pi text?> d </tr>;
// these are not equal as comments are valid XML Info items.
- assertEquals( rows2, Elem("","tr",e,Comment(" an XML comment "),ProcInstr("pinotext",None),ProcInstr("pi",Some("text"))));
+ assertEquals( rows2, Elem("","tr",e,Comment(" an XML comment "),ProcInstr("pinotext",""),ProcInstr("pi","text")));
- assertEquals( rows3, Elem("","tr",e,Text("a"),Comment(" an XML comment "),Text("b"),ProcInstr("pinotext",None),Text("c"),ProcInstr("pi",Some("text")),Text("d")));
+ assertEquals( rows3, Elem("","tr",e,Text("a"),Comment(" an XML comment "),Text("b"),ProcInstr("pinotext",""),Text("c"),ProcInstr("pi","text"),Text("d")));
}