Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/438.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在Antlr4中,重用规则是否总是比使用标记重新定义慢?_Javascript_Antlr4 - Fatal编程技术网

Javascript 在Antlr4中,重用规则是否总是比使用标记重新定义慢?

Javascript 在Antlr4中,重用规则是否总是比使用标记重新定义慢?,javascript,antlr4,Javascript,Antlr4,我正在用JavaScript分析Antlr4生成的解析器。我有一些规则与ID | STRING匹配 雷克瑟 分析器 如果我将some更改为some:name和不同到不同:名称性能下降约30%。(要将给定代码解析100次,时间从1.5秒增加到2秒左右) 在本例中,name是解析器中的终端节点。因此,我不会自行承担大量开销。我们还有8个地方使用ID | STRING。这30%是在我用name替换了它们之后 测试代码为: x = B."method. {a, b} 1"(1,2)

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

雷克瑟 分析器 如果我将
some
更改为
some:name
不同
不同:名称性能下降约30%。(要将给定代码解析100次,时间从1.5秒增加到2秒左右)

在本例中,
name
是解析器中的终端节点。因此,我不会自行承担大量开销。我们还有8个地方使用
ID | STRING
。这30%是在我用
name
替换了它们之后

测试代码为:

x = B."method. {a, b} 1"(1,2)
在上述代码中,以下内容将由“ID | STRING”匹配:

  • x
  • B
  • “梅托德{a,b}1”
  • 一,
  • 二,
  • 我在标题中的假设正确吗?

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

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

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


    如果您感觉到了围绕它的性能问题,那么“展开”它可能会有一些意义。当然,您将在生成的解析树中丢失“name”上下文。这可能是好事,也可能是坏事,这取决于你想如何处理事情。(有时,这些额外的解析树节点只是噪音,可能会让人感觉不舒服,而其他时候,它们是重要的信息)。

    我在Intellij IDEA插件的Profile选项卡中也观察到类似的解析时间模式。是的,您发现了Antlr的几种优化技术之一。折叠操作(为RHS符号序列引入新规则)总是会减慢解析调用的运行时间。相反,展开重构会导致更快的解析时间。当然,如果不经常使用规则,展开操作可能不会产生太大影响。还有许多其他重要的优化方法。嗨@kaby76,你能给我指一些关于“许多其他重要优化方法”的帮助内容吗?到目前为止,Google搜索没有返回很多有用的信息,除了这一条。Peng,没有太多好的Antlr优化来源。但托马塞蒂涵盖了很多。也许这很明显,但用Kleene操作符替换递归可以提高解析时间。阅读Parr的论文LL(*)可能是值得的:ANTLR解析器生成器的基础,查看解析器结束回溯的时间。同样值得考虑的是您需要什么样的解析。Antlr构造了一个CST,但是如果需要,您可以构造一个AST,并避免在解析之后从CST转换到AST的时间。是的。这是人为的,我对它进行了100次分析,以得到一个可测量和可比较的结果。然而,我可以说,在这种情况下,这是不可忽视的。我也尝试过在其他地方展开,但并非所有的“展开”都能带来明显的改善。在这种情况下,丢失“name”并不重要,因为我可以在上下文中使用“some”和“different”。我认为这会提高性能,因为我们“重用”了一个规则,它可以被“缓存”。我完全错误地理解了antlr4中“缓存”的工作原理。我用解析的代码更新了这个问题。在您的示例代码中,似乎几乎所有的输入都属于这个规则。因此,这肯定符合大量使用它来解析输入的条件。因此,我并不惊讶于看到它有很大的不同(但可能不会打赌30%)。有了这样一个简单的语法和输入,几乎所有的事情都会符合解析器规则,因此额外规则的开销是可以检测到的,这并不奇怪。有趣的线程都一样。
    name: ID | STRING ;
    
    rule1: some other rules;
    rule2: different rules
    
    some: ID | STRING ;
    different: ID | STRING ;
    
    x = B."method. {a, b} 1"(1,2)