As an example, I will take this simple C# parser by Phillip Trelford. In order to parse an identifier he writes this (slightly changed):
let reserved = ["for";"do"; "while";"if";"switch";"case";"default";"break" (*;...*)]
let pidentifierraw =
let isIdentifierFirstChar c = isLetter c || c = '_'
let isIdentifierChar c = isLetter c || isDigit c || c = '_'
many1Satisfy2L isIdentifierFirstChar isIdentifierChar "identifier"
let pidentifier =
pidentifierraw
>>= fun s ->
if reserved |> List.exists ((=) s) then fail "keyword instead of identifier"
else preturn s
The problem with pidentifier is that when it fails, the position indicator is at the end of the stream. An example of mine:
Error in Ln: 156 Col: 41 (UTF16-Col: 34)
Block "main" 116x60 font=default fg=textForeground
^
Note: The column count assumes a tab stop distance of 8 chars.
keyword instead of identifier
Obviously, not a C# snippet, but for the example's sake, I've used the pidentifier to parse the text after font=. Is it possible to tell FParsec to show the error at the beginning of the parsed input? Using >>?, .>>.? or any of the backtracking variants seems to have no effect.
I think what you want is
attempt p, which will backtrack to the original parser state if parserpfails. So you could just definepidentifieras:Output is then something like:
Update
If you don't want to see the backtracking info in the error message, you can use a simplified version of
attempt, like this:Output is now just: