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 final
s 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?
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.