简体   繁体   中英

FParsec combinator to turn Parser<char,_> until Parser<string,_>?

I'm certain there's a really simple answer to this, but I've been staring at this all day and I can't figure it out.

As per the tutorial, I'm implementing a JSON parser. To challenge myself, I'm implementing the number parser myself.

This is what I got so far:

let jnumber =
    let neg = stringReturn "-" -1 <|> preturn 1
    let digit = satisfy (isDigit)
    let digit19 = satisfy (fun c -> isDigit c && c <> '0')
    let digits = many1 digit
    let ``int`` =
        digit
        <|> (many1Satisfy2 (fun c -> isDigit c && c <> '0') isDigit)

The trouble is that digit is a Parser<char,_> , whereas the second option for int is a Parser<string,_> . Would I normally just use a combinator to turn digit into a Parser<char,_> , or is there something else I should do?

The |>> operator is what you're looking for. I quote the FParsec reference :

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 fx, where x is the result returned by p.

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

For example:

let jnumber =
    let neg = stringReturn "-" -1 <|> preturn 1
    let digit = satisfy (isDigit)
    let digit19 = satisfy (fun c -> isDigit c && c <> '0')
    let digits = many1 digit
    (digit |>> string) (* The operator is used here *)
    <|> (many1Satisfy2 (fun c -> isDigit c && c <> '0') isDigit)

You may want to read FParsec tutorial on parsing JSON which uses this operator quite intensively.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM