Skip to content

Commit

Permalink
Add an irrefutable version of the NoSuccess extractor (#496)
Browse files Browse the repository at this point in the history
  • Loading branch information
lrytz authored Jan 25, 2023
1 parent 2ac42b0 commit 537211c
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,34 @@ trait Parsers {

def get: Nothing = scala.sys.error("No result when parsing failed")
}
/** An extractor so `NoSuccess(msg, next)` can be used in matches. */
/**
* An extractor so `case NoSuccess(msg, next)` can be used in matches.
*
* Note: On Scala 2.13, using this extractor leads to an exhaustivity warning:
*
* {{{
* def m(r: ParseResult[Int]) = r match {
* case Success(i) => ...
* case NoSuccess(msg, _) => ... // "warning: match may not be exhaustive"
* }}}
*
* To eliminate this warning, use the irrefutable `NoSuccess.I` extractor.
* Due to binary compatibility, `NoSuccess` itself cannot be changed.
*/
object NoSuccess {
def unapply[T](x: ParseResult[T]) = x match {
case Failure(msg, next) => Some((msg, next))
case Error(msg, next) => Some((msg, next))
case _ => None
}

/** An irrefutable version of the `NoSuccess` extractor, used as `case NoSuccess.I(msg, next)`. */
object I {
def unapply(x: NoSuccess): Some[(String, Input)] = x match {
case Failure(msg, next) => Some((msg, next))
case Error(msg, next) => Some((msg, next))
}
}
}

/** The failure case of `ParseResult`: contains an error-message and the remaining input.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ class PackratParsersTest {

def extractResult(r : ParseResult[Int]): Int = r match {
case Success(a,_) => a
case NoSuccess(a,_) => sys.error(a)
case Failure(a, _) => sys.error(a)
case Error(a, _) => sys.error(a)
case NoSuccess.I(a,_) => sys.error(a)
}
def check(expected: Int, expr: String): Unit = {
val parseResult = head(new lexical.Scanner(expr))
Expand Down Expand Up @@ -84,9 +82,7 @@ class PackratParsersTest {

def extractResult(r : ParseResult[Int]): Int = r match {
case Success(a,_) => a
case NoSuccess(a,_) => sys.error(a)
case Failure(a, _) => sys.error(a)
case Error(a, _) => sys.error(a)
case NoSuccess.I(a,_) => sys.error(a)
}
def check(expected: Int, expr: String): Unit = {
val parseResult = head(new lexical.Scanner(expr))
Expand All @@ -109,9 +105,7 @@ class PackratParsersTest {
val head = phrase(AnBnCn)
def extractResult(r: ParseResult[AnBnCnResult]): AnBnCnResult = r match {
case Success(a,_) => a
case NoSuccess(a,_) => sys.error(a)
case Failure(a, _) => sys.error(a)
case Error(a, _) => sys.error(a)
case NoSuccess.I(a,_) => sys.error(a)
}
def threeLists(as: List[Symbol], bs: List[Symbol], cs: List[Symbol]): AnBnCnResult = {
val as1 = as.map(_.name)
Expand Down Expand Up @@ -152,9 +146,7 @@ class PackratParsersTest {

def extractResult(r: ParseResult[Res]): Res = r match {
case Success(a,_) => a
case NoSuccess(a,_) => sys.error(a)
case Failure(a, _) => sys.error(a)
case Error(a, _) => sys.error(a)
case NoSuccess.I(a,_) => sys.error(a)
}
def check(expected: Term, input: String, ctx: Ctx): Unit = {
val parseResult = phraseTerm(new lexical.Scanner(input))
Expand Down

0 comments on commit 537211c

Please sign in to comment.