Consider the following toy grammar and parser:
(* in EBNF:
ap = "a", { "ba" }
bp = ap, "bc"
*)
let ap = sepBy1 (pstring "a") (pstring "b")
let bp = ap .>> (pstring "bc")
let test = run bp "abababc"
I get the following output:
Error in Ln: 1 Col: 7
abababc
^
Expecting: 'a'
Clearly sepBy1
sees the last b
and expects it to lead into another a
, failing when it doesn't find one. Is there a variant of sepBy1
which would backtrack over b
and make this parse succeed? Is there any reason why I shouldn't use that instead?
This is one way to implement such a variant of sepBy1
:
let backtrackingSepBy1 p sep = pipe2 p (many (sep >>? p)) (fun hd tl -> hd::tl)
Avoiding backtracking in your parser grammar usually makes the parser faster, more portable and easier to debug. Hence, if you have the chance to avoid backtracking by restructuring the grammar (without complicating it too much), I'd recommend doing it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With