There are several notable issues with your code.
First off, as noticed in @scrwtp's answer, your parser returns unit
. Here's why: operator (>>.)
returns only the result returned by the right inner parser. On the other hand, (.>>)
would return the result of a left parser, while (.>>.)
would return a tuple of both left and right ones.
So, parser1 >>. parser2 >>. eof
is essentially (parser1 >>. parser2) >>. eof
.
The code in parens completely ignores the result of parser1
, and the second (>>.)
then ignores the entire result of the parser in parens. Finally, eof
returns unit
, and this value is being returned.
You may need some meaningful data returned instead, e.g. the parsed string. The easiest way is:
let capitalized = (asciiUpper .>>. many asciiLower .>> eof)
Mind the operators.
The code for inverted
can be done in a similar manner.
This parser would be of type Parser<(char * char list), unit>
, a tuple of first character and all the remaining ones, so you may need to merge them back. There are several ways to do that, here's one:
let mymerge (c1: char, cs: char list) = c1 :: cs // a simple cons
let pCapitalized = capitalized >>= mymerge
The beauty of this code is that your mymerge
is a normal function, working with normal char
's, it knows nothing about parsers or so. It just works with the data, and (>>=)
operator does the rest.
Note, pCapitalized
is also a parser, but it returns a single char list
.
Nothing stops you from applying further transitions. As you mentioned printing the string backwards:
let pCapitalizedAndReversed =
capitalized
>>= mymerge
>>= List.rev
I have written the code in this way for purpose. In different lines you see a gradual transition of your domain data, still within the paradigm of Parser. This is an important consideration, because any subsequent transition may "decide" that the data is bad for some reason and raise a parsing exception, for example. Or, alternatively, it may be merged with other parser.
As soon as your domain data (a parsed-out word) is complete, you extract the result as mentioned in another answer.
A minor note. choice
is superfluous for only two parsers. Use (<|>)
instead. From experience, careful choosing parser combinators is important because a wrong choice deep inside your core parser logic can easily make your parsers dramatically slow.
See FParsec Primitives for further details.