4

我正在制作一个 LR(1) 解析器,并且在各个地方都遇到了性能瓶颈。

我想尝试优化解析器的数据结构,但为了做到这一点,我需要大致了解有多少状态、规则和终端符号对于(可能很复杂)计算机语言(如 C++)是合理的。

我的猜测是,复杂语言的典型语法将具有:

  • ≤ 100 个终端符号
  • ≤ 50 个符号/产品
  • ≤ 2,000 条规则
  • ≤ 10,000 个州

但我真的不知道它们有多正确。

请注意,我假设每个规则的形式为非终结符符号 符号 符号...,因此看起来像的单个复合“规则”foo: (bar | baz)+实际上可能包含 5 条规则,而不仅仅是 1 条规则。

它们合理吗?如果没有,我在哪里可以找到这些数字?

4

1 回答 1

6

我每天开发的 DMS 系统在一台破旧的笔记本电脑上(刚刚在该笔记本电脑上测量)大约 7 秒内处理生产 IBM Enterprise COBOL 前端语法。

该语法有大约 500 个终端和 2500 个产生式,平均每个产生式大约 2.5 个标记。我们的产品与您描述的完全一样(没有 EBNF,只是买的东西不够重要,是的,我们是 DSL 的忠实拥护者。有时人们放入 DSL 的 geegaws 不值得)。解析器生成器产生 3800 个状态。(这些值也是刚刚测量的)。

DMS 具有完整的 C++11 语法,其中包含许多额外的东西来处理 GCC 和 MS 方言,以及 OpenMP。该语法有 457 个终端,大约 3000 个产生式,每个产生式平均有 2.3 个标记。解析器生成器产生 5800 个状态。需要更长的时间来生成:11 秒,在 i7 上。您可能会感到惊讶的是,生成词法分析器需要几十秒(实际上是多个词法分析器);C++11 中的词法怪异比你想象的要多得多。

生成器是我们自己实现的 GLR 生成器。

我们没有做很多优化生成时间的工作。它可能会加速 10 倍或更多;我们没有像大多数关于 LR 解析器生成的论文中建议的那样进行复杂的循环检测优化。结果是生成表需要更长的时间,但功能上没有任何损失。我们从来没有足够的动力进行这种优化,因为除了担心解析器表的生成时间之外,语言前端还有很多其他事情要做。

如果设计合理,我怀疑数据结构是否很重要。我们不太担心规则、项目集或状态的大小;我们只使用动态数组,它们会照顾自己。我们确实将前瞻打包到密集的位向量中。

作为额外的背景数据,您可能会发现这篇论文很有用:Tiago Alves 和 Joost Visser,SDF 语法的度量。技术报告,DI-Research.PURe-05.05.01,Departamento de Informática,Universidade do Minho,2005 年 5 月。

解析器生成器不是您在语法方面遇到困难的地方。它正在为特定的实现获取正确的语法规则。

于 2013-01-04T06:06:48.327 回答