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?
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
GrammarDefinitionyou should useref, 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.