I am trying to use FParsec to parse a list of zero or more elements of the form [string]
where the string in the middle can be anything (except ]
as to disambiguate from the end of the string). Here is my code as is:
let parseArgumentList : Parser<string list, unit> =
let parseArgument = (skipChar '[') >>. (manySatisfy (fun x -> x <> ']')) .>> (skipChar ']')
sepBy (parseArgument) (spaces)
[<EntryPoint>]
let main argv =
let parserResult = run parseArgumentList "[testString] [testString]"
printfn "%A" parserResult
0
The output here is:
Failure:
Error in Ln: 1 Col: 26
[testString] [testString]
^
Note: The error occurred at the end of the input stream.
Expecting: '['
It is as if the parser is expecting another set of parenthesis rather than terminating at 2 occurances in sepBy
. I tested this by changing the spaces
to (skipChar ' ') >>. spaces
and sure enough it parses fine. I am however unwilling to remove the option of no spaces between arguments. Any ideas or advice would be greatly appreciated.
I think using sepEndBy
instead of sepBy
will do what you want:
let parseArgumentList =
sepEndBy parseArgument spaces
From the FParser doc: The parser sepEndBy p sep
parses zero or more occurrences of p
separated and optionally ended by sep
. (Emphasis added.)
Running this on your test input produces the expected result:
Success: ["testString"; "testString"]
Note that this solution also has the nice side-benefit of consuming trailing spaces, if there are any. E.g. When the input is "[testString] [testString] "
.