APIParser

Parser

Direct-style parsers over immutable lists of arbitrary tokens.

A parser is an ordinary function performing Parse token and Fail (Error token). Sequencing uses ordinary calls and bindings. Alternatives commit when they consume input; attempt explicitly permits backtracking. Only the private cursor is restored: IO and other effects performed by a failed branch remain visible. Nested runners are independent. Tokens may carry source spans; offsets here count tokens, not text bytes.

import Parser
import Result exposing (Result(..))

pair _ =
    left = Parser.satisfy "positive integer" { n -> n > 0 }
    right = Parser.any()
    (left, right)

Parser.runAll [2, 3] pair == Ok (2, 3)

Error

type Error token =    { offset : Int    , expected : List String    , reason : Reason token    }Source

A failure at a token boundary. The unexpected token can carry source spans; applications supply their own end-of-input position and rendering.

Fields

offset

offset : IntSource

Zero-based token offset, retained even when attempt rewinds.

expected

expected : List StringSource

Expected descriptions, in branch order with duplicates removed on ties.

reason

reason : Reason tokenSource

The mismatch, custom explanation, or invalid repetition.

Instances:

Eq token => Eq (Error token)
Show token => Show (Error token)

Parsed

type Parsed token value =    { value : value    , remaining : List token    , offset : Int    }Source

A successful prefix parse.

Fields

value

value : valueSource

The parser’s result.

remaining

remaining : List tokenSource

The unconsumed suffix of the original input.

offset

offset : IntSource

The number of consumed tokens.

Instances:

(Eq value, Eq token) => Eq (Parsed token value)
(Show token, Show value) => Show (Parsed token value)

Reason

type Reason token    = Unexpected (Maybe token)    | Message String    | NonProgressSource

Why parsing stopped.

Constructors

Unexpected

Unexpected : Maybe token -> Reason tokenSource

A mismatching token, or Nothing for end of input.

Message

Message : String -> Reason tokenSource

An application-supplied explanation.

NonProgress

NonProgress : Reason tokenSource

A repeated parser succeeded without advancing. This is an error in the grammar; combinators never recover from it, including attempt.

Instances:

Eq token => Eq (Reason token)
Show token => Show (Reason token)

Parse

effect Parse tokenSource

Permission to read one token stream. run and runAll handle it; its checkpoint operations are private to this module.

any

any : () ->{Fail (Error a), Parse a} aSource

Consumes one token, failing without consumption at end of input.

attempt

attempt : (() ->{Fail (Error a), Parse a, e} b) ->{Fail (Error a), Parse a, e} bSource

Restores the cursor on ordinary parse failure, preserving the diagnostic. Success retains consumption. Other effects are never undone; non-progress errors propagate without recovery.

between

between : (() ->{Fail (Error a), Parse a, e} ()) -> (() ->{Fail (Error a), Parse a, e} ()) -> (() ->{Fail (Error a), Parse a, e} b) ->{Fail (Error a), Parse a, e} bSource

Parses opening and closing delimiters around action, returning its value.

end

end : () ->{Fail (Error a), Parse a} ()Source

Succeeds only at end of input; consumes nothing.

fail

fail : String ->{Fail (Error a), Parse a} bSource

Fails at the current token boundary with an application-supplied message.

label

label : String -> (() ->{Fail (Error a), Parse a, e} b) ->{Fail (Error a), Parse a, e} bSource

Replaces expectations on a non-consuming mismatch at the starting offset. Deeper errors, custom messages, and non-progress errors retain their detail.

many

many : (() ->{Fail (Error a), Parse a, e} b) ->{Fail (Error a), Parse a, e} List bSource

Repeats until a non-consuming failure, returning values in input order. Consuming failures propagate. Empty success raises NonProgress.

offset

offset : () ->{Parse a} IntSource

The zero-based position of the next token.

optional

optional : (() ->{Fail (Error a), Parse a, e} b) ->{Fail (Error a), Parse a, e} Maybe bSource

Answers Nothing on a non-consuming failure, otherwise preserves success or propagates the failure.

orElse

orElse : (() ->{Fail (Error a), Parse a, e} b) -> (() ->{Fail (Error a), Parse a, e} b) ->{Fail (Error a), Parse a, e} bSource

Tries right only when left fails without net consumption. If both fail recoverably, keeps the farther error and combines tied expectations. A consuming failure wins immediately. On a tied custom error, the left wins.

import Parser
import Result exposing (Result(..))

ab _ = _ = Parser.token "a" 'a'; Parser.token "b" 'b'
ac _ = _ = Parser.token "a" 'a'; Parser.token "c" 'c'

Parser.runAll ['a', 'c'] { Parser.orElse { Parser.attempt ab } ac } == Ok 'c'

peek

peek : () ->{Parse a} Maybe aSource

The next token without consumption, or Nothing at the end.

run

run : List a -> (() ->{Fail (Error a), Parse a, e} b) ->{e} Result (Error a) (Parsed a b)Source

Parses a prefix and returns its value and remaining input. Parse failures become Err; ambient effects pass through without being rolled back.

runAll

runAll : List a -> (() ->{Fail (Error a), Parse a, e} b) ->{e} Result (Error a) bSource

Parses the complete input, failing if any token remains after action.

satisfy

satisfy : String -> (a -> Bool) ->{Fail (Error a), Parse a} aSource

Consumes the next token if the pure predicate accepts it. A mismatch leaves input untouched and expects description.

sepBy

sepBy : (() ->{Fail (Error a), Parse a, e} b) -> (() ->{Fail (Error a), Parse a, e} ()) ->{Fail (Error a), Parse a, e} List bSource

Zero or more values separated by a Unit-returning parser. A consumed separator must be followed by a value; trailing separators are rejected.

some

some : (() ->{Fail (Error a), Parse a, e} b) ->{Fail (Error a), Parse a, e} List bSource

Like many, but requires at least one value and progress on every success.

token

token : Eq a => String -> a ->{Fail (Error a), Parse a} aSource

Consumes a token equal to wanted, using the supplied expectation text.