Reputation: 37045
I want to parse a given char
twice, but return a string
of that character only once.
For example:
aa -> a
I have some code that works, but also some code that does not work, and I don't understand why.
Why are these snippets different?
// Works
let parseEscapedQuote (c : char) =
let q = string c
pstring (q + q) >>% q
// Does not work
let parseEscapedQuote (c : char) =
let q = string c
pchar c >>. pchar c >>% q
Upvotes: 1
Views: 48
Reputation: 17038
The second one will successfully parse a repeated character the way you want, but it might not fail the way you expect. If only the first pchar c
succeeds, it will leave your parser in an invalid state. To fix this, you can use attempt
, which restores the prior state if it fails:
attempt (pchar c >>. pchar c) >>% q
Here's a complete example that illustrates the difference:
open FParsec
let parseTwiceBad (c : char) =
pchar c >>. pchar c >>% string c
let parseTwiceGood (c : char) =
attempt (pchar c >>. pchar c) >>% string c
let mkParser parseTwice =
choice [
parseTwice 'x'
anyString 3
]
let run parser str =
let result = runParserOnString parser () "" str
match result with
| Success (value, _, _) -> printfn "Success: %A" value
| Failure (msg, _, _) -> printfn "Failure: %s" msg
let test str =
printfn ""
printfn "Parsing \"%s\" with bad parser:" str
let parser = mkParser parseTwiceBad
run parser str
printfn "Parsing \"%s\" with good parser:" str
let parser = mkParser parseTwiceGood
run parser str
[<EntryPoint>]
let main argv =
test "xx"
test "xAx"
0
Output:
Parsing "xx" with bad parser:
Success: "x"
Parsing "xx" with good parser:
Success: "x"
Parsing "xAx" with bad parser:
Failure: Error in Ln: 1 Col: 2
xAx
^
Expecting: 'x'
Parsing "xAx" with good parser:
Success: "xAx"
Upvotes: 2