A parse error is the failure value returned when input does not meet a parser’s expectation. Rather than merely saying that parsing failed, it carries enough information to identify where failure occurred and what was expected. A parser can therefore return either a successful value or a ParseError. section 9.1 section 9.5.1
Location matters because the useful question is not only “what failed?” but “where did it fail?” A Location can retain the full input and an offset, with line and column computed from them. A label assigns the reported message for a failing parser while leaving the implementation responsible for locating the failure. section 9.5.1
case class ParseError(stack: List[(Location, String)])
A ParseError can be represented as a stack of location/message pairs, preserving several levels of context instead of selecting one message. section 9.5.2
One message is often too little. A low-level failure can say that an uppercase character appeared where a lowercase one was expected, while enclosing parsers explain the larger task in progress. `scope` adds such context without discarding existing labels, so an error stack reads from a broad activity toward its immediate cause. section 9.5.2
A misspelled magic word
A parser for `abra` followed by `cadabra` can label the second word. Given `abra cAdabra`, the immediate failure is the capital `A`; the label “second magic word” explains its grammatical role. An outer scope can add an even broader description such as parsing a magic spell. section 9.5.2
Choice introduces a second question: which failure should be reported? If two alternatives fail, reporting every branch can obscure the most relevant cause. Once a branch has consumed input and established that it is the intended path, its failure can be committed; the other branch is not tried. `attempt` reverses that commitment when backtracking remains desirable. section 9.5.3
Useful error-reporting operations separate distinct responsibilities:
- `label(msg)` replaces the message associated with a failure while retaining its location. section 9.5.1
- `scope(msg)` prepends contextual information to an existing error stack. section 9.5.2
- Committed choice reports a failure after input consumption; `attempt` makes that failure backtrackable. section 9.5.3
- Formatting can collapse messages at identical locations, print line and column, and mark the failing character with a caret. section 9.8
Keeping errors as explicit values makes reporting a design concern rather than an incidental side effect. The parser algebra can specify laws for labels and scopes, while a later representation decides how locations, stacks, alternate failures, and human-readable formatting are implemented. section 9.5.1 section 9.8
