diff options
author | Paul Phillips <paulp@improving.org> | 2010-01-15 02:12:10 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-01-15 02:12:10 +0000 |
commit | 2d324f4506191ba9059e14fa7482c2276b5f255a (patch) | |
tree | de9b4d00d4864eaaffdd033d36edf420ba83f619 /src/library | |
parent | df4d259938d2a522ba0726e86ded78d2a09982ce (diff) | |
download | scala-2d324f4506191ba9059e14fa7482c2276b5f255a.tar.gz scala-2d324f4506191ba9059e14fa7482c2276b5f255a.tar.bz2 scala-2d324f4506191ba9059e14fa7482c2276b5f255a.zip |
Fix and test for #2354. Review by community.
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/collection/Iterator.scala | 5 | ||||
-rw-r--r-- | src/library/scala/xml/parsing/MarkupParser.scala | 27 | ||||
-rw-r--r-- | src/library/scala/xml/parsing/MarkupParserCommon.scala | 48 |
3 files changed, 61 insertions, 19 deletions
diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 5f28161ed3..6be99bf27c 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -1112,9 +1112,10 @@ trait Iterator[+A] { self => res.toList } - /** Traverses this iterator and returns all produced values in a list. + /** Lazily wraps a Stream around this iterator so its values are memoized. * - * @return a stream which contains all values produced by this iterator. + * @return a Stream which can repeatedly produce all the values + * produced by this iterator. */ def toStream: Stream[A] = if (hasNext) Stream.cons(next, toStream) else Stream.empty diff --git a/src/library/scala/xml/parsing/MarkupParser.scala b/src/library/scala/xml/parsing/MarkupParser.scala index 2779fe1d7c..a15cd0f7e4 100644 --- a/src/library/scala/xml/parsing/MarkupParser.scala +++ b/src/library/scala/xml/parsing/MarkupParser.scala @@ -32,6 +32,7 @@ trait MarkupParser extends MarkupParserCommon with TokenTests self: MarkupParser with MarkupHandler => type PositionType = Int + type InputType = Source def xHandleError(that: Char, msg: String) = reportSyntaxError(msg) @@ -47,6 +48,15 @@ trait MarkupParser extends MarkupParserCommon with TokenTests // var curInput: Source = input + def lookahead(): BufferedIterator[Char] = new BufferedIterator[Char] { + val stream = curInput.toStream + curInput = Source.fromIterable(stream) + val underlying = Source.fromIterable(stream).buffered + + def hasNext = underlying.hasNext + def next = underlying.next + def head = underlying.head + } /** the handler of the markup, returns this */ private val handle: MarkupHandler = this @@ -57,7 +67,6 @@ trait MarkupParser extends MarkupParserCommon with TokenTests /** holds the position in the source file */ var pos: Int = _ - /* used when reading external subset */ var extIndex = -1 @@ -379,20 +388,8 @@ trait MarkupParser extends MarkupParserCommon with TokenTests */ def xCharData: NodeSeq = { xToken("[CDATA[") - val pos1 = pos - val sb: StringBuilder = new StringBuilder() - while (true) { - if (ch==']' && - { sb.append(ch); nextch; ch == ']' } && - { sb.append(ch); nextch; ch == '>' } ) { - sb.setLength(sb.length - 2); - nextch; - return PCData(sb.toString) - } else sb.append( ch ); - nextch; - } - // bq: (todo) increase grace when meeting CDATA section - throw FatalError("this cannot happen"); + def mkResult(pos: Int, s: String): NodeSeq = PCData(s) + xTakeUntil(mkResult, () => pos, "]]>") } /** CharRef ::= "&#" '0'..'9' {'0'..'9'} ";" diff --git a/src/library/scala/xml/parsing/MarkupParserCommon.scala b/src/library/scala/xml/parsing/MarkupParserCommon.scala index c4ba2ccf15..57c46c4685 100644 --- a/src/library/scala/xml/parsing/MarkupParserCommon.scala +++ b/src/library/scala/xml/parsing/MarkupParserCommon.scala @@ -18,9 +18,16 @@ import Utility.Escapes.{ pairs => unescape } * All members should be accessed through those. */ private[scala] trait MarkupParserCommon extends TokenTests { - // type InputType // Source, CharArrayReader + private final val SU: Char = 0x1A + protected def unreachable = Predef.error("Cannot be reached.") + // type HandleType // MarkupHandler, SymbolicXMLBuilder - // type PositionType // Int, Position + + type InputType // Source, CharArrayReader + type PositionType // Int, Position + + /** Create a lookahead reader which does not influence the input */ + def lookahead(): BufferedIterator[Char] def ch: Char def nextch: Char @@ -48,4 +55,41 @@ private[scala] trait MarkupParserCommon extends TokenTests { // def returning[T](x: T)(f: T => Unit): T = { f(x) ; x } + + /** Take characters from input stream until given String "until" + * is seen. Once seen, the accumulated characters are passed + * along with the current Position to the supplied handler function. + */ + protected def xTakeUntil[T]( + handler: (PositionType, String) => T, + positioner: () => PositionType, + until: String): T = + { + val sb = new StringBuilder + val head = until charAt 0 + val rest = until drop 1 + + while (true) { + if (ch == head && peek(rest)) + return handler(positioner(), sb.toString) + else if (ch == SU) + xHandleError(ch, "") // throws TruncatedXML in compiler + + sb append ch + nextch + } + unreachable + } + + /** Create a non-destructive lookahead reader and see if the head + * of the input would match the given String. If yes, return true + * and drop the entire String from input; if no, return false + * and leave input unchanged. + */ + private def peek(lookingFor: String): Boolean = + (lookahead() take lookingFor.length sameElements lookingFor.iterator) && { + // drop the chars from the real reader (all lookahead + orig) + (0 to lookingFor.length) foreach (_ => nextch) + true + } } |