diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2007-07-07 11:45:12 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2007-07-07 11:45:12 +0000 |
commit | f974621afd772591aafa5370e6751064983f89af (patch) | |
tree | 193c1caa8b296e9ff9582789e6c659ed8b865913 /src/library | |
parent | 00c12b4d00e45a9af61652d37355460ddfeb03c6 (diff) | |
download | scala-f974621afd772591aafa5370e6751064983f89af.tar.gz scala-f974621afd772591aafa5370e6751064983f89af.tar.bz2 scala-f974621afd772591aafa5370e6751064983f89af.zip |
integrating combinators into trunk
Diffstat (limited to 'src/library')
7 files changed, 324 insertions, 0 deletions
diff --git a/src/library/scala/util/parsing/input/CharArrayPosition.scala b/src/library/scala/util/parsing/input/CharArrayPosition.scala new file mode 100644 index 0000000000..299f15f067 --- /dev/null +++ b/src/library/scala/util/parsing/input/CharArrayPosition.scala @@ -0,0 +1,41 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.util.parsing.input + +/** `CharArrayPosition' implements the general `Position' class for + * documents represented by an `Array' of `char's. + * + * @param source The contents of the document in which this position is contained + * @param line The line number of the position (1-based) + * @param columm The column number of the position (1-based) + * + * @author Martin Odersky, Adriaan Moors + */ +class CharArrayPosition(val source: Array[char], val line: int, val column: int) extends Position { + + // TODO: this could be implemented more high-level: + // return the string representation of the sub-array of source that starts after the + // (lnum-1)'ed '\n' up to (but not including) the (lnum)'ed '\n' + protected def lineContents(lnum: int) = { + var i = 0 + var l = 1 + while (i < source.length && l < lnum) { + while (i < source.length && source(i) != '\n') i = i + 1 + i = i + 1 + l = l + 1 + } + var chars = new StringBuffer + while (i < source.length && source(i) != '\n') { + chars append source(i) + i = i + 1 + } + chars.toString + } +} + diff --git a/src/library/scala/util/parsing/input/CharArrayReader.scala b/src/library/scala/util/parsing/input/CharArrayReader.scala new file mode 100644 index 0000000000..4a531a4e53 --- /dev/null +++ b/src/library/scala/util/parsing/input/CharArrayReader.scala @@ -0,0 +1,56 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.util.parsing.input + +/** An object encapsulating basic character constants + * + * @author Martin Odersky, Adriaan Moors + */ +object CharArrayReader { + 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 an array of characters + * @param index starting offset into the array; the first element returned will be `source(index)' + * @param line the line number of the first element (counting from index `0' of `source') + * @param column the column number of the first element (counting from index `0' of `source') + * + * @author Martin Odersky, Adriaan Moors + */ +class CharArrayReader(source: Array[char], index: int, line: int, column: int) extends Reader[char] { + import CharArrayReader._ + + /** Construct a `CharArrayReader' with its first element at `source(0)' and position `(1,1)' + */ + def this(source: Array[char]) = this(source, 0, 1, 1) + + private var i = index + if (i + 1 < source.length && source(i) == CR && source(i + 1) == '\n') i = 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/NoPosition.scala b/src/library/scala/util/parsing/input/NoPosition.scala new file mode 100644 index 0000000000..ad498d19af --- /dev/null +++ b/src/library/scala/util/parsing/input/NoPosition.scala @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.util.parsing.input + +/** Undefined position + * + * @author Martin Odersky, Adriaan Moors + */ +object NoPosition extends Position { + def line = 0 + def column = 0 + override def toString = "<undefined position>" + override def longString = toString + def lineContents(lnum: int) = "" +} diff --git a/src/library/scala/util/parsing/input/Position.scala b/src/library/scala/util/parsing/input/Position.scala new file mode 100644 index 0000000000..0908c1fda7 --- /dev/null +++ b/src/library/scala/util/parsing/input/Position.scala @@ -0,0 +1,74 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.util.parsing.input + +/** `Position' is the base class for objects describing a position in a ``document''. + *<p> + * It provides functionality for: <ul> + * <li> generating a visual representation of this position (`longString'); + * <li> comparing two positions (`<'). + * </ul></p> + *<p> + * To use this class for a concrete kind of ``document'', implement the `lineContents' method.</p> + * + * @author Martin Odersky, Adriaan Moors + */ +trait Position { + + /** The line number referred to by the position; line numbers start at 1 */ + def line: int + + /** The column number referred to by the position; column numbers start at 1 */ + def column: int + + /** 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) + */ + protected def lineContents(lnum: int): String + + /** Returns a string representation of the `Position', of the form `line.column' */ + override def toString = ""+line+"."+column + + /** Returns a more ``visual'' representation of this position. + * More precisely, the resulting string consists of two lines: <ol> + * <li> the line in the document referred to by this position </li> + * <li>a caret indicating the column</li></ol> + * + * Example: + * + *<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 + } + }*/ + + /** 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' + */ + def <(that: Position) = { + this.line < that.line || + this.line == that.line && this.column < that.column + } +} diff --git a/src/library/scala/util/parsing/input/Positional.scala b/src/library/scala/util/parsing/input/Positional.scala new file mode 100644 index 0000000000..37bb5e2649 --- /dev/null +++ b/src/library/scala/util/parsing/input/Positional.scala @@ -0,0 +1,29 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.util.parsing.input + +/** A trait for objects that have a source position. + * + * @author Martin Odersky, Adriaan Moors + */ +trait Positional { + + /** The source position of this object, initially set to undefined. */ + var pos: Position = NoPosition + + /** If current source position is undefined, update it with given position `newpos' + * @return the object itself + */ + def setPos(newpos: Position): this.type = { + if (pos eq NoPosition) pos = newpos + this + } +} + + diff --git a/src/library/scala/util/parsing/input/Reader.scala b/src/library/scala/util/parsing/input/Reader.scala new file mode 100644 index 0000000000..327f4f7aff --- /dev/null +++ b/src/library/scala/util/parsing/input/Reader.scala @@ -0,0 +1,36 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.util.parsing.input + +/** An interface for streams of values that have positions + * + * @author Martin Odersky, Adriaan Moors + */ +abstract class Reader[+T] { + + /** Returns the first element of the stream + */ + def first: T + + /** Returns an abstract reader consisting of all elements except the first + * + * @return If `atEnd' is true, the result will be `this'; otherwise, it's a `Reader' containing + * more elements. + */ + def rest: Reader[T] + + /** The position of the first element in the stream + */ + 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) + */ + def atEnd: boolean +} diff --git a/src/library/scala/util/parsing/input/StreamReader.scala b/src/library/scala/util/parsing/input/StreamReader.scala new file mode 100755 index 0000000000..c07b85b83d --- /dev/null +++ b/src/library/scala/util/parsing/input/StreamReader.scala @@ -0,0 +1,67 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.util.parsing.input + +import java.io.BufferedReader + +/** An object to create a StreamReader from a java.io.Reader. + * + * @param in the java.io.Reader that provides the underlying stream of characters for this Reader + * + * @author Miles Sabin + */ +object StreamReader +{ + final val EofCh = '\032' + final val CR = '\015' + + def apply(in: java.io.Reader) = { + val bin = new BufferedReader(in) + new StreamReader(bin, bin.readLine, 1, 1) + } +} + +/** A character array reader reads a stream of characters (keeping track of their positions) + * from an array. + * + * @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' + * @param column the 1-based column number of the character returned by `first' + * + * @author Miles Sabin + */ +sealed class StreamReader private (bin: java.io.BufferedReader, sourceLine: String, ln: int, col: int) extends Reader[char] +{ + import StreamReader._ + + def first = + if(sourceLine == null) + EofCh + else if(col > sourceLine.length) + CR + else + sourceLine(col-1) + + def rest: StreamReader = + if(sourceLine == null) + this + else if(col > sourceLine.length) + new StreamReader(bin, bin.readLine, ln+1, 1) + else + new StreamReader(bin, sourceLine, ln, col+1) + + def pos: Position = new Position { + def line = ln + def column = col + def lineContents(lnum: int) = sourceLine + } + + def atEnd = (sourceLine == null) +} |