liveBook · Manning

Or combinator

As explained in Functional Programming in Scala, Second Edition

The or combinator runs a second parser when the first parser fails without consuming committed input, and otherwise returns the first parser's result.

The or combinator tries a first parser and runs a second parser on the same input only when the first fails without commitment. A successful first parser, or a committed failure, ends the choice immediately. This makes branching both controllable and more efficient than blindly exploring every alternative. section 9.6.4

Choosing between two phrases

Let p1 parse “abra cadabra” and p2 parse “abba babba”; p1 | p2 first tries the magic-spell branch. If p1 fails before consuming input, p2 gets the same input. If p1 has consumed input and then fails, the failure is reported without trying p2. Thus an input such as “abra cAdabra” can preserve the more informative failure from the selected branch. section 9.5.3

Implementations represent a failure with both a ParseError and an isCommitted flag. The or combinator inspects that flag; attempt converts committed failures into uncommitted failures, allowing another branch to run when the parser should not yet have committed. section 9.6.4

extension [A](p: Parser[A]) def or(p2: => Parser[A]): Parser[A] =
  l => p(l) match
    case Failure(e, false) => p2(s)
    case r => r                     #1

Inspect the compact implementation that preserves successes and committed failures while invoking the second parser only for uncommitted failures. section 9.6.4

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Defines branching through commitment flags and shows implementation-level interaction with attempt and Result.
Examples
Uses magic-spell and gibberish parsers to contrast informative committed errors with fallback alternatives.
What it assumes
Assumes parser results and failures, while introducing committed state through the behavior of or and attempt.
What you can do after
Apply it via parser combinators to select alternatives while preserving deliberate commitment and useful parse errors.
How it connects
Connects parser alternatives with backtracking, committed failure, uncommitted failure, attempt, ParseError, and Result.

Related concepts

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.