4

given the following

let maxCount = System.Int32.MaxValue
let pmlcomment = pstring "/*" >>. skipCharsTillString "*/" true (maxCount)
let ws = pspaces >>. many (pspaces >>. pmlcomment .>> pspaces) |>> (function | [] -> () | _ -> ())
let str_ws s = pstring s .>> ws
let exprBraceSeqOpt p =
    let trailingComma = (str_ws "," |>> fun _ -> None )
    between (str_ws "{") (str_ws "}") ((opt (attempt (sepBy p (str_ws ",")))) <|> (attempt trailingComma))
let sampleP = exprBraceSeqOpt (str_ws "x")

it properly matches all of the following except the last one:

["{}";"{x}";"{x,x}";"{x,x,}"]

I'm guessing something is altering the state or something.

How do I handle an optional trailing comma in fparsec?

Yawar
  • 11,272
  • 4
  • 48
  • 80
Maslow
  • 18,464
  • 20
  • 106
  • 193

1 Answers1

4

sepBy "eats up" the extra separator if it is present. That's just how it works, period. You cannot hack it by applying attempt in various places: if you apply attempt to the separator, it won't help, because the last separator actually succeeds, so attempt will have no effect. And applying attempt to the whole sepBy will also not help, because then the whole sepBy will be rolled back, not just the last separator. And applying attempt to the "x" parser itself, while achieving the desired trailing comma behavior, would also have the adverse effect of making the parser accept multiple commas in a row.

And because it is impossible to achieve the desired result via clever use of combinators, there is actually a special function for doing just what you're after - sepEndBy.

This would work as desired:

let exprBraceSeqOpt p =
    between (str_ws "{") (str_ws "}") (sepEndBy p (str_ws ","))

Also, as an aside, I should point out that function | [] -> () | _ -> () is a remarkably elaborate way to do ignore. :-)

Fyodor Soikin
  • 78,590
  • 9
  • 125
  • 172
  • 1
    very nice information. as for the ignore... I trimmed this down poorly for general consumption, there are things in there in my actual code =) – Maslow Nov 03 '16 at 04:51