Search code examples
recursionf#typesgraphvizfparsec

How can I express a type in F# that optionally recurses on itself (infinitely)


As a learning exercise I am trying to implment a parser for the graphviz dot language (The DOT language) using the functional parser library fparsec (FParsec). The language describes graphs.

Looking at the language definition I was compelled to write down the following definition:

let rec pstmt_list = opt(pstmt .>> opt(pchar ';') >>. opt pstmt_list)

Where pstmt and pchar ';' are parsers, .>> and >>. combine an occurence of the left parser with an occurence of the right parser, and opt parsers an optional occurrence of its argument parser as an option value. However this definition does not work complaining "... the resulting type would be infinite ...".

This example is probably most easily understood by taking a look at the DOT language linked above.

I am aware of the following seemingly linked questions:

But my F# knowledge may not be sufficient to translate them yet, if they apply here at all.


Solution

  • FParsec provides special combinators for parsing sequences. Normally you should prefer these combinators to reimplementing them with a recursive function. You can find an overview of the available combinators for parsing sequences here: http://www.quanttec.com/fparsec/reference/parser-overview.html#parsing-sequences

    In this example pstmt_list is a sequence of statements separated and optionally ended by semicolons, so you could easily define the parser as

    let pstmt_list = sepEndBy pstmt (pstring ";")