summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorburaq <buraq@epfl.ch>2004-03-05 13:53:03 +0000
committerburaq <buraq@epfl.ch>2004-03-05 13:53:03 +0000
commitc1c3bc8b5ad5b5ae693bce5def6abec706c90bc9 (patch)
tree59493953ea17f00717d6f37c9b30c21daf03a309
parent2d8126de26bad4d886012a1c666391948d8a6e71 (diff)
downloadscala-c1c3bc8b5ad5b5ae693bce5def6abec706c90bc9.tar.gz
scala-c1c3bc8b5ad5b5ae693bce5def6abec706c90bc9.tar.bz2
scala-c1c3bc8b5ad5b5ae693bce5def6abec706c90bc9.zip
markup parsing
-rw-r--r--sources/scala/tools/scalac/ast/parser/MarkupParser.scala235
-rw-r--r--sources/scala/tools/scalac/ast/parser/Parser.scala245
-rw-r--r--sources/scala/tools/scalac/ast/parser/Scanner.scala163
3 files changed, 340 insertions, 303 deletions
diff --git a/sources/scala/tools/scalac/ast/parser/MarkupParser.scala b/sources/scala/tools/scalac/ast/parser/MarkupParser.scala
new file mode 100644
index 0000000000..88afa0c5b5
--- /dev/null
+++ b/sources/scala/tools/scalac/ast/parser/MarkupParser.scala
@@ -0,0 +1,235 @@
+
+import scalac.ast._;
+import scalac.atree.AConstant;
+import scalac._;
+import scalac.util._;
+import ch.epfl.lamp.util.Position;
+import java.util.{Map, Stack, ArrayList, LinkedList};
+import java.lang.{Integer, Long, Float, Double};
+import scala.Iterator;
+import scala.tools.scalac.util.NewArray;
+import scala.collection.immutable.ListMap ;
+import scala.collection.mutable.Buffer;
+
+package scala.tools.scalac.ast.parser {
+
+class MarkupParser( unit:Unit, s:Scanner, p:Parser ) {
+
+ import Tokens.{EMPTY, RBRACE} ;
+ import scala.tools.scalac.ast.{TreeList => myTreeList}
+
+ /** the tree factory
+ */
+ val make: TreeFactory = unit.global.make;
+
+ /** the tree generator
+ */
+ val gen: TreeGen = unit.global.treeGen;
+
+ /** convenience method */
+ def scalaDot(pos: int, name: Name): Tree =
+ make.Select(pos, make.Ident(pos, Names.scala), name);
+
+ /** convenience method */
+ def convertToTypeId(t: Tree): Tree = t match {
+ case Tree$Ident(name) =>
+ make.Ident(t.pos, name.toTypeName())
+ case Tree$Select(qual, name) =>
+ make.Select(t.pos, qual, name.toTypeName())
+ case _ =>
+ t
+ }
+
+ // create scala xml tree
+
+ def mkXML(pos:int, isPattern:boolean, t:Tree, args:Array[Tree]):Tree = {
+ var symt = scalaDot(s.pos, Names.Symbol);
+ if( isPattern ) symt = convertToTypeId(symt);
+ val ts = new myTreeList();
+ ts.append(t);
+ ts.append(args);
+ make.Apply(pos, symt, ts.toArray());
+ }
+
+ def makeXMLpat(pos:int, n:Name, args:Array[Tree]):Tree =
+ mkXML(pos, true, gen.mkStringLit( pos, n.toString() ), args);
+
+ def makeXML(pos:int, n:Name, args:Array[Tree]):Tree =
+ mkXML(pos, false, gen.mkStringLit( pos, n.toString() ), args);
+
+ def makeXMLseq( pos:int, args:Array[Tree] ) = {
+ make.Apply(pos, scalaDot(s.pos, Names.List), args);
+ }
+
+ def makeXML(pos:int,n:Name,args:Array[Tree],attrMap:ListMap[Name,String]):Tree = {
+ var t = makeXML( pos, n, args );
+ if( attrMap.isEmpty ) {
+ t
+ } else {
+ val attrs = new Array[Tree]( attrMap.size );
+ val it = attrMap.elements ;
+ var i = 0; while( i < attrs.length ) {
+ val Pair( key, value ) = it.next;
+ attrs( i ) = make.Apply(pos, scalaDot(s.pos, Names.Tuple2), {
+ val x = new Array[Tree](2);
+ x( 0 ) = gen.mkStringLit( pos, key.toString() );
+ x( 1 ) = gen.mkStringLit( pos, value.toString() );
+ x });
+ i = i + 1;
+ };
+ make.Apply(pos, make.Select( pos, t, Names.PERCENT ), {
+ val x = new Array[Tree](1);
+ x( 0 ) = make.Apply(pos,
+ scalaDot(s.pos, Names.List),
+ attrs);
+ x })
+ }
+ }
+
+ /** xLiteral = xExpr { xExpr }
+ * @return Scala representation of this xml literal
+ * precondition: s.xStartsXML == true
+ */
+ def xLiteral:Tree = {
+ val pos = s.pos;
+ var tree = xExpr; s.token = EMPTY; s.nextToken();
+ if( s.xStartsXML ) {
+ val ts = new myTreeList(); ts.append( tree );
+ while( s.xStartsXML ) { ts.append( xExpr ); s.nextToken(); }
+ tree = makeXMLseq( pos, ts.toArray() );
+ }
+ tree
+ }
+
+ /** parse a start or empty tag.
+ * [40] STag ::= '<' Name { S Attribute } [S]
+ * [41] Attribute ::= Name Eq AttValue
+ * [44] EmptyElemTag ::= '<' Name { S Attribute } [S]
+ */
+ def xTag:Tuple2[Name, ListMap[Name,String]] = {
+ val elemName = s.xName;
+ s.xSpaceOpt;
+ var attrMap = ListMap.Empty[Name,String];
+ while( s.xIsNameStart ) {
+ val attrName = s.xName;
+ s.xEQ;
+ val endch = s.ch.asInstanceOf[char];
+ val attrValue = endch match {
+ case '"' | '\'' =>
+ s.xNext; val tmp = s.xAttributeValue( endch );
+ s.xNext; s.xSpaceOpt; tmp
+ case _ =>
+ s.xSyntaxError( "' or \" delimited attribute value expected" );
+ ""
+ }
+ // well-formedness constraint: unique attribute names
+ if( attrMap.contains( attrName ))
+ s.xSyntaxError( "attribute "+attrName+" may only be defined once" );
+
+ attrMap = attrMap.update( attrName, attrValue );
+ }
+ Tuple2( elemName, attrMap );
+ }
+
+ /* [42] '<' xmlEndTag ::= '<' '/' Name S? '>' */
+ def xEndTag( n:Name ) = {
+ s.xToken('/');
+ if( n != s.xName ) s.xSyntaxError( "expected closing tag of " + n );
+ s.xSpaceOpt;
+ s.xToken('>')
+ }
+
+ /** '<' xExpr ::= xmlTag1 '>' { xmlExpr | '{' simpleExpr '}' } ETag
+ * | xmlTag1 '/' '>'
+ * the caller has to resynchronize with s.token = EMPTY; s.nextToken;
+ */
+ def xExpr:Tree = {
+ val pos = s.pos;
+ val Tuple2( elemName, attrMap ) = xTag;
+ if( s.ch == '/' ) { // empty element
+ s.xToken('/'); s.xToken('>'); makeXML( pos, elemName, Tree.EMPTY_ARRAY );
+ } else { // handle content
+ s.xToken('>'); s.xSpaceOpt;
+
+ val ts = new myTreeList();
+ var exit = false;
+ while( !exit ) {
+ /* Console.println("read '"+s.ch.asInstanceOf[char]+"'"); */
+ s.ch match {
+ case '<' => // another tag
+ s.xNext; s.ch match {
+ case '/' => exit = true; // end tag
+ case '!' => s.xComment;
+ case _ => ts.append( xExpr ); // parse child
+ }
+ case '{' => // Scala block(s)
+ while( s.ch == '{' ) {
+ s.nextToken();
+ s.nextToken();
+ val bs = new myTreeList();
+ val b = p.expr(true,false); //block( s.pos );
+ if( s.token != RBRACE ) {
+ s.xSyntaxError(" expected end of Scala block");
+ }
+ ts.append( b );
+ }
+ case _ => // text content
+ ts.append( gen.mkStringLit( s.pos, s.xText ));
+ }
+ }
+ xEndTag( elemName );
+ makeXML( pos, elemName, ts.toArray(), attrMap );
+ }
+ }
+
+ /** @see xmlPattern. resynchronizes after succesful parse */
+ def xLiteralPattern = {
+ val t = xPattern; s.nextToken(); t
+ }
+
+ /** '<' xPattern ::= Name [S] { xmlPattern | '{' pattern3 '}' } ETag
+ * | Name [S] '/' '>'
+ */
+ def xPattern:Tree = {
+ val pos = s.pos;
+ val elemName = s.xName;
+ s.xSpaceOpt;
+ if( s.ch == '/' ) { // empty tag
+ s.xNext; s.xToken('>'); makeXMLpat( pos, elemName, Tree.EMPTY_ARRAY );
+ } else { // content
+ s.xToken('>');
+ val ts = new myTreeList();
+ var exit = false;
+ while( !exit ) {
+ //Console.print("["+s.ch.asInstanceOf[char]+"]");
+ s.ch match {
+ case '<' => { // tag
+ s.xNext;
+ if( s.ch != '/' ) { //child
+ ts.append( xPattern );
+ } else {
+ exit = true
+ }
+ }
+ case '{' => // embedded Scala patterns
+ while( s.ch == '{' ) {
+ s.nextToken();
+ s.nextToken();
+ val ps = p.patterns();
+ if( s.token != RBRACE ) {
+ s.xSyntaxError(" expected end of Scala block");
+ }
+ ts.append( ps );
+ }
+ case _ => // text
+ val pos = s.pos;
+ ts.append( gen.mkStringLit( pos, s.xText ) );
+ }
+ }
+ xEndTag( elemName );
+ makeXMLpat( pos, elemName, ts.toArray() );
+ }
+ }
+
+} /* class MarkupParser */
+}
diff --git a/sources/scala/tools/scalac/ast/parser/Parser.scala b/sources/scala/tools/scalac/ast/parser/Parser.scala
index 02057a6feb..b4c83e6fcd 100644
--- a/sources/scala/tools/scalac/ast/parser/Parser.scala
+++ b/sources/scala/tools/scalac/ast/parser/Parser.scala
@@ -36,8 +36,12 @@ class Parser(unit: Unit) {
*/
val s = new Scanner(unit);
- /** the tree factory
+ /** the markup parser
*/
+ val xmlp = new MarkupParser( unit, s, this );
+
+ /** the tree factory
+ */
val make: TreeFactory = unit.global.make;
/** the tree generator
@@ -360,50 +364,6 @@ class Parser(unit: Unit) {
make.LabelDef(pos, lname, new Array[Tree$Ident](0), rhs)
}
- def mkXML(pos:int, isPattern:boolean, t:Tree, args:Array[Tree]):Tree = {
- var symt = scalaDot(s.pos, Names.Symbol);
- if( isPattern ) symt = convertToTypeId(symt);
- val ts = new myTreeList();
- ts.append(t);
- ts.append(args);
- make.Apply(pos, symt, ts.toArray());
- }
-
- def makeXMLpat(pos:int, n:Name, args:Array[Tree]):Tree =
- mkXML(pos, true, gen.mkStringLit( pos, n.toString() ), args);
-
- def makeXML(pos:int, n:Name, args:Array[Tree]):Tree =
- mkXML(pos, false, gen.mkStringLit( pos, n.toString() ), args);
-
- def makeXMLseq( pos:int, args:Array[Tree] ) = {
- var symt = scalaDot(s.pos, Names.List);
- make.Apply(pos, symt, args);
- }
-
- def makeXML(pos:int, n:Name, args:Array[Tree], attrMap:ListMap[Name,String]):Tree = {
- val t = makeXML( pos, n, args );
- val attrs = new Array[Tree]( attrMap.size );
- var i = 0;
- for( val Pair( key, value ) <- attrMap.toList ) {
- attrs.update( i, make.Apply(pos,
- scalaDot(s.pos, Names.Tuple2),
- { val x = new Array[Tree](2);
- x(0) = gen.mkStringLit( pos, key.toString() );
- x(1) = gen.mkStringLit( pos, value.toString() );
- x }
- ));
- i = i + 1;
- };
- make.Apply(pos,
- make.Select( pos, t, Names.PERCENT ),
- { val x = new Array[Tree](1);
- x( 0 ) = make.Apply(pos,
- scalaDot(s.pos, Names.List),
- attrs);
- x })
-
- }
-
/** Convert tree to formal parameter list
*/
def convertToParams(t: Tree): Array[Tree$ValDef] = t match {
@@ -650,9 +610,9 @@ class Parser(unit: Unit) {
if (isSymLit) {
val pos = s.pos;
if (s.token == LPAREN || s.token == LBRACE)
- mkXML( pos, isPattern, t, argumentExprs() );
+ xmlp.mkXML( pos, isPattern, t, argumentExprs() );
else
- mkXML( pos, isPattern, t, Tree.EMPTY_ARRAY );
+ xmlp.mkXML( pos, isPattern, t, Tree.EMPTY_ARRAY );
} else {
t
}
@@ -978,7 +938,7 @@ class Parser(unit: Unit) {
}
/* SimpleExpr ::= literal
- * | xmlExpr
+ * | xLiteral
* | StableRef
* | `(' [Expr] `)'
* | BlockExpr
@@ -994,8 +954,8 @@ class Parser(unit: Unit) {
SYMBOLLIT | TRUE | FALSE | NULL =>
t = literal(false);
case IDENTIFIER | THIS | SUPER =>
- t = if(( s.name == LT )&&( unit.global.xmlMarkup )) {
- xmlExprTop(); /* top-level xml expression */
+ t = if( s.xStartsXML ) {
+ xmlp.xLiteral;
} else {
stableRef(true, false);
}
@@ -1049,29 +1009,6 @@ class Parser(unit: Unit) {
null;//dummy
}
- /** top level xml expression, resynchronizes after succesful parse
- * see xmlExpr
- */
- def xmlExprTop():Tree = {
- val pos = s.pos;
- var t = xmlExpr();
- //Console.println("old:"+token2string( s.token ) );
- s.token = EMPTY;
- s.nextToken();
- //Console.println("new:"+token2string( s.token ) );
- //Console.println("line:"+s.cline);
- if(( s.token == IDENTIFIER ) && ( s.name == LT )) {
- val ts = new myTreeList();
- ts.append( t );
- while(( s.token == IDENTIFIER ) && ( s.name == LT )) {
- ts.append( xmlExpr() );
- s.nextToken();
- }
- t = makeXMLseq( pos, ts.toArray() );
- }
- t
- }
-
/** ArgumentExprs ::= `(' [Exprs] `)'
* | BlockExpr
*/
@@ -1318,7 +1255,7 @@ class Parser(unit: Unit) {
/** simplePattern ::= varid
* | `_'
* | literal
- * | `<' xmlPatternTop
+ * | `<' xLiteralPattern
* | StableId [ `(' [Patterns] `)' ]
* | `(' [Patterns] `)'
* | (word: empty - nothing)
@@ -1329,8 +1266,8 @@ class Parser(unit: Unit) {
case IDENTIFIER | THIS =>
if (s.name == BAR) {
make.Sequence(s.pos, Tree.EMPTY_ARRAY); // ((nothing))
- } else if(( s.name == LT )&&( unit.global.xmlMarkup )) {
- xmlPatternTop()
+ } else if( s.xStartsXML ) {
+ xmlp.xLiteralPattern
} else {
var t = stableId();
while (s.token == LPAREN) {
@@ -1364,162 +1301,6 @@ class Parser(unit: Unit) {
syntaxError("illegal start of pattern", true)
}
- def xmlTag():Tuple2[Name, ListMap[Name,String]] = {
- var empty = false;
-
- /* [40] STag ::= '<' Name (S Attribute)* S?
- * [41] Attribute ::= Name Eq AttValue
- * [44] EmptyElemTag ::= '<' Name (S Attribute)* S?
- */
- val elemName = s.xmlName();
- s.xmlSpaceOpt();
- var attrMap = ListMap.Empty[Name,String];
- while( s.xml_isNameStart() ) {
- val attrName:Name = s.xmlName();
- s.xmlSpaceOpt();
- s.xmlToken('=');
- s.xmlSpaceOpt();
- var attrValue:String = "";
- val endch:char = s.ch.asInstanceOf[char];
- endch match {
- case '"' | '\'' => {
- s.nextch();
- attrValue = s.xmlAttribValue( endch );
- s.xmlToken( endch.asInstanceOf[char] );
- s.xmlSpaceOpt();
- }
- case _ => s.xml_syntaxError("' or \" delimited value expected here");
- }
- if( attrMap.contains( attrName )) {
- s.xml_syntaxError("attribute "+attrName+" may only be defined once");
- }
- attrMap = attrMap.update( attrName, attrValue );
- }
- Tuple2( elemName, attrMap );
- }
-
- /* [42] '<' xmlEndTag ::= '<' '/' Name S? '>' */
- def xmlEndTag(n:Name) = {
- s.xmlToken('/');
- if( n != s.xmlName() ) s.xml_syntaxError("expected closing tag of "+n);
- s.xmlSpaceOpt();
- s.xmlToken('>')
- }
-
- /** '<' xmlExpr ::= xmlTag1 '>' { xmlExpr | '{' simpleExpr '}' } ETag
- ** | xmlTag1 '\' '>'
- */
- def xmlExpr():Tree = {
- val pos = s.pos;
- val Tuple2(elemName, attrMap) = xmlTag();
- if( s.ch == '/' ) {
- s.xmlToken('/');
- s.xmlToken('>');
- makeXML( pos, elemName, Tree.EMPTY_ARRAY );
- } else {
- s.xmlToken('>'); /* handle XML content: */
- s.xmlSpaceOpt();
- val ts = new myTreeList();
- var exit = false;
- while( !exit ) {
- /* Console.println("read '"+s.ch.asInstanceOf[char]+"'"); */
- s.ch match {
- case '<' => { /* tag */
- s.nextch();
- s.ch match {
- case '/' => exit = true;
- case '!' =>
- s.xmlComment();
- case _ =>
- /* search end tag */
- ts.append( xmlExpr() );
- s.xmlSpaceOpt();
- }
- }
-
- case '{' => { /* Scala block */
- while( s.ch == '{' ) {
- s.nextToken();
- s.nextToken();
- val bs = new myTreeList();
- val b = expr(true,false); //block( s.pos );
- if( s.token != RBRACE ) {
- s.xml_syntaxError(" expected end of Scala block");
- }
- s.xmlSpaceOpt();
- ts.append( b );
- }
- }
- case _ => { /* text ? */
- val pos = s.pos;
- ts.append( gen.mkStringLit( pos, s.xmlText() ));
- }
- }
- }
- xmlEndTag( elemName );
- if( attrMap.isEmpty )
- makeXML( pos, elemName, ts.toArray() );
- else
- makeXML( pos, elemName, ts.toArray(), attrMap );
- }
- }
-
- /** top level xml pattern, resynchronizes after succesful parse
- * see xmlPattern
- */
- def xmlPatternTop():Tree = {
- val t = xmlPattern();
- s.nextToken();
- t
- }
-
- /** '<' xmlPattern ::= Name [S] { xmlPattern | '{' pattern3 '}' } ETag
- * | Name [S] '\' '>'
- */
- def xmlPattern():Tree = {
- val pos = s.pos;
- val elemName = s.xmlName();
- s.xmlSpaceOpt();
- if( s.ch == '/' ) {
- s.xmlToken('/');
- s.xmlToken('>');
- makeXMLpat( pos, elemName, Tree.EMPTY_ARRAY );
- } else { /* handle XML content: */
- s.xmlToken('>');
- val ts = new myTreeList();
- var exit = false;
- while( !exit ) {
- //Console.print("["+s.ch.asInstanceOf[char]+"]");
- s.ch match {
- case '<' => { /* tag */
- s.nextch();
- if( s.ch != '/' ) { /* search end tag */
- ts.append( xmlPattern() );
- } else {
- exit = true
- }
- }
- case '{' => { /* Scala patterns */
- while( s.ch == '{' ) {
- s.nextToken();
- s.nextToken();
- val ps = patterns();
- if( s.token != RBRACE ) {
- s.xml_syntaxError(" expected end of Scala block");
- }
- ts.append( ps );
- }
- }
- case _ => { /* text */
- val pos = s.pos;
- ts.append( gen.mkStringLit( pos, s.xmlText() ));
- }
- }
- }
- xmlEndTag( elemName );
- makeXMLpat( pos, elemName, ts.toArray() );
- }
- }
////////// MODIFIERS ////////////////////////////////////////////////////////////
/** Modifiers ::= {Modifier}
diff --git a/sources/scala/tools/scalac/ast/parser/Scanner.scala b/sources/scala/tools/scalac/ast/parser/Scanner.scala
index 174040d220..522ec142e0 100644
--- a/sources/scala/tools/scalac/ast/parser/Scanner.scala
+++ b/sources/scala/tools/scalac/ast/parser/Scanner.scala
@@ -8,6 +8,7 @@
import scalac._;
import scalac.util.Name;
+import scalac.util.Names;
import scalac.util.SourceRepresentation;
package scala.tools.scalac.ast.parser {
@@ -653,69 +654,79 @@ class Scanner(_unit: Unit) extends TokenData {
}
}
- /* X L
+ /* X M L
*/
- /* methods for XML tokenizing, see XML 1.0 rec, available from www.w3.org/xml */
+ /* methods for XML tokenizing, see XML 1.0 rec http://www.w3.org/xml */
- /* M
- */
-
- def xml_syntaxError(s:String) = {
- syntaxError("in XML literal: "+s);
- xml_nextch();
+ def xSyntaxError(s:String) = {
+ syntaxError("in XML literal: "+s); xNext;
}
- /* this helper functions updates ccol and cline
+ /** read the next character. do not skip whitespace.
+ * treat CR LF as single LF. update ccol and cline
+ *
+ * @todo: may XML contain SU, in CDATA sections ?
*/
- def xml_nextch() = {
+ def xNext = {
nextch();
ch match {
- case SU => syntaxError(lastpos, "unclosed XML literal"); token = EOF;
+ case SU =>
+ syntaxError( lastpos, "unclosed XML literal" );
+ token = EOF;
+ case LF =>
+ ccol = 0; cline = cline + 1;
case CR =>
- cline = cline + 1;
- ccol = 0;
- nextch(); /* in compliance with XML spec */
- if( ch == LF ) {
- ccol = 0;
- }
- case LF => {
- cline = cline + 1;
- ccol = 0;
- }
+ nextch();
+ if( LF == ch ) {
+ ccol = 0; cline = cline + 1;
+ } else {
+ bp = bp - 1; ch = CR
+ }
case _ =>
}
pos = Position.encode(cline, ccol);
}
- def xml_isSpace() = ch match {
- case ' ' | '\t' | '\r' | '\n' => true
+ /** scan [S] '=' [S]
+ */
+ def xEQ = {
+ xSpaceOpt; xToken('='); xSpaceOpt
+ }
+
+ final val LT = Name.fromString("<");
+
+ def xStartsXML = {
+ unit.global.xmlMarkup && ( token == IDENTIFIER )&&( name == LT );
+ }
+
+ def xIsSpace = ch match {
+ case ' ' | '\t' | CR | LF => true
case _ => false;
}
- def xmlSpaceOpt() = {
- while( xml_isSpace() ) {
- xml_nextch();
- }
+ /** skip optional space S?
+ */
+ def xSpaceOpt = {
+ while( xIsSpace ) { xNext; }
}
- /** [3] S ::= (#x20 | #x9 | #xD | #xA)+
+ /** scan [3] S ::= (#x20 | #x9 | #xD | #xA)+
*/
- def xmlSpace() = {
- if( xml_isSpace() ) {
- xml_nextch();
- xmlSpaceOpt()
+ def xSpace = {
+ if( xIsSpace ) {
+ xNext; xSpaceOpt
} else {
- xml_syntaxError("whitespace expected");
+ xSyntaxError("whitespace expected");
}
}
- /** a subset of
- * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
- *
- * todo: add unicode letters and digits as well as combining chars and extenders
+ /** scan [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':'
+ * | CombiningChar | Extender
+ * partial implementation
+ * @todo: add unicode letters, add CombiningChar Extender
**/
- def xml_isNameChar() = ch match {
+ def xIsNameChar = ch match {
case 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' |
'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' |
'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | 'a' | 'b' | 'c' | 'd' | 'e' |
@@ -726,7 +737,8 @@ class Scanner(_unit: Unit) extends TokenData {
case _ => false
}
- def xml_isNameStart() = ch match {
+ /** scan (Letter | '_' | ':') */
+ def xIsNameStart = ch match {
case 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' |
'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' |
'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | 'a' | 'b' | 'c' | 'd' | 'e' |
@@ -735,63 +747,72 @@ class Scanner(_unit: Unit) extends TokenData {
'_' | ':' => true;
case _ => false
}
- /** a subset of (see isNameChar() )
- * [5] Name ::= (Letter | '_' | ':') (NameChar)*
+ /** scan [5] Name ::= (Letter | '_' | ':') (NameChar)*
*/
- def xmlName():Name = {
- if( xml_isNameStart() ) {
+ def xName:Name = {
+ if( xIsNameStart ) {
val index = bp;
- while( xml_isNameChar() ) {
- xml_nextch();
- }
- Name.fromAscii(buf, index, bp - index);
+ while( xIsNameChar ) { xNext; }
+ Name.fromAscii( buf, index, bp - index );
} else {
- xml_syntaxError("name expected");
- Name.fromString("-error-");
+ xSyntaxError( "name expected" );
+ Names.EMPTY
}
}
- /* consuming everything up to the next endch */
- def xmlValue(endch:char):String = xmlValue(endch, true);
+ /** @see xSkipToNext( char, boolean ) */
+ def xSkipToNext( endch:char ):String = xSkipToNext( endch, true );
- def xmlValue(endch:char, keep:boolean):String = {
+ /** move forward to next endch. return a string if needed.
+ * @param endch the character to which we skip
+ * @param keep if true, this function returns the string, otherwise null
+ */
+ def xSkipToNext( endch:char, keep:boolean ):String = {
lastpos = pos;
val index = bp;
- while ( ch != endch ) { xml_nextch();};
- pos = Position.encode( cline, ccol );
+ while ( ch != endch ) { xNext; };
if( keep )
- new String(buf, index, bp-index);
+ new String( buf, index, bp-index );
else
null
}
- def xmlAttribValue(endch:char):String = {
- val s = xmlValue(endch, true);
+ /** attribute value, terminated by either ' or ". value may not contain <.
+ * @param endch either ' or "
+ */
+ def xAttributeValue( endch:char ):String = {
+ val s = xSkipToNext( endch );
+ // well-formedness constraint
if( s.indexOf('<') != -1 ) {
- xml_syntaxError("'<' not allowed in attrib value");
- "--syntax error--"
+ xSyntaxError( "'<' not allowed in attrib value" ); ""
} else {
s
}
}
- def xmlText():String = xmlValue('<');
+ /** character data. WRONG
+ */
+ def xText:String = xSkipToNext( '<' );
- def xmlComment() = {
- xmlToken('!');
- xmlToken('-');
- xmlToken('-');
- xmlValue('-', false);
- xmlToken('-');
- xmlToken('-');
- xmlToken('>');
+ /** scan XML comment.
+ */
+ def xComment = {
+ xToken('!');
+ xToken('-');
+ xToken('-');
+ xSkipToNext('-', false);
+ xToken('-');
+ xToken('-');
+ xToken('>');
};
- def xmlToken(that:char):unit = {
+ /** scan an exected XML token
+ */
+ def xToken(that:char):unit = {
if( ch == that ) {
- xml_nextch();
+ xNext;
} else {
- xml_syntaxError("'"+that+"' expected instead of '"+ch.asInstanceOf[char]+"'");
+ xSyntaxError("'"+that+"' expected instead of '"+ch.asInstanceOf[char]+"'");
}
}
/* end XML tokenizing */