I'm writing a parser for a pseudolanguage using of the FParsec library, I have a statement parser, which is a choice between all posible statements a block parser, which parses a series of statements until an "end" keyword and now I want to write a "loop" construct, the problem is, the loop itself is a statement, and contains a block this led to a recursive form of definition which F# didn't like I had written a parser in C# a while ago, and getting through this was easy since each parser was a function, and they can call each other independent of wether they're defined before or after
So I want to know how I could solve this in F#
here is the parsers mentioned:
// parses a list of statements, separated by 1 or more newlines, (pre|post)fixed by any amount of whitespace, and finishes parsing upon reaching an "end" keyword
let block endtag = many1Till (statement .>> nl) (skipString endtag) // at this moment, statement is undefined
// parses a loop structure; the keyword loop, followed by an identifier for the iteration variable, followed by an expression which evaluates to the amount iterations which should be executed, followed by a block closed with "endloop"
let loop = skipString "loop" >>. ws1 >>. id .>> ws1 .>>. expr .>> nl .>>. block "endloop" |>> fun ((i, n), s) -> Loop (i, n, s)
// parses any statement, pre or post fixed by any amount of whitespace
let statement = spaces >>. choice [writeline; write; comment; definition; loop; sleep; assignment] .>> spaces
FParsec supports recursive parsers through
createParserForwardedToRef
. The JSON parser described in the tutorial shows how to use it. Here's an excerpt of the relevant info: