summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorburaq <buraq@epfl.ch>2004-07-19 17:01:35 +0000
committerburaq <buraq@epfl.ch>2004-07-19 17:01:35 +0000
commit9ed892ea8fb7c169e4bf41ffe38b612eb6b3f8a0 (patch)
treeac94db2e21f6c6b177cd7990db145498351c7a50 /sources
parent9393649522ccfb35fdf2307aea89f6784ed99741 (diff)
downloadscala-9ed892ea8fb7c169e4bf41ffe38b612eb6b3f8a0.tar.gz
scala-9ed892ea8fb7c169e4bf41ffe38b612eb6b3f8a0.tar.bz2
scala-9ed892ea8fb7c169e4bf41ffe38b612eb6b3f8a0.zip
xml parsing into lib
Diffstat (limited to 'sources')
-rw-r--r--sources/scala/tools/scalac/ast/parser/MarkupParser.scala28
-rw-r--r--sources/scala/tools/scalac/ast/parser/SymbolicXMLBuilder.scala23
-rw-r--r--sources/scala/xml/TextBuffer.scala13
-rw-r--r--sources/scala/xml/parsing/AttribValue.scala4
-rw-r--r--sources/scala/xml/parsing/MarkupHandler.scala12
-rw-r--r--sources/scala/xml/parsing/MarkupParser.scala177
6 files changed, 160 insertions, 97 deletions
diff --git a/sources/scala/tools/scalac/ast/parser/MarkupParser.scala b/sources/scala/tools/scalac/ast/parser/MarkupParser.scala
index f8d8ca938d..e980bfb5b6 100644
--- a/sources/scala/tools/scalac/ast/parser/MarkupParser.scala
+++ b/sources/scala/tools/scalac/ast/parser/MarkupParser.scala
@@ -37,7 +37,6 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
/** the XML tree builder */
val gen = unit.global.treeGen ;
- var mode:boolean = false;
final val PATTERN = true;
final val EXPR = false;
@@ -46,20 +45,20 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
/** append Unicode character to name buffer*/
//private def putChar(c: char) = cbuf.append( c );
- /** xLiteral = xExpr { xExpr }
+ /** xLiteral = element { element }
* @return Scala representation of this xml literal
* precondition: s.xStartsXML == true
*/
def xLiteral: Tree = {
init;
- mode = EXPR;
+ handle.isPattern = false;
val pos = s.pos;
- var tree = xExpr; xSpaceOpt;
+ var tree = element; xSpaceOpt;
if( ch=='<' ) {
val ts = new mutable.ArrayBuffer[Tree](); ts.append( tree );
while( ch == '<' ) {
nextch;
- ts.append( xExpr );
+ ts.append( element );
xSpaceOpt;
}
tree = handle.makeXMLseq( pos, ts );
@@ -75,8 +74,8 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
*/
def xLiteralPattern:Tree = {
init;
- val oldMode = mode;
- mode = PATTERN;
+ val oldMode = handle.isPattern;
+ handle.isPattern = true;
val pos = s.pos;
var tree = xPattern; xSpaceOpt;
if( ch == '<' ) {
@@ -88,7 +87,7 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
}
tree = handle.makeXMLseqPat( pos, ts.toArray() );
}
- mode = oldMode;
+ handle.isPattern = oldMode;
//Console.println("out of xLiteralPattern, parsed:"+tree.toString());
s.xSync2;
tree
@@ -132,7 +131,6 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
* AttValue ::= `'` { _ } `'`
* | `"` { _ } `"`
* | `{` scalablock `}`
- */
def xAttributes = {
var aMap = new mutable.HashMap[String, AttribValue[Tree]];
while( xml.Parsing.isNameStart( ch )) {
@@ -162,6 +160,7 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
};
aMap
}
+ */
def xSyntaxError(str:String) = {
@@ -214,7 +213,7 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
// postcond: xEmbeddedBlock = false;
if( xEmbeddedBlock ) throw new ApplicationError(); // assert
case _ => // teMaxt
- appendTrimmed( pos2, mode, ts, xText );
+ appendText( pos2, ts, xText );
// here xEmbeddedBlock might be true;
//if( xEmbeddedBlock ) throw new ApplicationError("after:"+text); // assert
}
@@ -223,5 +222,14 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
handle.makeXMLpat( pos1, qname, ts );
}
+
+ override def appendText(pos: int, ts:mutable.Buffer[Tree], txt:String):Unit = {
+ if( !preserveWS )
+ for( val t <- TextBuffer.fromString( txt ).toText ) {
+ ts.append( handle.text( pos, t.text ) );
+ }
+ else
+ ts.append( handle.text( pos, txt ));
+ }
} /* class MarkupParser */
}
diff --git a/sources/scala/tools/scalac/ast/parser/SymbolicXMLBuilder.scala b/sources/scala/tools/scalac/ast/parser/SymbolicXMLBuilder.scala
index 64e7a9827a..8e9a0fd9b1 100644
--- a/sources/scala/tools/scalac/ast/parser/SymbolicXMLBuilder.scala
+++ b/sources/scala/tools/scalac/ast/parser/SymbolicXMLBuilder.scala
@@ -27,6 +27,19 @@ class SymbolicXMLBuilder(make: TreeFactory, gen: TreeGen, p: Parser, preserveWS:
import scala.tools.scalac.ast.{TreeList => myTreeList}
+ def attributeCDataValue(pos: int, str:String): AttribValue[Tree] = {
+ val v = gen.mkStringLit(pos, str);
+ new AttribValue[Tree] {
+ def value = v;
+ }
+ }
+ def attributeEmbedded(pos: int, v:Tree): AttribValue[Tree] = {
+ new AttribValue[Tree] {
+ def value = v;
+ }
+ }
+ var isPattern:Boolean = _;
+
val _ArrayBuffer = Name.fromString("ArrayBuffer");
val _Attribute = Name.fromString("Attribute");
val _NodeBuffer = Name.fromString("NodeBuffer");
@@ -200,7 +213,7 @@ class SymbolicXMLBuilder(make: TreeFactory, gen: TreeGen, p: Parser, preserveWS:
}
}
- final def EntityRef( pos:int, n: String ) = {
+ final def entityRef( pos:int, n: String ) = {
val constr = make.Apply( pos,
_scala_xml_EntityRef( pos ),
Predef.Array[Tree]( gen.mkStringLit( pos, n )));
@@ -208,7 +221,7 @@ class SymbolicXMLBuilder(make: TreeFactory, gen: TreeGen, p: Parser, preserveWS:
make.New( pos, constr );
};
// create scala.xml.Text here <: scala.xml.Node
- final def Text( pos: int, isPattern:Boolean, txt:String ):Tree = {
+ final def text( pos: int, txt:String ):Tree = {
//makeText( pos, isPattern, gen.mkStringLit( pos, txt ));
val txt1 = gen.mkStringLit( pos, txt );
if( isPattern )
@@ -252,15 +265,15 @@ class SymbolicXMLBuilder(make: TreeFactory, gen: TreeGen, p: Parser, preserveWS:
);
// create
- def Comment( pos: int, comment:scala.xml.Comment ):Tree =
+ def comment( pos: int, comment:scala.xml.Comment ):Tree =
Comment( pos, gen.mkStringLit( pos, comment.text ));
// create
- def CharData( pos: int, charData:scala.xml.CharData ):Tree =
+ def charData( pos: int, charData:scala.xml.CharData ):Tree =
CharData( pos, gen.mkStringLit( pos, charData.text ));
// create scala.xml.Text here <: scala.xml.Node
- def ProcInstr( pos: int, procInstr:scala.xml.ProcInstr ):Tree =
+ def procInstr( pos: int, procInstr:scala.xml.ProcInstr ):Tree =
procInstr.text match {
case Some(txt) =>
ProcInstr( pos,
diff --git a/sources/scala/xml/TextBuffer.scala b/sources/scala/xml/TextBuffer.scala
index 207bba560d..ff528cf3d2 100644
--- a/sources/scala/xml/TextBuffer.scala
+++ b/sources/scala/xml/TextBuffer.scala
@@ -8,9 +8,16 @@
\* */
package scala.xml ;
-/** this classes is for creating text nodes with trimmed whitespace.
- * all occurrences of one or more whitespace in strings appended (using the
- * append method) will be replaced by a single space character
+object TextBuffer {
+ def fromString(str: String): TextBuffer = {
+ new TextBuffer().append( str );
+ }
+}
+
+/** this classes is for creating text nodes without surplus whitespace.
+ * all occurrences of one or more whitespace in strings appended with the
+ * append method will be replaced by a single space character, and
+ * leading and trailing space will be removed completely.
*/
class TextBuffer {
diff --git a/sources/scala/xml/parsing/AttribValue.scala b/sources/scala/xml/parsing/AttribValue.scala
index febf83900c..fbb17241e6 100644
--- a/sources/scala/xml/parsing/AttribValue.scala
+++ b/sources/scala/xml/parsing/AttribValue.scala
@@ -1,4 +1,6 @@
package scala.xml.parsing ;
/** a container for attribute values */
-case class AttribValue[A](value: A);
+trait AttribValue[A] {
+ def value: A;
+};
diff --git a/sources/scala/xml/parsing/MarkupHandler.scala b/sources/scala/xml/parsing/MarkupHandler.scala
index 3fe83502b4..862a8defb2 100644
--- a/sources/scala/xml/parsing/MarkupHandler.scala
+++ b/sources/scala/xml/parsing/MarkupHandler.scala
@@ -6,13 +6,15 @@ import scala.collection.mutable ;
/** @todo: make ConstructingMarkupHandler */
abstract class MarkupHandler[MarkupType, AVType] {
+ def attributeCDataValue(pos: int, str:String): AttribValue[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 EntityRef(pos: Int, n: String): 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 entityRef(pos: Int, n: String): MarkupType;
- def Text(pos: Int, mode: Boolean, txt: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 ffde84f5ce..4ba86778a1 100644
--- a/sources/scala/xml/parsing/MarkupParser.scala
+++ b/sources/scala/xml/parsing/MarkupParser.scala
@@ -7,9 +7,6 @@ abstract class MarkupParser[MarkupType, AVType] {
val handle: MarkupHandler[MarkupType, AVType];
- // @todo: kill this field
- var mode: Boolean;
-
/** character buffer, for names */
protected val cbuf = new StringBuffer();
@@ -53,8 +50,41 @@ abstract class MarkupParser[MarkupType, AVType] {
return xEmbeddedBlock;
}
-
- def xAttributes: scala.collection.mutable.Map[String,AttribValue[AVType]];
+ /** parse attribute and add it to listmap
+ * [41] Attributes ::= { S Name Eq AttValue }
+ * AttValue ::= `'` { _ } `'`
+ * | `"` { _ } `"`
+ * | `{` scalablock `}`
+ */
+ def xAttributes = {
+ var aMap = new mutable.HashMap[String, AttribValue[AVType]];
+ while( xml.Parsing.isNameStart( ch )) {
+ val key = xName;
+ xEQ;
+ val delim = ch;
+ val pos1 = pos;
+ val value:AttribValue[AVType] = ch match {
+ case '"' | '\'' =>
+ nextch;
+ val tmp = xAttributeValue( delim );
+ nextch;
+ handle.attributeCDataValue( pos1, tmp );
+ case '{' =>
+ nextch;
+ handle.attributeEmbedded(pos1, xEmbeddedExpr);
+ case _ =>
+ xSyntaxError( "' 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" );
+ aMap.update( key, value );
+ if(( ch != '/' )&&( ch != '>' ))
+ xSpace;
+ };
+ aMap
+ }
/** attribute value, terminated by either ' or ". value may not contain <.
* @param endch either ' or "
@@ -174,22 +204,78 @@ abstract class MarkupParser[MarkupType, AVType] {
return null; // this cannot happen;
};
- def appendTrimmed(pos: int, mode:Boolean, ts:mutable.Buffer[MarkupType], txt:String):Unit = {
- var textNodes =
- if( !preserveWS )
- new TextBuffer().append( txt ).toText;
- else
- List( scala.xml.Text( txt ));
-
- for( val t <- textNodes ) {
- ts.append( handle.Text( pos, mode, t.text ) );
- };
+ def appendText(pos: int, ts:mutable.Buffer[MarkupType], txt:String):Unit = {
+ if( !preserveWS )
+ for( val t <- TextBuffer.fromString( txt ).toText ) {
+ ts.append( handle.text( pos, t.text ) );
+ }
+ else
+ ts.append( handle.text( pos, txt ));
}
- /** '<' xExpr ::= xmlTag1 '>' { xmlExpr | '{' simpleExpr '}' } ETag
+
+ def content: mutable.Buffer[MarkupType] = {
+ var ts = new mutable.ArrayBuffer[MarkupType];
+ var exit = false;
+ while( !exit ) {
+ if( xEmbeddedBlock ) {
+ ts.append( xEmbeddedExpr );
+ } else {
+ val pos2 = pos;
+ ch match {
+ case '<' => // another tag
+ nextch;
+ ch match {
+ 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
+ nextch;
+ ts.append(handle.procInstr( pos2, xProcInstr ));
+ case _ =>
+ ts.append( element ); // child
+ }
+
+ case '{' =>
+ if( xCheckEmbeddedBlock ) {
+ ts.append(xEmbeddedExpr);
+ } else {
+ val str = new StringBuffer("{");
+ str.append( xText );
+ appendText(pos2, ts, str.toString());
+ //@todo
+ }
+ // postcond: xEmbeddedBlock == false!
+ case '&' => // EntityRef or CharRef
+ nextch;
+ ch match {
+ case '#' => // CharacterRef
+ nextch;
+ val theChar = handle.text( pos2, xCharRef );
+ xToken(';');
+ ts.append( theChar );
+ case _ => // EntityRef
+ val n = xName ;
+ xToken(';');
+ ts.append( handle.entityRef( pos2, n ) );
+ }
+ case _ => // text content
+ appendText(pos2, ts, xText);
+ // here xEmbeddedBlock might be true
+ }
+ }
+ }
+ ts
+ } /* end content */
+
+ /** '<' element ::= xmlTag1 '>' { xmlExpr | '{' simpleExpr '}' } ETag
* | xmlTag1 '/' '>'
*/
- def xExpr: MarkupType = {
+ def element: MarkupType = {
var pos1 = pos;
val Tuple2(qname, attrMap) = xTag;
if(ch == '/') { // empty element
@@ -198,62 +284,7 @@ abstract class MarkupParser[MarkupType, AVType] {
handle.element( pos1, qname, attrMap, new mutable.ListBuffer[MarkupType] );
} else { // handle content
xToken('>');
- var ts = new mutable.ArrayBuffer[MarkupType];
- var exit = false;
- while( !exit ) {
- if( xEmbeddedBlock ) {
- ts.append( xEmbeddedExpr );
- } else {
- val pos2 = pos;
- ch match {
- case '<' => // another tag
- nextch;
- ch match {
- 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
- nextch;
- ts.append(handle.ProcInstr( pos2, xProcInstr ));
- case _ =>
- ts.append( xExpr ); // child
- }
-
- case '{' =>
- if( xCheckEmbeddedBlock ) {
- ts.append(xEmbeddedExpr);
- } else {
- val str = new StringBuffer("{");
- str.append( xText );
- appendTrimmed( pos2, mode, ts, str.toString() );
- //@todo
- }
- // postcond: xEmbeddedBlock == false!
- case '&' => // EntityRef or CharRef
- nextch;
- ch match {
- case '#' => // CharacterRef
- nextch;
- val theChar = handle.Text( pos2, false, xCharRef );
- xToken(';');
- ts.append( theChar );
- case _ => // EntityRef
- val n = xName ;
- xToken(';');
- ts.append( handle.EntityRef( pos2, n ) );
- }
- case _ => // text content
- appendTrimmed( pos2, mode, ts, xText );
- //@todo
- // here xEmbeddedBlock might be true
-
- }
- }
- }
+ val ts = content;
xEndTag( qname );
handle.element( pos1, qname, attrMap, ts );
}