liveBook · Manning

Parse error

As explained in Functional Programming in Scala, Second Edition

A parse error is a failure report identifying that input does not conform to the expectations of a parser, including its location and cause.

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

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Develops labels, locations, nested stacks, branch commitment, and formatting, then shows implementation-oriented error representations.
Examples
Uses failing `abra`/`cadabra` parsers, competing magic-spell and gibberish branches, and caret-formatted input locations.
What you can do after
Build it from scratch by representing failures, attaching context, controlling backtracking, and formatting diagnostic output.
How it connects
Connects ParseError to parser combinators, Location, label, scope, choice, backtracking, and attempt.

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.