summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2010-01-18 17:06:37 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2010-01-18 17:06:37 +0000
commit6e4cba7314c8fabcf73ce7324dc8fdf852515246 (patch)
tree9cad99ee4640186c492de616eeefc34b02158075
parent2cff99f2d2cff5a3e1b896177abbd2acda239744 (diff)
downloadscala-6e4cba7314c8fabcf73ce7324dc8fdf852515246.tar.gz
scala-6e4cba7314c8fabcf73ce7324dc8fdf852515246.tar.bz2
scala-6e4cba7314c8fabcf73ce7324dc8fdf852515246.zip
Merged revisions 20573 via svnmerge from
https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r20573 | extempore | 2010-01-18 17:55:52 +0100 (Mon, 18 Jan 2010) | 3 lines Tail-recursive implementations of parser combinators rep1 and repN, which covers all of them since the others go through those. Review by rompf. ........
-rw-r--r--src/library/scala/util/parsing/combinator/Parsers.scala52
1 files changed, 23 insertions, 29 deletions
diff --git a/src/library/scala/util/parsing/combinator/Parsers.scala b/src/library/scala/util/parsing/combinator/Parsers.scala
index 3aa7cc7de1..6fe35ad3b0 100644
--- a/src/library/scala/util/parsing/combinator/Parsers.scala
+++ b/src/library/scala/util/parsing/combinator/Parsers.scala
@@ -11,7 +11,8 @@
package scala.util.parsing.combinator
import scala.util.parsing.input._
-import scala.collection.mutable.{Map=>MutableMap}
+import scala.collection.mutable.ListBuffer
+import scala.annotation.tailrec
// TODO: better error handling (labelling like parsec's <?>)
@@ -539,7 +540,6 @@ trait Parsers {
r
}
-
/** A parser generator for repetitions.
*
* <p> rep(p) repeatedly uses `p' to parse the input until `p' fails (the result is a List
@@ -589,37 +589,20 @@ trait Parsers {
* @return A parser that returns a list of results produced by first applying `f' and then
* repeatedly `p' to the input (it only succeeds if `f' matches).
*/
- def rep1[T](first: => Parser[T], p: => Parser[T]): Parser[List[T]] = Parser{ in0 =>
- val xs = new scala.collection.mutable.ListBuffer[T]
- var in = in0
-
- var res = first(in)
+ def rep1[T](first: => Parser[T], p: => Parser[T]): Parser[List[T]] = Parser { in =>
+ val elems = new ListBuffer[T]
- while(res.successful) {
- xs += res.get
- in = res.next
- res = p(in)
+ @tailrec def applyp(in0: Input): ParseResult[List[T]] = p(in0) match {
+ case Success(x, rest) => elems += x ; applyp(rest)
+ case _ => Success(elems.toList, in0)
}
- // assert(res.isInstanceOf[NoSuccess])
-
- res match {
- case e: Error => e
- case _ =>
- if (!xs.isEmpty) {
- // the next parser should start parsing where p failed,
- // since `!p(in).successful', the next input to be consumed is `in'
- Success(xs.toList, in) // TODO: I don't think in == res.next holds
- }
- else {
- Failure(res.asInstanceOf[NoSuccess].msg, in0)
- }
+ first(in) match {
+ case Success(x, rest) => elems += x ; applyp(rest)
+ case ns: NoSuccess => ns
}
}
- //= first ~ rep(p) ^^ { case ~(x, xs) => x :: xs }
-
-
/** A parser generator for a specified number of repetitions.
*
* <p> repN(n, p) uses `p' exactly `n' time to parse the input
@@ -630,8 +613,19 @@ trait Parsers {
* @return A parser that returns a list of results produced by repeatedly applying `p' to the input
* (and that only succeeds if `p' matches exactly `n' times).
*/
- def repN[T](n: Int, p: => Parser[T]): Parser[List[T]] =
- if(n==0) success(Nil) else p ~ repN(n-1, p) ^^ { case ~(x, xs) => x :: xs }
+ def repN[T](num: Int, p: => Parser[T]): Parser[List[T]] =
+ if (num == 0) success(Nil) else Parser { in =>
+ val elems = new ListBuffer[T]
+
+ @tailrec def applyp(in0: Input): ParseResult[List[T]] =
+ if (elems.length == num) Success(elems.toList, in0)
+ else p(in0) match {
+ case Success(x, rest) => elems += x ; applyp(rest)
+ case ns: NoSuccess => return ns
+ }
+
+ applyp(in)
+ }
/** A parser generator for non-empty repetitions.
*