Parsing ranges with FParsec

FParsec is an F# adaptation of Parsec, a free monadic parser combinator library for Haskell. It can parse context-sensitive, infinite look-ahead grammars, has complete support for unicode input and large files (> 4 GB) and produces excellent error messages.

You can download and install it from the above link. To use it in an application, you must add a reference to FParsec.dll and FParsecCS.dll.

In this post I will use FParsec to parse ranges of numerical values, such as [1-100], and IPs, such as [10.5.10.0-10.5.255.255].

I will start by defining some types:

Having that, I can define a parser for numerical ranges like this:

That can be read like this: make sure it stars with [ byt skip that, parse an numerical value and let that be a, make sure – follows but skip that, parse a second numerical value and let that be b, make sure ] follows but skip that, and it if successful return a Range of a and b.

To print a Range value I’ll use this function:

Here is a test

That outputs:

Using “(1-100)” instead of “[1-100]” yields the following error message:

Let’s move forward and define an IP parses. Based on what I did so far this should be pretty easy to understand.

And an IP range parser would look just like the first range parser, except that pint64 would be replaced by p_ip:

Here are some helper functions for testing these parses:

You probably noticed the construction “(p_numrange .>> eof)”. That reads: parse a range, and then the end of the file and return the range. That helps us making sure nothing follows the range, like “[1-100] more here”.

Executing

yields

Executing

yields

and executing

yields

But why defining two range parser? Isn’t possible to have just a single one and specify which parser to use for the values? Yes, it is possible, and that would look like this:

Having that, we can re-define the p_numrange and p_iprange like shown bellow:

Everything above would work, except for testip function that needs change to:

That’s about it about parsing ranges with FParsec.

CategoriesF#

2 Replies to “Parsing ranges with FParsec”

  1. Nice article, Marius.

    There’s a small issue with the error messages: the caret (^) isn’t displayed at the right position because the whitespace isn’t significant in HTML. You could fix this by putting pre-tags around the error messages.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.