可以安全地重用 petitparser 解析器吗?

Can a petitparser parser be reused safely?

在 Dart 中使用 petitparser,是否可以重用解析器?

例如,假设我们要解析像 192.168.1.21.

这样的 IPv4 样式地址

最初,我写道:

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

我注意到我的序列解析器有 7 个 children,正如预期的那样,但是数字解析器 都是相同的(至少都有相同的 hashCode) 而点解析器则完全不同。尽管如此,解析器似乎可以正常工作。

我试验过:

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

在这个简单的例子中效果同样好,代价是多了一些 ()s 和更多的 objects 内存。

有什么理由比另一种更喜欢一种风格吗?有没有更好的写法?

第一次尝试成功是我的幸运吗?如果我将所有 final 更改为返回 Parser 的函数,那么我似乎采用了 GrammarDefinition 的风格。我是否必须/我应该在整个过程中使用 ref(parser) 语法?

我的整体解析器是针对 non-recursive 语法的,目前我没有使用 GrammarDefinition。到目前为止,当我认为我的语法中没有任何递归时,将我所做的修改为语法定义有什么好处?

是的,解析器可以(并且应该)被重用。解析器对象可以看作是知道如何解析特定语法的可配置函数。您可以调用(解析一些输入)并重用 Dart 函数等解析器。

以上两个示例都可以工作并且执行相同的操作,第一个示例只是生成了一些较小的解析器图。使用 GrammarDefinition 时,您应该使用 ref,它使用递归语法并自动重用解析器对象。在你的情况下,我会选择最初的例子,它似乎是最简洁的解决方案。