1

Using petitparser in Dart, is it ok to reuse a parser?

For example, say we want to parse an IPv4 style address like 192.168.1.21.

Initally, I wrote:

final ipv4Part = digit().repeat(1, 3).flatten();
final ipv4Address = (ipv4Part &
        char('.') &
        ipv4Part &
        char('.') &
        ipv4Part &
        char('.') &
        ipv4Part)
    .flatten();
ipv4Address.parse('192.168.1.21');

I noticed that my sequence parser had 7 children, as expected, but the number parsers were all identical (at least all had the same hashCode) whereas the dot parsers were all different. Nonetheless, the parser seemed to work.

I experimented with:

Parser ipv4Part() => digit().repeat(1, 3).flatten();
final ipv4Address = (ipv4Part() &
        char('.') &
        ipv4Part() &
        char('.') &
        ipv4Part() &
        char('.') &
        ipv4Part())
    .flatten();

which worked equally well in this simple case, at the expense of a few extra ()s and a handful more objects in memory.

Is there any reason to prefer one style over the other? Is there a better way to write this?

Was I just lucky that my first attempt worked? If I change all my finals to functions returning Parser it seems I'm adopting the style of GrammarDefinition. Would I have to / should I then use the ref(parser) syntax throughout?

My overall parser is for a non-recursive grammar, and at the moment I'm not using GrammarDefinition. What are the benefits of reworking what I've done into a grammar definition when, so far, I don't think there's any recursion in my grammar?

Richard Heap
  • 48,344
  • 9
  • 130
  • 112
  • In what I'm sure is beside the point, for this particular case of parsing IPv4 addresses I'd probably recommend using regular expressions over custom grammar parsers. It just seems to me like overkill for IP addresses for any but educational purposes. – Abion47 Feb 28 '20 at 21:36
  • If you need to parse an ip address in dart you can just use [InternetAddress](https://api.dart.dev/stable/2.7.1/dart-io/InternetAddress/InternetAddress.html) and catch the `ArgumentException` – Mattia Feb 29 '20 at 09:13

1 Answers1

1

Yes, parsers can (and should) be reused. The parser objects can be seen as configurable functions that know how to parse a particular grammar. You can call (parse some input) and reuse parsers like Dart functions.

Either of the above examples work and do the same, the first one just produces a bit of a smaller parser graph. When using GrammarDefinition you should use ref, it works with recursive grammars and automatically reuses the parser objects. In your case I would go with the initial example, it seems to be the most succinct solution.

Lukas Renggli
  • 8,754
  • 23
  • 46