diff options
author | Daniel Capo Sobral <dcs@dcs-132-CK-NF79.(none)> | 2011-11-02 18:13:24 -0200 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-12-02 14:16:00 -0800 |
commit | 2f02cdaaf3674de490bed30e795f778180329dd9 (patch) | |
tree | 131690db2b5da5b84f56338d98960ece6fa8681c | |
parent | 8be1cfc777352a2e65344ebc1413dd9398379081 (diff) | |
download | scala-2f02cdaaf3674de490bed30e795f778180329dd9.tar.gz scala-2f02cdaaf3674de490bed30e795f778180329dd9.tar.bz2 scala-2f02cdaaf3674de490bed30e795f778180329dd9.zip |
Add filter/withFilter method to Parser
Complement map and flatMap when used in for comprehensions. This is
required when pattern matching is used on the result of the generators.
It is implemented through a new filterWithError method on ParseResult.
-rw-r--r-- | src/library/scala/util/parsing/combinator/Parsers.scala | 14 | ||||
-rw-r--r-- | test/files/run/parserFilter.check | 9 | ||||
-rw-r--r-- | test/files/run/parserFilter.scala | 15 | ||||
-rw-r--r-- | test/files/run/parserForFilter.check | 1 | ||||
-rw-r--r-- | test/files/run/parserForFilter.scala | 12 |
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")) + } +} + |