diff options
author | Martin Odersky <odersky@gmail.com> | 2008-03-10 12:00:03 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2008-03-10 12:00:03 +0000 |
commit | 83d3f475da9ab4db3bb35613639e55008b39b495 (patch) | |
tree | 9af5d7b4b8d8ffc79344599026a988caf7becaef /src/library | |
parent | 82953600481e3fa2238b897adb20d3fa7503c108 (diff) | |
download | scala-83d3f475da9ab4db3bb35613639e55008b39b495.tar.gz scala-83d3f475da9ab4db3bb35613639e55008b39b495.tar.bz2 scala-83d3f475da9ab4db3bb35613639e55008b39b495.zip |
1.
2. Added * operator to RichString
3. changed zip in Array to accept arrays of different length
4. changed takeWhile/dropWhile in Array to yield Projections
5. Added Manifest types
Diffstat (limited to 'src/library')
17 files changed, 392 insertions, 79 deletions
diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index bafe0ac58e..b3f08c5ef8 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -189,6 +189,14 @@ object Array { override def force : Array[A] = toArray override def drop( from: Int) = slice(from, length) override def take(until: Int) = slice(0, until) + override def dropWhile(p: A => Boolean) = { + val c = length + 1 + drop((findIndexOf(!p(_)) + c) % c) + } + override def takeWhile(p: A => Boolean) = { + val c = length + 1 + take((findIndexOf(!p(_)) + c) % c) + } override def slice(from0 : Int, until0 : Int) : Projection[A] = new RandomAccessSeq.MutableSlice[A] with Projection[A] { override def from = from0 override def until = until0 @@ -214,6 +222,8 @@ object Array { override def slice(from : Int, until : Int) : Projection[A] = projection.slice(from, until) override def take(until : Int) : Projection[A] = projection.take(until) override def drop(from : Int) : Projection[A] = projection.drop(from) + override def dropWhile(p: A => Boolean) = projection.dropWhile(p) + override def takeWhile(p: A => Boolean) = projection.takeWhile(p) override def reverse = projection.reverse override def force = asInstanceOf[Array[A]] } @@ -328,24 +338,6 @@ final class Array[A](_length: Int) extends Array.Array0[A] { */ override def filter(p: A => Boolean): Array[A] = throw new Error() - /** Returns the longest prefix of this array whose elements satisfy - * the predicate <code>p</code>. - * - * @param p the test predicate. - * @return the longest prefix of this array whose elements satisfy - * the predicate <code>p</code>. - */ - override def takeWhile(p: A => Boolean): Array[A] = throw new Error() - - /** Returns the longest suffix of this array whose first element - * does not satisfy the predicate <code>p</code>. - * - * @param p the test predicate. - * @return the longest suffix of the array whose first element - * does not satisfy the predicate <code>p</code>. - */ - override def dropWhile(p: A => Boolean): Array[A] = throw new Error() - /** Returns an array consisting of all elements of this array followed * by all elements of the argument iterable. */ diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala new file mode 100755 index 0000000000..ee4d70ebda --- /dev/null +++ b/src/library/scala/reflect/Manifest.scala @@ -0,0 +1,22 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.reflect + +object Manifest { + def singleType[T](value: Any): Manifest[T] = null + def classType[T](clazz: Predef.Class[_]): Manifest[T] = null + def classType[T](clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] = null + def classType[T](prefix: Manifest[_], clazz: Predef.Class[_]): Manifest[T] = null + def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] = null + def abstractType[T](prefix: Manifest[_], name: String): Manifest[T] = null + def abstractType[T](prefix: Manifest[_], name: String, args: Manifest[_]*): Manifest[T] = null + def intersectionType[T](parents: Manifest[_]*): Manifest[T] = null +} + +abstract class Manifest[T] + diff --git a/src/library/scala/runtime/BoxedArray.scala b/src/library/scala/runtime/BoxedArray.scala index f3193ec017..ea0d7c654d 100644 --- a/src/library/scala/runtime/BoxedArray.scala +++ b/src/library/scala/runtime/BoxedArray.scala @@ -98,23 +98,23 @@ abstract class BoxedArray extends Array.Array0[Any] { final override def ++[b >: Any](that: Iterable[b]): Array[b] = super.++(that).toArray - final def zip[b](that: Array[b]): Array[Tuple2[Any,b]] = { - val len = length min that.length - val result = new Array[Tuple2[Any,b]](len) + final def zip[b](that: Array[b]): Array[(Any,b)] = { + val len = this.length min that.length + val result = new Array[(Any,b)](len) var i = 0 while (i < len) { - result(i) = new Tuple2(this(i), that(i)) + result(i) = (this(i), that(i)) i += 1 } result } - final def zipWithIndex: Array[Tuple2[Any,Int]] = { + final def zipWithIndex: Array[(Any,Int)] = { val len = length - val result = new Array[Tuple2[Any,Int]](len) + val result = new Array[(Any,Int)](len) var i = 0 while (i < len) { - result(i) = new Tuple2(this(i), i) + result(i) = (this(i), i) i += 1 } result @@ -123,15 +123,6 @@ abstract class BoxedArray extends Array.Array0[Any] { /** Returns an array that contains all indices of this array */ def indices: Array[Int] = Array.range(0, length) - override def takeWhile(p: Any => Boolean) = { - val c = length + 1 - take((findIndexOf(!p(_)) + c) % c) - } - override def dropWhile(p: Any => Boolean) = { - val c = length + 1 - drop((findIndexOf(!p(_)) + c) % c) - } - final def deepToString() = deepMkString(stringPrefix + "(", ",", ")") final def deepMkString(start: String, sep: String, end: String): String = { diff --git a/src/library/scala/runtime/RichString.scala b/src/library/scala/runtime/RichString.scala index afd80afb66..8e6bca4ba5 100644 --- a/src/library/scala/runtime/RichString.scala +++ b/src/library/scala/runtime/RichString.scala @@ -74,6 +74,14 @@ final class RichString(val self: String) extends Proxy with RandomAccessSeq[Char new RichString(buf.toString) } + /** return n times the current string + */ + def * (n: Int): String = { + val buf = new StringBuffer + for (i <- 0 until n) buf append self + buf.toString + } + override def compare(other: String) = self compareTo other private def isLineBreak(c: Char) = c == LF || c == FF diff --git a/src/library/scala/util/parsing/combinator/Parsers.scala b/src/library/scala/util/parsing/combinator/Parsers.scala index b566375280..450fc73d86 100644 --- a/src/library/scala/util/parsing/combinator/Parsers.scala +++ b/src/library/scala/util/parsing/combinator/Parsers.scala @@ -715,9 +715,14 @@ trait Parsers { def phrase[T](p: Parser[T]) = new Parser[T] { lastNoSuccess = null def apply(in: Input) = p(in) match { - case s @ Success(out, in1) if in1.atEnd => s - case s @ Success(out, in1) => Failure("end of input expected", in1) - case f : NoSuccess => lastNoSuccess + case s @ Success(out, in1) => + if (in1.atEnd) + s + else if (lastNoSuccess == null || lastNoSuccess.next.pos < in1.pos) + Failure("end of input expected", in1) + else + lastNoSuccess + case _ => lastNoSuccess } } diff --git a/src/library/scala/util/parsing/combinator/RegexParsers.scala b/src/library/scala/util/parsing/combinator/RegexParsers.scala new file mode 100755 index 0000000000..6d42bb2794 --- /dev/null +++ b/src/library/scala/util/parsing/combinator/RegexParsers.scala @@ -0,0 +1,87 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: Parsers.scala 12357 2007-07-18 21:55:08Z moors $ + +package scala.util.parsing.combinator + +import java.util.regex._ +import scala.util.parsing.input.CharSequenceReader + +trait RegexParsers extends Parsers { + + type Elem = Char + + var skipWhitespace = true + + private val whiteSpacePat = Pattern compile """\s+""" + + private def handleWhiteSpace(source: CharSequence, offset: Int): Int = { + var start = offset + if (skipWhitespace) { + val wsm = whiteSpacePat.matcher(source.subSequence(offset, source.length)) + if (wsm.lookingAt) start += wsm.end + } + start + } + + /** A parser that matches a literal string */ + implicit def literal(s: String): Parser[String] = new Parser[String] { + def apply(in: Input) = { + val source = in.source + val offset = in.offset + val start = handleWhiteSpace(source, offset) + var i = 0 + var j = start + while (i < s.length && j < source.length && s.charAt(i) == source.charAt(j)) { + i += 1 + j += 1 + } + if (i == s.length) + Success(source.subSequence(start, j).toString, in.drop(j - offset)) + else + Failure("`"+s+"' expected", in.drop(start - offset)) + } + } + + /** A parser that matches a regex string */ + def regex(s: String): Parser[String] = new Parser[String] { + private val pattern = Pattern.compile(s) + def apply(in: Input) = { + val source = in.source + val offset = in.offset + val start = handleWhiteSpace(source, offset) + val pm = pattern.matcher(source.subSequence(start, source.length)) + if (pm.lookingAt) + Success(source.subSequence(start, start + pm.end).toString, + in.drop(start + pm.end - offset)) + else + Failure("string matching regex `"+s+"' expected", in.drop(start - offset)) + } + } + + /** A helper class to turn strings into regexes */ + class PreRegex(s: String) { + def r: Parser[String] = regex(s) + } + + /** An implicit definition which lets you follow a string with `.r', turning + * it into a regex parser. E.g. + * + * """A\w*""".r is a regex parser for identifiers starting with `A'. + */ + implicit def mkPreRegex(s: String) = new PreRegex(s) + + /** Parse some prefix of character sequence `in' with parser `p' */ + def parse[T](p: Parser[T])(in: CharSequence): ParseResult[T] = + p(new CharSequenceReader(in)) + + /** Parse all of character sequence `in' with parser `p' */ + def parseAll[T](p: Parser[T])(in: CharSequence): ParseResult[T] = + parse(phrase(p))(in) +} diff --git a/src/library/scala/util/parsing/combinator/lexical/Scanners.scala b/src/library/scala/util/parsing/combinator/lexical/Scanners.scala index 8b9e7724b7..d4f3103a71 100644 --- a/src/library/scala/util/parsing/combinator/lexical/Scanners.scala +++ b/src/library/scala/util/parsing/combinator/lexical/Scanners.scala @@ -66,6 +66,8 @@ trait Scanners extends Parsers { } private def skip(in: Reader[Char]) = if (in.atEnd) in else in.rest + def source: CharSequence = in.source + def offset: Int = in.offset def first = tok def rest = new Scanner(rest2) def pos = rest1.pos diff --git a/src/library/scala/util/parsing/combinator/testing/RegexTest.scala b/src/library/scala/util/parsing/combinator/testing/RegexTest.scala new file mode 100755 index 0000000000..a1356f8afe --- /dev/null +++ b/src/library/scala/util/parsing/combinator/testing/RegexTest.scala @@ -0,0 +1,21 @@ +package test + +import scala.util.parsing.combinator._ +import scala.util.parsing.input._ + +case class Ident(s: String) +case class Number(n: Int) +case class Str(s: String) + +object RegexTest extends RegexParsers { + val ident: Parser[Any] = """[a-zA-Z_]\w*""".r ^^ (s => Ident(s)) + val number: Parser[Any] = """\d\d*""".r ^^ (s => Number(s.toInt)) + val string: Parser[Any] = "\".*\"".r ^^ (s => Str(s.substring(1, s.length - 1))) + val parser = (ident | number | string)* + + def main(args: Array[String]) = { + val in = args mkString " " + println("\nin : "+in) + println(phrase[Any](parser)(new CharSequenceReader(in))) + } +} diff --git a/src/library/scala/util/parsing/combinatorold/lexical/Scanners.scala b/src/library/scala/util/parsing/combinatorold/lexical/Scanners.scala index 2256c76d62..d4479d8045 100644 --- a/src/library/scala/util/parsing/combinatorold/lexical/Scanners.scala +++ b/src/library/scala/util/parsing/combinatorold/lexical/Scanners.scala @@ -66,6 +66,8 @@ trait Scanners extends Parsers { } private def skip(in: Reader[Char]) = if (in.atEnd) in else in.rest + def source: CharSequence = in.source + def offset: Int = in.offset def first = tok def rest = new Scanner(rest2) def pos = rest1.pos diff --git a/src/library/scala/util/parsing/input/CharArrayPosition.scala b/src/library/scala/util/parsing/input/CharArrayPosition.scala index c3d9f6ea62..8d63b12332 100644 --- a/src/library/scala/util/parsing/input/CharArrayPosition.scala +++ b/src/library/scala/util/parsing/input/CharArrayPosition.scala @@ -18,7 +18,9 @@ package scala.util.parsing.input * @param columm The column number of the position (1-based) * * @author Martin Odersky, Adriaan Moors + * @deprecated; use OffsetPosition instead */ +@deprecated class CharArrayPosition(val source: Array[Char], val line: Int, val column: Int) extends Position { // TODO: this could be implemented more high-level: diff --git a/src/library/scala/util/parsing/input/CharArrayReader.scala b/src/library/scala/util/parsing/input/CharArrayReader.scala index f1f3240e19..b7c576c631 100644 --- a/src/library/scala/util/parsing/input/CharArrayReader.scala +++ b/src/library/scala/util/parsing/input/CharArrayReader.scala @@ -29,31 +29,9 @@ object CharArrayReader { * * @author Martin Odersky, Adriaan Moors */ -class CharArrayReader(source: Array[Char], index: Int, line: Int, column: Int) extends Reader[Char] { - import CharArrayReader._ +class CharArrayReader(chars: Array[Char], index: Int) +extends CharSequenceReader(new CharArraySequence(chars), index) { - /** Construct a <code>CharArrayReader</code> with its first element at - * <code>source(0)</code> and position <code>(1,1)</code>. - */ - def this(source: Array[Char]) = this(source, 0, 1, 1) + def this(chars: Array[Char]) = this(chars, 0) - private var i = index - if (i + 1 < source.length && source(i) == CR && source(i + 1) == '\n') i += 1 - - // see `first' in `Reader' - def first = if (i == source.length) EofCh else source(i) - - // see `rest' in `Reader' - def rest: CharArrayReader = { - val ch = first - if (ch == EofCh) this - else if (ch == '\n') new CharArrayReader(source, i + 1, line + 1, 1) - else new CharArrayReader(source, i + 1, line, column + 1) - } - - // see `pos' in `Reader' - def pos: Position = new CharArrayPosition(source, line, column) - - // see `atEnd' in `Reader' - def atEnd = i == source.length } diff --git a/src/library/scala/util/parsing/input/CharArraySequence.scala b/src/library/scala/util/parsing/input/CharArraySequence.scala new file mode 100755 index 0000000000..9acca84df2 --- /dev/null +++ b/src/library/scala/util/parsing/input/CharArraySequence.scala @@ -0,0 +1,37 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: + + +package scala.util.parsing.input + +/** An implementation of java.lang.CharSequence over a character array + * + * @author Martin Odersky + */ +class CharArraySequence(source: Array[Char], start: Int, end: Int) extends CharSequence { + + def this(source: Array[Char], start: Int) = this(source, start, source.length) + + def this(source: Array[Char]) = this(source, 0) + + if (start < 0) throw new IndexOutOfBoundsException + if (end > source.length) throw new IndexOutOfBoundsException + + def charAt(index: Int) = + if (start + index < end) source(index + start) + else throw new IndexOutOfBoundsException + + def length: Int = if (end < start) 0 else end - start + + def subSequence(_start: Int, _end: Int) = + new CharArraySequence(source, start + _start, start + _end) + + override def toString = new String(source, start, end - start) +} diff --git a/src/library/scala/util/parsing/input/CharSequenceReader.scala b/src/library/scala/util/parsing/input/CharSequenceReader.scala new file mode 100755 index 0000000000..453a808f08 --- /dev/null +++ b/src/library/scala/util/parsing/input/CharSequenceReader.scala @@ -0,0 +1,79 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: StringReader.scala 12268 2007-07-11 13:45:53Z michelou $ + +package scala.util.parsing.input + +/** An object encapsulating basic character constants + * + * @author Martin Odersky, Adriaan Moors + */ +object CharSequenceReader { + final val EofCh = '\032' + final val CR = '\015' +} + +/** A character array reader reads a stream of characters (keeping track of their positions) + * from an array. + * + * @param source the source sequence + * @param index starting index. + * + * @author Martin Odersky + */ +class CharSequenceReader(val source: CharSequence, index: Int) extends Reader[Char] { + import CharSequenceReader._ + + /** Construct a <code>CharSequenceReader</code> with its first element at + * <code>source(0)</code> and position <code>(1,1)</code>. + */ + def this(source: CharSequence) = this(source, 0) + + /** The effective offset into source + * This is the same as index, except that CR characters at the end of a line + * are always skipped. + */ + lazy val offset: Int = + if (index + 1 < source.length && + source.charAt(index) == CR && source.charAt(index + 1) == '\n') + index + 1 + else + index + + /** Returns the first element of the reader, or EofCh if reader is at its end + */ + def first = + if (offset == source.length) EofCh + else source.charAt(offset) + + /** Returns a CharSequenceReader consisting of all elements except the first + * + * @return If <code>atEnd</code> is <code>true</code>, the result will be + * <code>this'; otherwise, it's a <code>CharSequenceReader</code> containing + * the rest of input. + */ + def rest: CharSequenceReader = + if (offset == source.length) this + else new CharSequenceReader(source, offset + 1) + + /** The position of the first element in the reader + */ + def pos: Position = new OffsetPosition(source, offset) + + /** true iff there are no more elements in this reader (except for trailing + * EofCh's) + */ + def atEnd = offset == source.length + + /** Returns an abstract reader consisting of all elements except the first + * <code>n</code> elements. + */ + override def drop(n: Int): CharSequenceReader = + new CharSequenceReader(source, (offset + n) min source.length) +} diff --git a/src/library/scala/util/parsing/input/OffsetPosition.scala b/src/library/scala/util/parsing/input/OffsetPosition.scala new file mode 100755 index 0000000000..a29e195455 --- /dev/null +++ b/src/library/scala/util/parsing/input/OffsetPosition.scala @@ -0,0 +1,73 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.util.parsing.input + +import collection.mutable.ArrayBuffer + +/** <p> + * <code>OffsetPosition</code> is a standard class for positions + * represented as offsets into a source ``document''. + * @param source The source document + * @param offset The offset indicating the position + * + * @author Martin Odersky + */ +case class OffsetPosition(source: CharSequence, offset: Int) extends Position { + + /** An index that contains all line starts, including first line, and eof */ + private lazy val index: Array[Int] = { + var lineStarts = new ArrayBuffer[Int] + lineStarts += 0 + for (i <- 0 until source.length) + if (source.charAt(i) == '\n') lineStarts += (i + 1) + lineStarts += source.length + lineStarts.toArray + } + + /** The line number referred to by the position; line numbers start at 1 */ + def line: Int = { + var lo = 0 + var hi = index.length - 1 + while (lo + 1 < hi) { + val mid = (hi + lo) / 2 + if (offset < index(mid)) hi = mid + else lo = mid + } + lo + 1 + } + + /** The column number referred to by the position; column numbers start at 1 */ + def column: Int = offset - index(line - 1) + 1 + + /** The contents of the line numbered `lnum' (must not contain a new-line character). + * + * @param lnum a 1-based integer index into the `document' + * @return the line at `lnum' (not including a newline) + */ + def lineContents(lnum: Int): String = + source.subSequence(index(lnum - 1), index(lnum)).toString + + /** Returns a string representation of the `Position', of the form `line.column' */ + override def toString = line+"."+column + + /** Compare this position to another, by first comparing their line numbers, + * and then -- if necessary -- using the columns to break a tie. + * + * @param `that' a `Position' to compare to this `Position' + * @return true if this position's line or (in case of a tie wrt. line numbers) + * its column is smaller than the corresponding components of `that' + */ + override def <(that: Position) = that match { + case OffsetPosition(_, that_offset) => + this.offset < that_offset + case _ => + this.line < that.line || + this.line == that.line && this.column < that.column + } +} diff --git a/src/library/scala/util/parsing/input/Position.scala b/src/library/scala/util/parsing/input/Position.scala index 1be14a1211..64d2ecf3a1 100644 --- a/src/library/scala/util/parsing/input/Position.scala +++ b/src/library/scala/util/parsing/input/Position.scala @@ -9,7 +9,7 @@ package scala.util.parsing.input /** <p> - * <code>Position</code> is the base class for objects describing a + * <code>Position</code> is the base trait for objects describing a * position in a ``document''. * </p> * <p> @@ -53,18 +53,7 @@ trait Position { *<pre> List(this, is, a, line, from, the, document) * ^</pre> */ - def longString = lineContents(line)+"\n"+List.toString(List.make(column-1, ' '))+"^" -/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - TODO: it would be nicer to be able to write (' '*column-1) - --> add * method to scala.runtime.RichChar? - class RichChar { ... - /** Returns a string that consists of `n' occurrences of this character. */ - def *(n: int) = { - val chars = new StringBuffer - for (val i <- 1 until n) chars append this - chars.toString - } - }*/ + def longString = lineContents(line)+"\n"+(" " * (column - 1))+"^" /** Compare this position to another, by first comparing their line numbers, * and then -- if necessary -- using the columns to break a tie. diff --git a/src/library/scala/util/parsing/input/Reader.scala b/src/library/scala/util/parsing/input/Reader.scala index 3a1021bbd6..f9d7115113 100644 --- a/src/library/scala/util/parsing/input/Reader.scala +++ b/src/library/scala/util/parsing/input/Reader.scala @@ -17,7 +17,13 @@ package scala.util.parsing.input */ abstract class Reader[+T] { - /** Returns the first element of the stream + /** The source character sequence for this reader */ + def source: CharSequence + + /** The current index into source */ + def offset: Int + + /** Returns the first element of the reader */ def first: T @@ -29,12 +35,21 @@ abstract class Reader[+T] { */ def rest: Reader[T] - /** The position of the first element in the stream + /** Returns an abstract reader consisting of all elements except the first + * <code>n</code> elements. + */ + def drop(n: Int): Reader[T] = { + var r: Reader[T] = this + var cnt = n + while (cnt > 0) r = r.rest + r + } + + /** The position of the first element in the reader */ def pos: Position - /** Whether there are any more elements in this reader besides the first. - * (i.e., whether calling `rest' will yield a `Reader' with more elements) + /** true iff there are no more elements in this reader */ def atEnd: Boolean } diff --git a/src/library/scala/util/parsing/input/StreamReader.scala b/src/library/scala/util/parsing/input/StreamReader.scala index 9522e66650..bad859d4c0 100755 --- a/src/library/scala/util/parsing/input/StreamReader.scala +++ b/src/library/scala/util/parsing/input/StreamReader.scala @@ -32,6 +32,13 @@ object StreamReader { /** A character array reader reads a stream of characters (keeping track of * their positions) from an array. * + * NOTE: + * StreamReaders do not really fulfill the new contract for readers, which + * requires a `source' CharSequence representing the full input. + * Instead source is treated line by line. + * As a consequence, regex matching cannot extend beyond a single lines + * when a StreamReader are used for input. + * * @param bin the underlying java.io.BufferedReader * @param sourceLine the line at column `col' in the stream * @param line the 1-based line number of the character returned by `first' @@ -43,6 +50,9 @@ sealed class StreamReader private (bin: BufferedReader, sourceLine: String, ln: extends Reader[Char] { import StreamReader._ + def source: CharSequence = sourceLine + def offset: Int = col-1 + def first = if (sourceLine == null) EofCh |