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
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
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.
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.
