summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2007-07-07 11:45:12 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2007-07-07 11:45:12 +0000
commitf974621afd772591aafa5370e6751064983f89af (patch)
tree193c1caa8b296e9ff9582789e6c659ed8b865913
parent00c12b4d00e45a9af61652d37355460ddfeb03c6 (diff)
downloadscala-f974621afd772591aafa5370e6751064983f89af.tar.gz
scala-f974621afd772591aafa5370e6751064983f89af.tar.bz2
scala-f974621afd772591aafa5370e6751064983f89af.zip
integrating combinators into trunk
-rw-r--r--src/library/scala/util/parsing/input/CharArrayPosition.scala41
-rw-r--r--src/library/scala/util/parsing/input/CharArrayReader.scala56
-rw-r--r--src/library/scala/util/parsing/input/NoPosition.scala21
-rw-r--r--src/library/scala/util/parsing/input/Position.scala74
-rw-r--r--src/library/scala/util/parsing/input/Positional.scala29
-rw-r--r--src/library/scala/util/parsing/input/Reader.scala36
-rwxr-xr-xsrc/library/scala/util/parsing/input/StreamReader.scala67
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)
+}