1

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

例如,假设我们要解析 IPv4 样式的地址,例如192.168.1.21.

最初,我写道:

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

我注意到我的序列解析器有 7 个孩子,正如预期的那样,但是数字解析器都是相同的(至少都具有相同的hashCode),而点解析器却是不同的。尽管如此,解析器似乎工作。

我尝试过:

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

在这种简单的情况下同样有效,但代价是()内存中的一些额外的 s 和少量的对象。

有什么理由更喜欢一种风格而不是另一种风格?有没有更好的方法来写这个?

我只是幸运,我的第一次尝试成功了吗?如果我将所有finals 更改为返回的函数Parser,似乎我采用了GrammarDefinition. 我是否必须/我应该ref(parser)自始至终使用语法?

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

4

1 回答 1

1

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

上述任何一个例子都可以工作并且做同样的事情,第一个例子只是产生了一个更小的解析器图。使用GrammarDefinition时应该使用ref,它适用于递归语法并自动重用解析器对象。在您的情况下,我将使用最初的示例,这似乎是最简洁的解决方案。

于 2020-02-29T19:07:57.983 回答