Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FParsec: backtracking `sepBy`

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?

like image 837
Carl Patenaude Poulin Avatar asked Aug 12 '17 19:08

Carl Patenaude Poulin


1 Answers

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.

like image 118
Stephan Tolksdorf Avatar answered Sep 27 '22 16:09

Stephan Tolksdorf