nibble
Types
A dead end represents a the point where a parser that had committed down a
path failed. It contains the position of the failure, the Error
describing the failure, and the context stack for any parsers that had run.
pub type DeadEnd(tok, ctx) {
DeadEnd(
pos: Span,
problem: Error(tok),
context: List(Located(ctx)),
)
}
Constructors
-
DeadEnd( pos: Span, problem: Error(tok), context: List(Located(ctx)), )
pub type Error(tok) {
BadParser(String)
Custom(String)
EndOfInput
Expected(String, got: tok)
Unexpected(tok)
}
Constructors
-
BadParser(String)
-
Custom(String)
-
EndOfInput
-
Expected(String, got: tok)
-
Unexpected(tok)
pub type Located(ctx) {
Located(pos: Span, context: ctx)
}
Constructors
-
Located(pos: Span, context: ctx)
The Parser
type has three paramteres, let’s take a look at each of them:
Parser(a, tok, ctx)
// ^ (1)
// ^^^ (2)
// ^^^ (3)
-
a
is the type of value that the parser knows how to produce. If you were writing a parser for a programming language, this might be your expression type. -
tok
is the type of tokens that the parser knows how to consume. You can take a look at theToken
type for a bit more info, but note that it’s not necessary for the token stream to come from nibble’s lexer. -
ctx
is used to make error reporting nicer. You can place a parser into a custom context. When the parser runs the context gets pushed into a stack. If the parser fails you can see the context stack in the error message, which can make error reporting and debugging much easier!
pub opaque type Parser(a, tok, ctx)
Functions
pub fn backtrackable(parser: Parser(a, b, c)) -> Parser(a, b, c)
pub fn do_in(context: a, parser: Parser(b, c, a), f: fn(b) ->
Parser(d, c, a)) -> Parser(d, c, a)
pub fn inspect(parser: Parser(a, b, c), message: String) -> Parser(
a,
b,
c,
)
Run the given parser and then inspect it’s state.
pub fn list(parser: Parser(a, b, c), separator sep: Parser(
d,
b,
c,
)) -> Parser(List(a), b, c)
pub fn run(src: List(Token(a)), parser: Parser(b, a, c)) -> Result(
b,
List(DeadEnd(a, c)),
)
pub fn take_map_while(f: fn(a) -> Option(b)) -> Parser(
List(b),
a,
c,
)
pub fn take_map_while1(expecting: String, f: fn(a) -> Option(b)) -> Parser(
List(b),
a,
c,
)
pub fn take_until(predicate: fn(a) -> Bool) -> Parser(
List(a),
a,
b,
)
pub fn take_until1(expecting: String, predicate: fn(a) -> Bool) -> Parser(
List(a),
a,
b,
)
pub fn take_while(predicate: fn(a) -> Bool) -> Parser(
List(a),
a,
b,
)
💡 This parser can succeed without consuming any input (if the predicate
immediately fails). You can end up with an infinite loop if you’re not
careful. Use take_while1
if you want to guarantee you
take at least one token.
pub fn take_while1(expecting: String, predicate: fn(a) -> Bool) -> Parser(
List(a),
a,
b,
)
💡 If this parser succeeds, the list produced is guaranteed to be non-empty.
let assert
away!