首页 > 解决方案 > 在 Antlr4 中重用规则总是比使用令牌重新定义慢吗?

问题描述

我正在用 JavaScript 分析我的 Antlr4 生成的解析器。我有一些匹配的规则ID | STRING

词法分析器

ID
 : [a-zA-Z_] [a-zA-Z_0-9]*
 ;

STRING
 : '"' (~["\r\n] | '""')* ('"'|[\r\n])?
 ;

解析器

name: ID | STRING ;

rule1: some other rules;
rule2: different rules

some: ID | STRING ;
different: ID | STRING ;

如果我更改为somesome: name;性能下降约 30%。(要解析给定代码 100 次,时间从 1.5 秒增加到大约 2 秒)。differentdifferent: name;

在这种情况下,name是解析器中的终端节点。所以我不会假设很多开销本身。我们还有 8 个其他地方使用ID | STRING. 那 30% 是在我将它们全部替换为name.

测试代码为:

x = B."method. {a, b} 1"(1,2)

在上面的代码中,以下内容将被“ID | STRING”匹配:

  1. X
  2. “方法。{a, b} 1”
  3. 1
  4. 2

我在标题中的假设是否正确?

标签: javascriptantlr4

解决方案


30% 似乎很多(但在一个非常简单的例子中这可能是人为的)

使用递归下降解析器,调用名称规则而不是识别两个标记中的任何一个都会有一些开销是有道理的。

我认为在更大的比赛中整体影响可以忽略不计,除非这是你语法中非常基本的部分,并且经常使用。

如果您在它周围感到性能痛苦,那么“展开”它可能是有道理的。当然,您会在生成的解析树中丢​​失“名称”上下文。这可能是好事也可能是坏事,这取决于你想如何处理事情。(有时,那些额外的解析树节点只是您拥有的噪音,可能会让人感到恼火,而其他时候,它们是重要的信息)。


推荐阅读