summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library/scala/util/parsing/combinator/Parsers.scala14
-rw-r--r--test/files/run/parserFilter.check9
-rw-r--r--test/files/run/parserFilter.scala15
-rw-r--r--test/files/run/parserForFilter.check1
-rw-r--r--test/files/run/parserForFilter.scala12
5 files changed, 51 insertions, 0 deletions
diff --git a/src/library/scala/util/parsing/combinator/Parsers.scala b/src/library/scala/util/parsing/combinator/Parsers.scala
index e7ea9f598b..341e654d56 100644
--- a/src/library/scala/util/parsing/combinator/Parsers.scala
+++ b/src/library/scala/util/parsing/combinator/Parsers.scala
@@ -108,6 +108,8 @@ trait Parsers {
def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U]
+ def filterWithError(p: T => Boolean, error: T => String, position: Input): ParseResult[T]
+
def append[U >: T](a: => ParseResult[U]): ParseResult[U]
def isEmpty = !successful
@@ -137,6 +139,10 @@ trait Parsers {
def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U]
= f(result)(next)
+ def filterWithError(p: T => Boolean, error: T => String, position: Input): ParseResult[T] =
+ if (p(result)) this
+ else Failure(error(result), position)
+
def append[U >: T](a: => ParseResult[U]): ParseResult[U] = this
def get: T = result
@@ -161,6 +167,8 @@ trait Parsers {
def flatMapWithNext[U](f: Nothing => Input => ParseResult[U]): ParseResult[U]
= this
+ def filterWithError(p: Nothing => Boolean, error: Nothing => String, position: Input): ParseResult[Nothing] = this
+
def get: Nothing = sys.error("No result when parsing failed")
}
/** An extractor so `NoSuccess(msg, next)` can be used in matches. */
@@ -224,6 +232,12 @@ trait Parsers {
def map[U](f: T => U): Parser[U] //= flatMap{x => success(f(x))}
= Parser{ in => this(in) map(f)}
+ def filter(p: T => Boolean): Parser[T]
+ = withFilter(p)
+
+ def withFilter(p: T => Boolean): Parser[T]
+ = Parser{ in => this(in) filterWithError(p, "Input doesn't match filter: "+_, in)}
+
// no filter yet, dealing with zero is tricky!
@migration(2, 9, "As of 2.9, the call-by-name argument is evaluated at most once per constructed Parser object, instead of on every need that arises during parsing.")
diff --git a/test/files/run/parserFilter.check b/test/files/run/parserFilter.check
new file mode 100644
index 0000000000..be04454426
--- /dev/null
+++ b/test/files/run/parserFilter.check
@@ -0,0 +1,9 @@
+[1.3] failure: Input doesn't match filter: false
+
+if false
+ ^
+[1.1] failure: Input doesn't match filter: not
+
+not true
+^
+[1.8] parsed: (if~true)
diff --git a/test/files/run/parserFilter.scala b/test/files/run/parserFilter.scala
new file mode 100644
index 0000000000..d007d441f4
--- /dev/null
+++ b/test/files/run/parserFilter.scala
@@ -0,0 +1,15 @@
+object Test extends scala.util.parsing.combinator.RegexParsers {
+ val keywords = Set("if", "false")
+ def word: Parser[String] = "\\w+".r
+
+ def keyword: Parser[String] = word filter (keywords.contains)
+ def ident: Parser[String] = word filter(!keywords.contains(_))
+
+ def test = keyword ~ ident
+
+ def main(args: Array[String]) {
+ println(parseAll(test, "if false"))
+ println(parseAll(test, "not true"))
+ println(parseAll(test, "if true"))
+ }
+}
diff --git a/test/files/run/parserForFilter.check b/test/files/run/parserForFilter.check
new file mode 100644
index 0000000000..a53c147719
--- /dev/null
+++ b/test/files/run/parserForFilter.check
@@ -0,0 +1 @@
+[1.13] parsed: (second,first)
diff --git a/test/files/run/parserForFilter.scala b/test/files/run/parserForFilter.scala
new file mode 100644
index 0000000000..1bc44f8033
--- /dev/null
+++ b/test/files/run/parserForFilter.scala
@@ -0,0 +1,12 @@
+object Test extends scala.util.parsing.combinator.RegexParsers {
+ def word: Parser[String] = "\\w+".r
+
+ def twoWords = for {
+ (a ~ b) <- word ~ word
+ } yield (b, a)
+
+ def main(args: Array[String]) {
+ println(parseAll(twoWords, "first second"))
+ }
+}
+