implicit final class ErrorMethods[P, +A] extends AnyRef
This class exposes helpful combinators that are specialised for generating more helpful errors messages.
This extension class operates on values that are convertible to parsers. It enables the use of error combinators, which can be used for data validation, error annotation, or immediate failing.
- P
the type of base value that this class is used on (the conversion to
Parsley) is summoned automatically.
- Source
- combinator.scala
- Version
3.0.0
- Grouped
- Alphabetic
- By Inheritance
- ErrorMethods
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Instance Constructors
-
new
ErrorMethods(p: P)(implicit con: (P) ⇒ Parsley[A])
This constructor should not be called manually, it is designed to be used via Scala's implicit resolution.
This constructor should not be called manually, it is designed to be used via Scala's implicit resolution.
- p
the value that this class is enabling methods on.
- con
a conversion that allows values convertible to parsers to be used.
Value Members
-
def
!(msggen: (A) ⇒ String): Parsley[Nothing]
This combinator parses this parser and then fails, using the result of this parser to customise the error message.
This combinator parses this parser and then fails, using the result of this parser to customise the error message.
Similar to
fail, but first parses this parser: if it succeeded, then its resultxis used to form the error message for thefailcombinator by callingmsggen(x). If this parser fails, however, its error message will be generated instead.- msggen
the generator function for error message, creating a message based on the result of this parser.
- returns
a parser that always fails, with the given generator used to produce the error message if this parser succeeded.
- Note
this combinator will generate error messages rooted at the start of the previously successful parse of this parser, but only in terms of their position: the actual error is generated at the end of the parse, which means it takes priority over sibling errors. This is because the error concerns the whole parse (for caret) and morally starts where this parser started (as it caused the failure), however, if it had full
amend-like behaviour these errors would often disappear.
-
final
def
!=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
##(): Int
- Definition Classes
- AnyRef → Any
-
final
def
==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
def
?(item: String): Parsley[A]
This combinator changes the expected component of any errors generated by this parser.
This combinator changes the expected component of any errors generated by this parser.
This is just an alias for the
labelcombinator.Known as
<?>in Haskell.- Since
3.0.0
- See also
-
final
def
asInstanceOf[T0]: T0
- Definition Classes
- Any
-
def
clone(): AnyRef
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( ... ) @native()
-
def
collectMsg[B](msggen: (A) ⇒ Seq[String])(pf: PartialFunction[A, B]): Parsley[B]
This combinator applies a partial function
pfto the result of this parser if its result is defined forpf, failing if it is not.This combinator applies a partial function
pfto the result of this parser if its result is defined forpf, failing if it is not.First, parse this parser. If it succeeds, test whether its result
xis in the domain of the partial functionpf. If it is defined forpf, returnpf(x). Otherwise, if the result was undefined then fail producing a specialised error message withmsggen(x). Equivalent to aguardAgainstfollowed by amap.- msggen
a function that generates the error messages to use if the filtering fails.
- pf
the partial function used to both filter the result of this parser and transform it.
- returns
a parser which returns the result of this parser applied to pf, if possible.
A good example of this combinator in use is for handling overflow in numeric literals.
val integer: Parsley[BigInt] = ... // this should be amended/entrenched for best results val int16: Parsley[Short] = integer.collectMsg(n => Seq(s"integer literal $n is not within the range -2^16 to +2^16-1")) { case x if x >= Short.MinValue && x <= Short.MaxValue => x.toShort }
- Since
4.0.0
- Note
when this combinator fails (and not this parser itself), it will generate errors rooted at the start of the parse (as if
amendhad been used) and the caret will span the entire successful parse of this parser.- See also
collect, which is a basic version of this same combinator with no customised error message.guardAgainst, which is similar tocollectMsg, except it does not transform the data.
Example: -
def
collectMsg[B](msg0: String, msgs: String*)(pf: PartialFunction[A, B]): Parsley[B]
This combinator applies a partial function
pfto the result of this parser if its result is defined forpf, failing if it is not.This combinator applies a partial function
pfto the result of this parser if its result is defined forpf, failing if it is not.First, parse this parser. If it succeeds, test whether its result
xis in the domain of the partial functionpf. If it is defined forpf, returnpf(x). Otherwise, if the result was undefined then fail producing a specialised error message withmsg. Equivalent to aguardAgainst(whosemsggenignores its argument) followed by amap.- msg0
the first error message to use if the filtering fails.
- msgs
the remaining error messages to use if the filtering fails.
- pf
the partial function used to both filter the result of this parser and transform it.
- returns
a parser which returns the result of this parser applied to pf, if possible.
A good example of this combinator in use is for handling overflow in numeric literals.
val integer: Parsley[BigInt] = ... // this should be amended/entrenched for best results val int16: Parsley[Short] = integer.collectMsg("integer literal should within the range -2^16 to +2^16-1") { case x if x >= Short.MinValue && x <= Short.MaxValue => x.toShort }
- Since
3.0.0
- Note
when this combinator fails (and not this parser itself), it will generate errors rooted at the start of the parse (as if
amendhad been used) and the caret will span the entire successful parse of this parser.- See also
collect, which is a basic version of this same combinator with no customised error message.guardAgainst, which is similar tocollectMsg, except it does not transform the data.
Example: -
final
def
eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
def
equals(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
def
explain(reason: String): Parsley[A]
This combinator adds a reason to error messages generated by this parser.
This combinator adds a reason to error messages generated by this parser.
When this parser fails having not observably* consumed input, this combinator adds
reasonto the error message, which should justify why the error occured. Unlike error labels, which may persist if more progress is made having not consumed input, reasons are not carried forward in the error message, and are lost.*a parser is said to observably consume input when error messages generated by a parser
poccur at a deeper offset thanporiginally started at. While this sounds like it is the same as "having consumed input" for the purposes of backtracking, they are disjoint concepts:- in
attempt(p),pcan observably consume input even though the wider parser does not consume input due to theattempt. - in
amend(p),pcan consume input and may not backtrack even though the consumption is not observable in the error message due to theamend.
- reason
the reason why a parser failed.
- returns
a parser that produces the given reason for failure if it fails.
- Since
3.0.0
- in
-
def
filterOut(pred: PartialFunction[A, String]): Parsley[A]
This combinator filters the result of this parser using the given partial-predicate, succeeding only when the predicate is undefined.
This combinator filters the result of this parser using the given partial-predicate, succeeding only when the predicate is undefined.
First, parse this parser. If it succeeds then take its result
xand test ifpred.isDefinedAt(x)is true. If it is false, the parser succeeds, returningx. Otherwise,pred(x)will yield a reasonreasonand the parser will fail withreasonprovided to the generated error message à laexplain.This is useful for performing data validation, but where a definitive reason can be given for the failure. In this instance, the rest of the error message is generated as normal, with the expected and unexpected components still given, along with any other generated reasons.
- pred
the predicate that is tested against the parser result, which also generates errors.
- returns
a parser that returns the result of this parser if it fails the predicate.
scala> import parsley.character.letter scala> val keywords = Set("if", "then", "else") scala> val ident = stringOfSome(letter).filterOut { case v if keywords.contains(v) => s"keyword $v cannot be an identifier" } scala> ident.parse("hello") val res0 = Success("hello") scala> ident.parse("if") val res1 = Failure(..)
- Since
3.0.0
- Note
when this combinator fails (and not this parser itself), it will generate errors rooted at the start of the parse (as if
amendhad been used) and the caret will span the entire successful parse of this parser.- See also
filterNot, which is a basic version of this same combinator with no customised reason.guardAgainst, which is similar tofilterOut, except it generates a specialised error as opposed to just a reason.
Example: -
def
finalize(): Unit
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( classOf[java.lang.Throwable] )
-
final
def
getClass(): Class[_]
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
def
guardAgainst(pred: PartialFunction[A, Seq[String]]): Parsley[A]
This combinator filters the result of this parser using the given partial-predicate, succeeding only when the predicate is undefined.
This combinator filters the result of this parser using the given partial-predicate, succeeding only when the predicate is undefined.
First, parse this parser. If it succeeds then take its result
xand test ofpred.isDefinedAt(x)is true. If it is false, the parser succeeds, returningx. Otherwisepred(x)will yield an error messagemsgand the parser will fail, producing a specialised error only consisting of the messagemsgà lafail.This is useful for performing data validation, but where failure is not tied to the grammar but some other property of the results. For instance, with the identifier example given for
filterOut, it is reasonable to suggest that an identifier was expected, and a keyword is not a valid identifier: i.e. these components still make sense. WhereguardAgainstshines, however, is in scenarios where the expected alternatives, or the unexpected component itself distract from the cause of the error, or are irrelevant in some way. This might be becauseguardAgainstis checking some property of the data that is possible to encode in the grammar, but otherwise impractical, either because it is hard to maintain or generates poor error messages for the user.- pred
the predicate that is tested against the parser result, which also generates errors.
- returns
a parser that returns the result of this parser if it fails the predicate.
Suppose we are parsing a data-format for graphs, and a restriction has been placed that ensures that the numeric identifiers of each declared node must be ordered. This has, for whatever reason, been specified as a syntactic property of the data. This is possible to encode using context-sensitive parsing (since each new node can only be parsed according to the previous one), but is fairly difficult and impractical. Instead, when all the declarations have been read, a
guardAgainstcan be used to prevent mis-ordering:val node = integer val nodes = many(node).guardAgainst { case ns if ns.nonEmpty && ns.zip(ns.tail).exists { case (x, y) => x == y } => val Some((x, _)) = ns.zip(ns.tail).find { case (x, y) => x == y } Seq(s"node $x has been declared twice") case ns if ns.nonEmpty && ns.zip(ns.tail).exists { case (x, y) => x > y } => val Some((x, y)) = ns.zip(ns.tail).find { case (x, y) => x > y } Seq(s"nodes $x and $y are declared in the wrong order", "all nodes should be ordered") }
- Since
4.0.0
- Note
when this combinator fails (and not this parser itself), it will generate errors rooted at the start of the parse (as if
amendhad been used) and the caret will span the entire successful parse of this parser.- See also
filterNot, which is a basic version of this same combinator with no customised error message.filterOut, which is similar toguardAgainst, except it generates a reason for failure and not a specialised error.collectMsg, which is similar toguardAgainst, but can also transform the data on success.
Example: -
def
hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
-
def
hide: Parsley[A]
This combinator hides the expected component of errors generated by this parser.
This combinator hides the expected component of errors generated by this parser.
When this parser fails having not observably* consumed input, this combinator hides any error labels assigned to the expected item by any
labelcombinators, or indeed the base raw labels produced by the input consuming combinators themselves.This can be useful, say, for hiding whitespace labels, which are not normally useful information to include in an error message for whitespace insensitive grammars.
*a parser is said to observably consume input when error messages generated by a parser
poccur at a deeper offset thanporiginally started at. While this sounds like it is the same as "having consumed input" for the purposes of backtracking, they are disjoint concepts:- in
attempt(p),pcan observably consume input even though the wider parser does not consume input due to theattempt. - in
amend(p),pcan consume input and may not backtrack even though the consumption is not observable in the error message due to theamend.
- returns
a parser that does not produce an expected component on failure.
- Since
3.0.0
- See also
- in
-
final
def
isInstanceOf[T0]: Boolean
- Definition Classes
- Any
-
def
label(item: String): Parsley[A]
This combinator changes the expected component of any errors generated by this parser.
This combinator changes the expected component of any errors generated by this parser.
When this parser fails having not observably* consumed input, the expected component of the generated error message is set to be the given
item.*a parser is said to observably consume input when error messages generated by a parser
poccur at a deeper offset thanporiginally started at. While this sounds like it is the same as "having consumed input" for the purposes of backtracking, they are disjoint concepts:- in
attempt(p),pcan observably consume input even though the wider parser does not consume input due to theattempt. - in
amend(p),pcan consume input and may not backtrack even though the consumption is not observable in the error message due to theamend.
- item
the name to give to the expected component of any qualifying errors.
- returns
a parser that expects
itemon failure.
- Since
3.0.0
- in
-
final
def
ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
final
def
notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
final
def
notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
-
final
def
synchronized[T0](arg0: ⇒ T0): T0
- Definition Classes
- AnyRef
-
def
toString(): String
- Definition Classes
- AnyRef → Any
-
def
unexpected(msggen: (A) ⇒ String): Parsley[Nothing]
This combinator parses this parser and then fails, using the result of this parser to customise the unexpected component of the error message.
This combinator parses this parser and then fails, using the result of this parser to customise the unexpected component of the error message.
Similar to
unexpected, but first parses this parser: if it succeeded, then its resultxis used to form the unexpected component of the generated error by callingmsggen(x). If this parser fails, however, its error message will be returned untouched.- msggen
the generator function for error message, creating a message based on the result of this parser.
- returns
a parser that always fails, with the given generator used to produce an unexpected message if this parser succeeded.
- Note
this combinator will generate error messages rooted at the start of the previously successful parse of this parser, but only in terms of their position: the actual error is generated at the end of the parse, which means it takes priority over sibling errors. This is because the error concerns the whole parse (for caret) and morally starts where this parser started (as it caused the failure), however, if it had full
amend-like behaviour these errors would often disappear.
-
def
unexpectedWhen(pred: PartialFunction[A, String]): Parsley[A]
This combinator filters the result of this parser using the given partial-predicate, succeeding only when the predicate is undefined.
This combinator filters the result of this parser using the given partial-predicate, succeeding only when the predicate is undefined.
First, parse this parser. If it succeeds then take its result
xand test ifpred.isDefinedAt(x)is true. If it is false, the parser succeeds, returningx. Otherwise,pred(x)will yield a unexpected label and the parser will fail usingunexpectedand that label.This is useful for performing data validation, but where a the failure results in the entire token being unexpected. In this instance, the rest of the error message is generated as normal, with the expected components still given, along with any generated reasons.
- pred
the predicate that is tested against the parser result, which also generates errors.
- returns
a parser that returns the result of this parser if it fails the predicate.
scala> import parsley.character.letter scala> val keywords = Set("if", "then", "else") scala> val ident = stringOfSome(letter).unexpectedWhen { case v if keywords.contains(v) => s"keyword $v" } scala> ident.parse("hello") val res0 = Success("hello") scala> ident.parse("if") val res1 = Failure(..)
- Since
3.0.0
- Note
when this combinator fails (and not this parser itself), it will generate errors rooted at the start of the parse (as if
amendhad been used) and the caret will span the entire successful parse of this parser.- See also
filterNot, which is a basic version of this same combinator with no unexpected message.filterOut, which is a variant that produces a reason for failure as opposed to an unexpected message.guardAgainst, which is similar tounexpectedWhen, except it generates a specialised error as opposed to just a reason.
Example: -
final
def
wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... ) @native()
Error Enrichment Combinators
These combinators add additional information - or refine the existing information within - to an error message that has been generated within the scope of the parser they have been called on. These are a very basic, but effective, way of improving the quality of error messages generated by Parsley.
Filtering Combinators
These combinators perform filtering on a parser, with particular emphasis on generating meaningful
error messages if the filtering fails. This is particularly useful for data validation within the
parser, as very instructive error messages describing what went wrong can be generated. These combinators
often filter using a PartialFunction: this may be because they combine filtering with mapping (in which
case, the error message is provided separately), or the function may produce a String.
In these cases, the partial function is producing the error messages: if the input to the function is
defined, this means that it is invalid and the filtering will fail using the message obtained from the
succesful partial function invocation.
Failure Combinators
These combinator immediately fail the parser, with a more bespoke message.