6.2 FParsec.Primitives

6.2.1 Interface

// FParsec.dll

[<AutoOpen>] // module is automatically opened when FParsec namespace is opened
module FParsec.Primitives

[<Literal>] val Ok:         ReplyStatus = ReplyStatus.Ok
[<Literal>] val Error:      ReplyStatus = ReplyStatus.Error
[<Literal>] val FatalError: ReplyStatus = ReplyStatus.FatalError


type Parser<'TResult, 'TUserState> = CharStream<'TUserState> -> Reply<'TResult>


// Two basic primitives that are only seldomly directly used in user code:
val preturn: 'a -> Parser<'a,'u>
val pzero: Parser<'a,'u>


// Chaining and piping parsers
// ==============================
val (>>=):  Parser<'a,'u> -> ('a -> Parser<'b,'u>) -> Parser<'b,'u>

val (>>%):   Parser<'a,'u> -> 'b -> Parser<'b,'u>
val (>>.):   Parser<'a,'u> -> Parser<'b,'u> -> Parser<'b,'u>
val (.>>):   Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a,'u>
val (.>>.):  Parser<'a,'u> -> Parser<'b,'u> -> Parser<('a * 'b),'u>
val between: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'c,'u>

val (|>>): Parser<'a,'u> -> ('a -> 'b) -> Parser<'b,'u>

val pipe2: Parser<'a,'u> -> Parser<'b,'u> -> ('a -> 'b -> 'c) -> Parser<'c,'u>

val pipe3: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u>
           -> ('a -> 'b -> 'c -> 'd) -> Parser<'d,'u>

val pipe4: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'d,'u>
           -> ('a -> 'b -> 'c -> 'd -> 'e) -> Parser<'e,'u>

val pipe5: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'d,'u>
           -> Parser<'e,'u>
           -> ('a -> 'b -> 'c -> 'd -> 'e -> 'f) -> Parser<'f,'u>


// Parsing alternatives and recovering from errors
// ===============================================
val (<|>):       Parser<'a,'u>  -> Parser<'a,'u> -> Parser<'a,'u>
val choice:  seq<Parser<'a,'u>> -> Parser<'a,'u>
val choiceL: seq<Parser<'a,'u>> -> string -> Parser<'a,'u>

val (<|>%):   Parser<'a,'u> -> 'a -> Parser<'a,'u>
val opt:      Parser<'a,'u> -> Parser<'a option,'u>
val optional: Parser<'a,'u> -> Parser<unit,'u>

val attempt: Parser<'a,'u> -> Parser<'a,'u>

val (>>=?): Parser<'a,'u> -> ('a -> Parser<'b,'u>) -> Parser<'b,'u>
val (>>?):  Parser<'a,'u> -> Parser<'b,'u> -> Parser<'b,'u>
val (.>>?): Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a,'u>
val (.>>.?): Parser<'a,'u> -> Parser<'b,'u> -> Parser<('a * 'b),'u>


// Conditional parsing and looking ahead
// =====================================
val notEmpty: Parser<'a,'u> -> Parser<'a,'u>

val followedBy:     Parser<'a,'u> -> Parser<unit,'u>
val followedByL:    Parser<'a,'u> -> string -> Parser<unit,'u>
val notFollowedBy:  Parser<'a,'u> -> Parser<unit,'u>
val notFollowedByL: Parser<'a,'u> -> string -> Parser<unit,'u>

val lookAhead: Parser<'a,'u> -> Parser<'a,'u>


// Customizing error messages
// ==========================
val (<?>):  Parser<'a,'u> -> string -> Parser<'a,'u>
val (<??>): Parser<'a,'u> -> string -> Parser<'a,'u>

val fail:        string -> Parser<'a,'u>
val failFatally: string -> Parser<'a,'u>


// Parsing sequences
// =================
val tuple2: Parser<'a,'u> -> Parser<'b,'u> -> Parser<('a * 'b),'u>
val tuple3: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u>
            -> Parser<('a * 'b * 'c),'u>
val tuple4: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'d,'u>
            -> Parser<('a * 'b * 'c * 'd),'u>
val tuple5: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'d,'u>
            -> Parser<'e,'u> -> Parser<('a * 'b * 'c * 'd * 'e),'u>

val parray:    int -> Parser<'a,'u> -> Parser<'a[],'u>
val skipArray: int -> Parser<'a,'u> -> Parser<unit,'u>

val many:      Parser<'a,'u> -> Parser<'a list,'u>
val many1:     Parser<'a,'u> -> Parser<'a list,'u>
val skipMany:  Parser<'a,'u> -> Parser<unit,'u>
val skipMany1: Parser<'a,'u> -> Parser<unit,'u>

val sepBy:         Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>
val sepBy1:        Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>
val skipSepBy:     Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>
val skipSepBy1:    Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>

val sepEndBy:      Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>
val sepEndBy1:     Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>
val skipSepEndBy:  Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>
val skipSepEndBy1: Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>

val manyTill:      Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>
val many1Till:     Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>
val skipManyTill:  Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>
val skipMany1Till: Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>

[<CompilationRepresentationFlags.Static>]
type Inline =
  static member inline Many: stateFromFirstElement: ('T -> 'State)
                           * foldState: ('State -> 'T -> 'State)
                           * resultFromState: ('State -> 'Result)
                           * elementParser: Parser<'T,'U>
                           * ?firstElementParser: Parser<'T,'U>
                           * ?resultForEmptySequence: (unit -> 'Result)
                          -> Parser<'Result,'U>

  static member inline SepBy: stateFromFirstElement: ('T -> 'State)
                            * foldState: ('State -> 'Separator -> 'T -> 'State)
                            * resultFromState: ('State -> 'Result)
                            * elementParser: Parser<'T,'U>
                            * separatorParser: Parser<'Separator,'U>
                            * ?firstElementParser: Parser<'T,'U>
                            * ?resultForEmptySequence: (unit -> 'Result)
                            * ?separatorMayEndSequence: bool
                           -> Parser<'Result,'U>

  static member inline ManyTill: stateFromFirstElement: ('T -> 'State)
                               * foldState: ('State -> 'T -> 'State)
                               * resultFromStateAndEnd: ('State -> 'E -> 'Result)
                               * elementParser: Parser<'T,'U>
                               * endParser: Parser<'E,'U>
                               * ?firstElementParser: Parser<'T,'U>
                               * ?resultForEmptySequence: ('E -> 'Result)
                              -> Parser<'Result,'U>

val chainl1: Parser<'a,'u> -> Parser<('a -> 'a -> 'a),'u>       -> Parser<'a,'u>
val chainl:  Parser<'a,'u> -> Parser<('a -> 'a -> 'a),'u> -> 'a -> Parser<'a,'u>
val chainr1: Parser<'a,'u> -> Parser<('a -> 'a -> 'a),'u>       -> Parser<'a,'u>
val chainr:  Parser<'a,'u> -> Parser<('a -> 'a -> 'a),'u> -> 'a -> Parser<'a,'u>


// Building parsers using F#'s computation expression syntax
type ParserCombinator = // ...
val parse: ParserCombinator

// Building mutually recursive parser values
val createParserForwardedToRef: unit -> Parser<'a,'u> * Parser<'a,'u> ref

6.2.2 Members

[<Literal>] val Ok: ReplyStatus = ReplyStatus.Ok

This ReplyStatus value indicates that a parser succeeded.

[<Literal>] val Error: ReplyStatus = ReplyStatus.Error

This ReplyStatus value indicates that a parser failed.

[<Literal>] val FatalError: ReplyStatus = ReplyStatus.FatalError

This ReplyStatus value indicates that a parser failed and no error recovery (except after backtracking) should be tried.

type Parser<'TResult, 'TUserState> = CharStream<'TUserState> -> Reply<'TResult>

The type of the parser functions supported throughout the FParsec library.

val preturn: 'a -> Parser<'a,'u>

The parser preturn x always succeeds with the result x (without changing the parser state).

preturn x is defined as fun stream -> Reply(x).

val pzero: Parser<'a,'u>

The parser pzero always fails with an empty error message list, i.e. an unspecified error.

pzero x is defined as fun stream -> Reply(Error, NoErrorMessage).

val (>>=): Parser<'a,'u> -> ('a -> Parser<'b,'u>) -> Parser<'b,'u>

The parser p >>= f first applies the parser p to the input, then applies the function f to the result returned by p and finally applies the parser returned by f to the input.

Note

Please see the user’s guide chapter Applying parsers in sequence for an in‐depth discussion of the behaviour of this and other sequencing combinators.

The >>= combinator is the conceptual foundation for all combinators that consecutively apply multiple parsers to the input. In order to precisely define its behaviour we give an equivalent definition:

let (>>=) (p: Parser<'a,'u>) (f: 'a -> Parser<'b,'u>) =
    fun stream ->
        let reply1 = p stream
        if reply1.Status = Ok then
            let p2 = f reply1.Result
            let stateTag = stream.StateTag
            let mutable reply2 = p2 stream
            if stateTag = stream.StateTag then
                reply2.Error <- mergeErrors reply1.Error reply2.Error
            reply2
        else
            Reply(reply1.Status, reply1.Error)
val (>>%): Parser<'a,'u> -> 'b -> Parser<'b,'u>

The parser p >>% x applies the parser p and returns the result x.

p >>% x is an optimized implementation of p >>= fun _ -> preturn x.

val (>>.): Parser<'a,'u> -> Parser<'b,'u> -> Parser<'b,'u>

The parser p1 >>. p2 applies the parsers p1 and p2 in sequence and returns the result of p2.

p1 >>. p2 is an optimized implementation of p1 >>= fun _ -> p2.

val (.>>): Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a,'u>

The parser p1 .>> p2 applies the parsers p1 and p2 in sequence and returns the result of p1.

p1 .>> p2 is an optimized implementation of p1 >>= fun x -> p2 >>% x.

val (.>>.): Parser<'a,'u> -> Parser<'b,'u> -> Parser<('a * 'b),'u>

The parser p1 .>>. p2 applies the parsers p1 and p2 in sequence and returns the results in a tuple.

p1 .>>. p2 is an optimized implementation of

p1 >>= fun a ->
p2 >>= fun b -> preturn (a, b)
val between: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'c,'u>

The parser between popen pclose p applies the parsers pOpen, p and pEnd in sequence. It returns the result of p.

between popen pclose p is an optimized implementation of popen >>. p .>> pclose.

val (|>>): Parser<'a,'u> -> ('a -> 'b) -> Parser<'b,'u>

The parser p |>> f applies the parser p and returns the result of the function application f x, where x is the result returned by p.

p |>> f is an optimized implementation of p >>= fun x -> preturn (f x).

val pipe2: Parser<'a,'u> -> Parser<'b,'u> -> ('a -> 'b -> 'c) -> Parser<'c,'u>

The parser pipe2 p1 p2 f applies the parsers p1 and p2 in sequence. It returns the result of the function application f a b, where a and b are the results returned by p1 and p2.

pipe2 p1 p2 f is an optimized implementation of

p1 >>= fun a ->
p2 >>= fun b -> preturn (f a b)
val pipe3: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u>
           -> ('a -> 'b -> 'c -> 'd) -> Parser<'d,'u>

The parser pipe3 p1 p2 p3 f applies the parsers p1, p2 and p3 in sequence. It returns the result of the function application f a b c, where a, b and c are the results returned by p1, p2 and p3.

pipe3 p1 p2 p3 f is an optimized implementation of

p1 >>= fun a ->
p2 >>= fun b ->
p3 >>= fun c -> preturn (f a b c)
val pipe4: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'d,'u>
           -> ('a -> 'b -> 'c -> 'd -> 'e) -> Parser<'e,'u>

The parser pipe4 p1 p2 p3 p4 f applies the parsers p1, p2, p3 and p4 in sequence. It returns the result of the function application f a b c d, where a, b, c and d are the results returned by p1, p2, p3 and p4.

pipe4 p1 p2 p3 p4 f is an optimized implementation of

p1 >>= fun a ->
p2 >>= fun b ->
p3 >>= fun c ->
p4 >>= fun d -> preturn (f a b c d)
val pipe5: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'d,'u>
           -> Parser<'e,'u>
           -> ('a -> 'b -> 'c -> 'd -> 'e -> 'f) -> Parser<'f,'u>

The parser pipe5 p1 p2 p3 p4 p5 f applies the parsers p1, p2, p3, p4 and p5 in sequence. It returns the result of the function application f a b c d e, where a, b, c, d and e are the results returned by p1, p2, p3, p4 and p5.

pipe5 p1 p2 p3 p4 p5 f is an optimized implementation of

p1 >>= fun a ->
p2 >>= fun b ->
p3 >>= fun c ->
p4 >>= fun d ->
p5 >>= fun e -> preturn (f a b c d e)
val (<|>): Parser<'a,'u> -> Parser<'a,'u> -> Parser<'a,'u>

The parser p1 <|> p2 first applies the parser p1. If p1 succeeds, the result of p1 is returned. If p1 fails with a non‐fatal error and without changing the parser state, the parser p2 is applied. Note: The stream position is part of the parser state, so if p1 fails after consuming input, p2 will not be applied.

The choice combinator is a generalization of <|> to more than two parsers.

Note

Please see the user’s guide chapter on Parsing alternatives for an in‐depth discussion of the behaviour of this combinator.

val choice: seq<Parser<'a,'u>> -> Parser<'a,'u>

The parser choice ps is an optimized implementation of p1 <|> p2 <|> ... <|> pn , where p1pn are the parsers in the sequence ps.

choice [p] is equivalent to p.
choice [] is equivalent to pzero.

val choiceL: seq<Parser<'a,'u>> -> string -> Parser<'a,'u>

The parser choiceL ps label is an optimized implementation of choice ps <?> label.

choiceL is slightly faster than choice, because it doesn’t have to aggregate error messages.

val (<|>%): Parser<'a,'u> -> 'a -> Parser<'a,'u>

The parser p <|>% x is an optimized implementation of p <|> preturn x.

val opt: Parser<'a,'u> -> Parser<'a option,'u>

The parser opt p parses an optional occurrence of p as an option value.

opt p is an optimized implementation of (p |>> Some) <|>% None.

val optional: Parser<'a,'u> -> Parser<unit,'u>

The parser optional p skips over an optional occurrence of p.

optional p is an optimized implementation of (p >>% ()) <|>% ().

val attempt: Parser<'a,'u> -> Parser<'a,'u>

The parser attempt p applies the parser p. If p fails after changing the parser state or with a fatal error, attempt p will backtrack to the original parser state and report a non‐fatal error.

val (>>=?): Parser<'a,'u> -> ('a -> Parser<'b,'u>) -> Parser<'b,'u>

The parser p >>=? f behaves like p >>= f, except that it will backtrack to the beginning if the parser returned by f fails with a non‐fatal error and without changing the parser state, even if p1 has changed the parser state.

val (>>?): Parser<'a,'u> -> Parser<'b,'u> -> Parser<'b,'u>

The parser p1 >>? p2 behaves like p1 >>. p2, except that it will backtrack to the beginning if p2 fails with a non‐fatal error and without changing the parser state, even if p1 has changed the parser state.

val (.>>?): Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a,'u>

The parser p1 .>>? p2 behaves like p1 .>> p2, except that it will backtrack to the beginning if p2 fails with a non‐fatal error and without changing the parser state, even if p1 has changed the parser state.

val (.>>.?): Parser<'a,'u> -> Parser<'b,'u> -> Parser<('a * 'b),'u>

The parser p1 .>>.? p2 behaves like p1 .>>. p2, except that it will backtrack to the beginning if p2 fails with a non‐fatal error and without changing the parser state, even if p1 has changed the parser state.

val notEmpty: Parser<'a,'u> -> Parser<'a,'u>

The parser notEmpty p behaves like p, except that it fails when p succeeds without consuming input or changing the parser state in any other way.

notEmpty is useful for forcing sequence parsers to consume input. For example, notEmpty (manySatisfy f) behaves like many1Satisfy f.

val followedBy: Parser<'a,'u> -> Parser<unit,'u>

The parser followedBy p succeeds if the parser p succeeds at the current position. Otherwise it fails with a non‐fatal error. This parser never changes the parser state.

If the parser followedBy p fails, it returns no descriptive error message. Hence it should only be used together with other parsers that take care of a potential error. Alternatively, followedByL p label can be used to ensure a more descriptive error message.

val followedByL: Parser<'a,'u> -> string -> Parser<unit,'u>

The parser followedByL p behaves like followedBy p, except that it returns an Expected label error message when the parser p fails.

val notFollowedBy: Parser<'a,'u> -> Parser<unit,'u>

The parser notFollowedBy p succeeds if the parser p fails to parse at the current position. Otherwise it fails with a non‐fatal error. This parser never changes the parser state.

If the parser notFollowedBy p fails, it returns no descriptive error message. Hence it should only be used together with other parsers that take care of a potential error. Alternatively, notFollowedByL p label can be used to ensure a more descriptive error message.

val notFollowedByL: Parser<'a,'u> -> string -> Parser<unit,'u>

The parser notFollowedByL p behaves like notFollowedBy p, except that it returns an Unexpected label error message when the parser p fails.

val lookAhead: Parser<'a,'u> -> Parser<'a,'u>

The parser lookAhead p parses p and restores the original parser state afterwards. If p fails after changing the parser state, the error messages are wrapped in a NestedError. If it succeeds, any error messages are discarded. Fatal errors are turned into normal errors.

val (<?>): Parser<'a,'u> -> string -> Parser<'a,'u>

The parser p <?> label applies the parser p. If p does not change the parser state (usually because p failed), the error messages are replaced with expected label.

Please also see the user’s guide chapter on customizing error messages.

val (<??>): Parser<'a,'u> -> string -> Parser<'a,'u>

The parser p <??> label behaves like p <?> label, except that when p fails after changing the parser state (for example, because p consumes input before it fails), a CompoundError message is generated with both the given string label and the error messages generated by p.

Please also see the user’s guide chapter on customizing error messages.

val fail: string -> Parser<'a,'u>

The parser fail msg always fails with a messageError msg. The string msg will be displayed together with other error messages generated for the same input position.

fail msg is equivalent to fun stream -> Reply(Error, messageError msg).

val failFatally: string -> Parser<'a,'u>

The parser failFatally msg always fails with a messageError msg. It returns with a FatalError, so that no error recovery is attempted (except via backtracking constructs).

failFatally msg is equivalent to fun stream -> Reply(FatalError, messageError msg).

val tuple2: Parser<'a,'u> -> Parser<'b,'u> -> Parser<('a * 'b),'u>

The parser tuple2 p1 p2 applies the parsers p1 and p2 in sequence and returns the results in a tuple.

tuple2 p1 p2 is defined as p1 .>>. p2 and is equivalent to pipe2 p1 p2 (fun a b -> (a, b)).

val tuple3: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u>
            -> Parser<('a * 'b * 'c),'u>

The parser tuple3 p1 p2 p3 applies the parsers p1, p2 and p3 in sequence and returns the results in a tuple.

tuple3 p1 p2 p3 is equivalent to pipe3 p1 p2 p3 (fun a b c -> (a, b, c)).

val tuple4: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'d,'u>
            -> Parser<('a * 'b * 'c * 'd),'u>

The parser tuple4 p1 p2 p3 p4 applies the parsers p1, p2, p3 and p4 in sequence and returns the results in a tuple.

tuple4 p1 p2 p3 p4 is equivalent to pipe4 p1 p2 p3 p4 (fun a b c d -> (a, b, c, d)).

val tuple5: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'d,'u>
            -> Parser<'e,'u> -> Parser<('a * 'b * 'c * 'd * 'e),'u>

The parser tuple5 p1 p2 p3 p4 p5 applies the parsers p1, p2, p3, p4 and p5 in sequence and returns the results in a tuple.

tuple5 p1 p2 p3 p4 p5 is equivalent to pipe5 p1 p2 p3 p4 p5 (fun a b c d e -> (a, b, c, d, e)).

val parray: int -> Parser<'a,'u> -> Parser<'a[],'u>

The parser parray n p parses n occurrences of p and returns the results in an array.

For example, parray 3 p is equivalent to pipe3 p p p (fun a b c -> [|a;b;c|]).

val skipArray: int -> Parser<'a,'u> -> Parser<unit,'u>

The parser skipArray n p is an optimized implementation of parray n p |>> ignore.

val many: Parser<'a,'u> -> Parser<'a list,'u>

The parser many p repeatedly applies the parser p until p fails. It returns a list of the results returned by p. At the end of the sequence p must fail without changing the parser state and without signalling a FatalError, otherwise many p will fail with the error reported by p.

many p tries to guard against an infinite loop by raising an exception if p succeeds without changing the parser state.

Ignoring efficiency issues, stack space usage and the infinite recursion case, many could be defined as follows:

let rec many p =
    (p >>= fun hd ->
               many p
               |>> fun tl -> hd::tl)
    <|>% []
val many1: Parser<'a,'u> -> Parser<'a list,'u>

The parser many1 p behaves like many p, except that it requires p to succeed at least one time.

many1 p is equivalent to pipe2 p (many p) (fun hd tl -> hd::tl).

val skipMany: Parser<'a,'u> -> Parser<unit,'u>

The parser skipMany p is an optimized implementation of many p |>> ignore.

val skipMany1: Parser<'a,'u> -> Parser<unit,'u>

The parser skipMany1 p is an optimized implementation of many1 p |>> ignore.

val sepBy: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>

The parser sepBy p sep parses zero or more occurrences of p separated by sep (in EBNF: (p (sep p)*)?). It returns a list of the results returned by p.

sepBy p sep is almost equivalent to pipe2 p (many (sep >>. p)) (fun hd tl -> hd::tl) <|>% [], except with regard to a case rarely encountered in practice: If sep succeeds without changing the parser state and p then fails without changing the state, then sepBy p sep fails too, while the parser given by the almost equivalent definition would succeed.

val sepBy1: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>

The parser sepBy1 p sep parses one or more occurrences of p separated by sep (in EBNF: p (sep p)*).

The parser sepBy1 p behaves like sepBy p, except that it requires p to succeed at least one time. Hence, if sepBy1 succeeds, the returned list always contains at least one value.

val skipSepBy: Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>

The parser skipSepBy p sep is an optimized implementation of sepBy p sep |>> ignore.

val skipSepBy1: Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>

The parser skipSepBy1 p sep is an optimized implementation of sepBy1 p sep |>> ignore.

val sepEndBy: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>

The parser sepEndBy p sep parses zero or more occurrences of p separated and optionally ended by sep (in EBNF: (p (sep p)* sep?)?). It returns a list of the results returned by p.

sepEndBy p sep tries to guard against an infinite loop by raising an exception if p and sep succeed without changing the parser state.

Ignoring efficiency issues, stack space usage and the infinite recursion case, sepEndBy could be defined as follows:

let rec sepEndBy p sep =
    (p >>= fun hd ->
               sep >>. sepEndBy p sep <|>% []
               |>> fun tl -> hd::tl)
    <|>% []
val sepEndBy1: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>

The parser sepEndBy1 p sep parses one or more occurrences of p separated and optionally ended by sep (in EBNF: p (sep p)* sep?). It returns a list of the results returned by p.

The parser sepEndBy1 p behaves like sepEndBy p, except that it requires p to succeed at least one time. Hence, if sepEndBy1 succeeds, the returned list always contains at least one value.

val skipSepEndBy: Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>

The parser skipSepEndBy p sep is an optimized implementation of sepEndBy p sep |>> ignore.

val skipSepEndBy1: Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>

The parser skipSepEndBy1 p sep is an optimized implementation of sepEndBy1 p sep |>> ignore.

val manyTill: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>

The parser manyTill p endp repeatedly applies the parser p for as long as endp fails (without changing the parser state). It returns a list of the results returned by p.

manyTill p endp is an optimized variant of many (notFollowedBy endp >>. p) .>> endp that doesn’t have to apply endp twice at the end of the sequence and that fails with the error reported by endp if endp fails after changing the parser state.

val many1Till: Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>

The parser many1Till p endp behaves like manyTill p endp, except that it requires p to succeed at least one time.

many1Till p endp is an optimized implementation of pipe2 p (manyTill p endp) (fun hd tl -> hd::tl).

val skipManyTill: Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>

The parser skipManyTill p endp is an optimized implementation of manyTill p endp |>> ignore.

val skipMany1Till: Parser<'a,'u> -> Parser<'b,'u> -> Parser<unit,'u>

The parser skipMany1Till p endp is an optimized implementation of many1Till p endp |>> ignore.

[<CompilationRepresentationFlags.Static>]
type Inline =

Inline is a static class that contains the following inline helper methods for defining optimized sequence parsers:

static member inline Many: stateFromFirstElement: ('T -> 'State)
                         * foldState: ('State -> 'T -> 'State)
                         * resultFromState: ('State -> 'Result)
                         * elementParser: Parser<'T,'U>
                         * ?firstElementParser: Parser<'T,'U>
                         * ?resultForEmptySequence: (unit -> 'Result)
                        -> Parser<'Result,'U>

Inline.Many is an inline helper method for defining optimized sequence parsers.

Inline.Many(stateFromFirstElement, foldState, resultFromState, elementParser) expands to an optimized implementation of

many1 elementParser // requires at least 1 element
|>> function hd::tl ->
    resultFromState (List.fold foldState (stateFromFirstElement hd) tl)
Note

The 'State argument to the foldState function is completely independent of FParsec’s usual parser state. The term “accumulator” would be a more accurate name for the argument, but that is just too unwieldy to use in the method signature.

If you pass a value for the optional argument resultForEmptySequence, the parser expands to an optimized implementation of

many elementParser // accepts empty sequence
|>> function
    | [] -> resultForEmptySequence()
    | hd::tl -> resultFromState (List.fold foldState (stateFromFirstElement hd) tl)

If you pass a value for the optional argument firstElementParser, the first element of the sequence will be parsed with firstElementParser instead of elementParser.

The following example shows how you can use Inline.Many to define an optimized parser that behaves like many1 p |>> List.reduce f but avoids the temporary allocation of a list:

let many1Reduce p f =
    Inline.Many(elementParser = p,
                stateFromFirstElement = (fun x0 -> x0),
                foldState = (fun acc y -> f acc y),
                resultFromState = (fun acc -> acc))

A simple test run:

> run (many1Reduce (pint32 .>> spaces) (+)) "1 2 3";;
val it : ParserResult<int32,unit> = Success: 6

The following example shows how you can use Inline.Many to create an optimized sequence parser that returns an array instead of a list:

let manyA2 p1 p =
    Inline.Many(firstElementParser = p1,
                elementParser = p,
                stateFromFirstElement = (fun x0 ->
                                             let ra = ResizeArray<_>()
                                             ra.Add(x0)
                                             ra),
                foldState = (fun ra x -> ra.Add(x); ra),
                resultFromState = (fun ra -> ra.ToArray()),
                resultForEmptySequence = (fun () -> [||]))

let manyA p = manyA2 p p

Two simple test runs:

> run (manyA (pint32 .>> spaces)) "";;
val it : ParserResult<int32 [],unit> = Success: [||]
> run (manyA (pint32 .>> spaces)) "1 2 3";;
val it : ParserResult<int32 [],unit> = Success: [|1; 2; 3|]
static member inline SepBy: stateFromFirstElement: ('T -> 'State)
                          * foldState: ('State -> 'Separator -> 'T -> 'State)
                          * resultFromState: ('State -> 'Result)
                          * elementParser: Parser<'T,'U>
                          * separatorParser: Parser<'Separator,'U>
                          * ?firstElementParser: Parser<'T,'U>
                          * ?resultForEmptySequence: (unit -> 'Result)
                          * ?separatorMayEndSequence: bool
                         -> Parser<'Result,'U>

Inline.SepBy is an inline helper method for defining optimized sequence parsers. By default, parsers defined with Inline.SepBy parse sequences of the form (in EBNF): element (separator element)*

Inline.SepBy(stateFromFirstElement, foldState, resultFromState, elementParser, separatorParser) expands to an optimized implementation of

pipe2 elementParser (many (separatorParser .>>. elementParser))
      (fun elem0 sepsAndElems ->
          sepsAndElems
          |> List.fold (fun acc (sep, e) -> foldState acc sep e)
                       (stateFromFirstElement elem0)
          |> resultFromState)

For most practical purposes the behaviour of the expanded Inline.SepBy parser and the above definition based on many can be considered equivalent, but there is a fringe case where the behaviour differs: If separatorParser succeeds without changing the parser state and elementParser then fails without changing the parser state, then the Inline.SepBy parser fails too, while the parser given by the definition based on many would succeed.

Note

The 'State argument to the foldState function is completely independent of FParsec’s usual parser state. The term “accumulator” would be a more accurate name for the argument, but that is just too unwieldy to use in the method signature.

If you pass true as the value for the optional argument separatorMayEndSequence, a separator may also end the sequence, i.e. the parser will accept sequences of the following form (in EBNF):

element (separator element)* separator?

Note that foldState is not called with the value of an ending separator.

If you pass a value for the optional argument resultForEmptySequence, the parser returned by Inline.SepBy will call resultForEmptySequence to create the parser result when it encounters an empty sequence. If you don’t pass a resultForEmptySequence function, the parser will fail for an empty sequence.

If you pass a value for the optional argument firstElementParser, the first element of a sequence will be parsed with firstElementParser instead of elementParser.

The following example shows how you can use Inline.SepBy to define an optimized parser that behaves like sepBy1 p sep |>> List.reduce f but avoids the temporary allocation of a list:

let sepBy1Reduce p sep f =
    Inline.SepBy(elementParser = p,
                 separatorParser = sep,
                 stateFromFirstElement = (fun x0 -> x0),
                 foldState = (fun acc _ y -> f acc y),
                 resultFromState = (fun acc -> acc))

A simple test run:

> run (sepBy1Reduce pint32 (pstring "," >>. spaces) (+)) "1, 2, 3";;
val it : ParserResult<int32,unit> = Success: 6

The following example shows how one could define CharParsers.stringsSepBy using Inline.SepBy:

let stringsSepBy p sep =
    Inline.SepBy(elementParser = p,
                 separatorParser = sep,
                 stateFromFirstElement =
                     (fun str -> let sb = System.Text.StringBuilder()
                                 sb.Append(str : string)),
                                 // sb.Append returns sb
                 foldState =
                     (fun sb sep str -> sb.Append(sep : string)
                                          .Append(str : string)),
                 resultFromState = (fun sb -> sb.ToString()))

let testParser : Parser<string,unit> =
    stringsSepBy (manySatisfy isLetter) (pstring @"\\" >>% @"\")
> run testParser "";;
val it : ParserResult<string,unit> = Success: ""
> run testParser @"abc\\def\\\\";;
val it : ParserResult<string,unit> = Success: "abc\def\\"
static member inline ManyTill: stateFromFirstElement: ('T -> 'State)
                             * foldState: ('State -> 'T -> 'State)
                             * resultFromStateAndEnd: ('State -> 'E -> 'Result)
                             * elementParser: Parser<'T,'U>
                             * endParser: Parser<'E,'U>
                             * ?firstElementParser: Parser<'T,'U>
                             * ?resultForEmptySequence: ('E -> 'Result)
                            -> Parser<'Result,'U>

Inline.ManyTill is an inline helper method for defining optimized sequence parsers.

Inline.ManyTill(stateFromFirstElement, foldState, resultFromState, elementParser, endParser) expands to an optimized implementation of

many1Till elementParser endParser // requires at least 1 element
|>> function hd::tl ->
    resultFromState (List.fold foldState (stateFromFirstElement hd) tl)
Note

The 'State argument to the foldState function is completely independent of FParsec’s usual parser state. The term “accumulator” would be a more accurate name for the argument, but that is just too unwieldy to use in the method signature.

If you pass a value for the optional argument resultForEmptySequence, the parser expands to an optimized implementation of

manyTill elementParser endParser // accepts empty sequence
|>> function
    | [] -> resultForEmptySequence()
    | hd::tl -> resultFromState (List.fold foldState (stateFromFirstElement hd) tl)

If you pass a value for the optional argument firstElementParser, the first element of the sequence will be parsed with firstElementParser instead of elementParser.

The following example shows how one could define CharParsers.manyCharsTill2 using Inline.ManyTill:

let myManyCharsTillApply2 cp1 cp endp f =
    Inline.ManyTill(firstElementParser = cp1,
                    elementParser = cp,
                    endParser = endp,
                    stateFromFirstElement =
                        (fun c -> let sb = System.Text.StringBuilder()
                                  sb.Append(c : char)),
                                  // sb.Append returns sb
                    foldState = (fun sb c -> sb.Append(c : char)),
                    resultFromStateAndEnd = (fun sb e -> f (sb.ToString()) e),
                    resultForEmptySequence = (fun e -> f "" e))

let myManyCharsTillApply cp endp f = myManyCharsTillApply2 cp cp endp f

let myRestOfLine : Parser<string,unit> =
    myManyCharsTillApply anyChar ((newline >>% "\\n") <|> (eof >>% ""))
                         (fun str nl -> str + nl)
> run myRestOfLine "";;
val it : ParserResult<string,unit> = Success: ""
> run myRestOfLine "abc\r\ndef";;
val it : ParserResult<string,unit> = Success: "abc\n"
val chainl1: Parser<'a,'u> -> Parser<('a -> 'a -> 'a),'u> -> Parser<'a,'u>

The parser chainl1 p op parses one or more occurrences of p separated by op (in EBNF: p (op p)*). It returns the value obtained by left associative application of all functions returned by op to the results returned by p, i.e. f_n (...(f_2 (f_1 x_1 x_2) x_3) ...) x_n+1, where f_1 to f_n are the functions returned by theparser op and x_1 to x_n+1 are the values returned by p. If only a single occurance of p and no occurance of op is parsed, the result of p is returned directly.

The chainl1 implementation uses constant stack space.

val chainl: Parser<'a,'u> -> Parser<('a -> 'a -> 'a),'u> -> 'a -> Parser<'a,'u>

The parser chainl p op defVal is equivalent to chainl1 p op <|>% defVal.

val chainr1: Parser<'a,'u> -> Parser<('a -> 'a -> 'a),'u> -> Parser<'a,'u>

The parser chainr1 p op parses one or more occurrences of p separated by op (in EBNF: p (op p)*). It returns the value obtained by right associative application of all functions returned by op to the results returned by p, i.e. f1 x_1 (f_2 x_2 (... (f_n x_n x_n+1) ...)), where f_1 to f_n are the functions returned by the parser op and x_1 to x_n+1 are the values returned by p. If only a single occurance of p and no occurance of op is parsed, the result of p is returned directly.

The chainr1 implementation uses constant stack space.

val chainr: Parser<'a,'u> -> Parser<('a -> 'a -> 'a),'u> -> 'a -> Parser<'a,'u>

The parser chainr p op defVal is equivalent to chainr1 p op <|>% defVal.

type ParserCombinator =

This class is defined as

[<Sealed>]
type ParserCombinator() =
  member t.Delay(f)   = fun state -> (f ()) state
  member t.Return(x)  = preturn x
  member t.Bind(p, f) = p >>= f
  member t.Zero()     = pzero
  member t.ReturnFrom(p) = p
  member t.TryWith(p, cf) = fun state -> try p state
                                         with e -> (cf e) state
  member t.TryFinally(p, ff) = fun state -> try p state
                                            finally ff ()

Instances of this class can be used to build parsers using F#’s computation expression syntax. The default instance for this purpose is parse.

Please see the user’s guide chapter “Where is the monad?” for an introduction to the parse {...} syntax.

Some constructs supported by parse and their translations are

let! pat = expr in pexpr   ==>   expr >>= (fun pat -> pexpr)

let pat = expr in pexpr    ==>   let pat = expr in pexpr

do! expr in pexpr          ==>   expr >>= (fun  () -> pexpr)

do expr in pexpr           ==>   expr; pexpr

if expr then pexpr1        ==>   if expr then pexpr1
else pexpr2                      else pexpr2

if expr then pexpr         ==>   if expr then pexpr1 else pzero

return exp                 ==>   preturn rexpr

return! expr               ==>   expr

where expr is any F# expression and pexpr is an expression of type Parser<_,_>. You need to use the !‐constructs whenever you have a right hand side expression that evaluates to a parser.

val parse: ParserCombinator

A builder object of type ParserCombinator for building parsers using F#’s computation expression syntax.

val createParserForwardedToRef: unit -> Parser<'a,'u> * Parser<'a,'u> ref

let p, pRef = createParserForwardedToRef() creates a parser p that forwards all calls to the parser in the reference cell pRef. Initially, pRef holds a reference to a dummy parser that raises an exception on any invocation.

The JSON parser example in the tutorial shows how you can use createParserForwardedToRef to define a parser for a recursive grammar.