From 1b37a0b4f21834fb1d181f2b50da1728e49cf467 Mon Sep 17 00:00:00 2001 From: "Daniel C. Sobral" Date: Tue, 15 Nov 2011 23:08:16 -0200 Subject: Add withErrorMessage/withFailureMessage to Parser. Can be used to reliably override the default no success messages. --- .../scala/util/parsing/combinator/Parsers.scala | 56 ++++++++++++++++++++++ test/files/run/parserNoSuccessMessage.check | 20 ++++++++ test/files/run/parserNoSuccessMessage.scala | 19 ++++++++ 3 files changed, 95 insertions(+) create mode 100644 test/files/run/parserNoSuccessMessage.check create mode 100644 test/files/run/parserNoSuccessMessage.scala diff --git a/src/library/scala/util/parsing/combinator/Parsers.scala b/src/library/scala/util/parsing/combinator/Parsers.scala index e7ea9f598b..ad907f90e6 100644 --- a/src/library/scala/util/parsing/combinator/Parsers.scala +++ b/src/library/scala/util/parsing/combinator/Parsers.scala @@ -443,6 +443,62 @@ trait Parsers { * @return opt(this) */ def ? = opt(this) + + /** Changes the failure message produced by a parser. + * + * This doesn't change the behavior of a parser on neither + * success nor error, just on failure. The semantics are + * slightly different than those obtained by doing `| failure(msg)`, + * in that the message produced by this method will always + * replace the message produced, which is not guaranteed + * by that idiom. + * + * For example, parser `p` below will always produce the + * designated failure message, while `q` will not produce + * it if `sign` is parsed but `number` is not. + * + * {{{ + * def p = sign.? ~ number withFailureMessage "Number expected!" + * def q = sign.? ~ number | failure("Number expected!") + * }}} + * + * @param msg The message that will replace the default failure message. + * @return A parser with the same properties and different failure message. + */ + def withFailureMessage(msg: String) = Parser{ in => + this(in) match { + case Failure(_, next) => Failure(msg, next) + case other => other + } + } + + /** Changes the error message produced by a parser. + * + * This doesn't change the behavior of a parser on neither + * success nor failure, just on error. The semantics are + * slightly different than those obtained by doing `| error(msg)`, + * in that the message produced by this method will always + * replace the message produced, which is not guaranteed + * by that idiom. + * + * For example, parser `p` below will always produce the + * designated error message, while `q` will not produce + * it if `sign` is parsed but `number` is not. + * + * {{{ + * def p = sign.? ~ number withErrorMessage "Number expected!" + * def q = sign.? ~ number | error("Number expected!") + * }}} + * + * @param msg The message that will replace the default error message. + * @return A parser with the same properties and different error message. + */ + def withErrorMessage(msg: String) = Parser{ in => + this(in) match { + case Error(_, next) => Error(msg, next) + case other => other + } + } } /** Wrap a parser so that its failures become errors (the `|` combinator diff --git a/test/files/run/parserNoSuccessMessage.check b/test/files/run/parserNoSuccessMessage.check new file mode 100644 index 0000000000..fe00d2fd3a --- /dev/null +++ b/test/files/run/parserNoSuccessMessage.check @@ -0,0 +1,20 @@ +[1.2] failure: string matching regex `\d+' expected but `x' found + +-x + ^ +[1.1] failure: string matching regex `\d+' expected but `x' found + +x +^ +[1.3] parsed: (Some(-)~5) +[1.2] parsed: (None~5) +[1.2] error: Number expected! + +-x + ^ +[1.1] error: Number expected! + +x +^ +[1.3] parsed: (Some(-)~5) +[1.2] parsed: (None~5) diff --git a/test/files/run/parserNoSuccessMessage.scala b/test/files/run/parserNoSuccessMessage.scala new file mode 100644 index 0000000000..93aa252db0 --- /dev/null +++ b/test/files/run/parserNoSuccessMessage.scala @@ -0,0 +1,19 @@ +object Test extends scala.util.parsing.combinator.RegexParsers { + def sign = "-" + def number = "\\d+".r + def p = sign.? ~ number withErrorMessage "Number expected!" + def q = sign.? ~! number withErrorMessage "Number expected!" + + def main(args: Array[String]) { + println(parseAll(p, "-x")) + println(parseAll(p, "x")) + println(parseAll(p, "-5")) + println(parseAll(p, "5")) + println(parseAll(q, "-x")) + println(parseAll(q, "x")) + println(parseAll(q, "-5")) + println(parseAll(q, "5")) + } +} + + -- cgit v1.2.3