diff options
-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")) + } +} + |