ANTLR4 在 Python 中生成解析器速度较慢,但​​在 Java 中生成速度较快

Slow ANTLR4 generated Parser in Python, but fast in Java

我正在尝试转换 ant ANTLR3 grammar to an ANTLR4 grammar,以便在 antlr4-python2-runtime 中使用它。 这个语法是一个 C/C++ 模糊解析器。

转换后(基本上删除了树运算符和 semantic/syntactic 谓词),我使用以下方法生成了 Python2 文件:

java -jar antlr4.5-complete.jar -Dlanguage=Python2 CPPGrammar.g4

并且代码生成没有任何错误,所以我将其导入我的 python 项目(我正在使用 PyCharm)进行一些测试:

import sys, time
from antlr4 import *
from parser.CPPGrammarLexer import CPPGrammarLexer
from parser.CPPGrammarParser import CPPGrammarParser

currenttimemillis = lambda: int(round(time.time() * 1000))

def is_string(object):
    return isinstance(object,str)

def parsecommandstringline(argv):
    if(2!=len(argv)):
        raise IndexError("Invalid args size.")
    if(is_string(argv[1])):
        return True
    else:
        raise TypeError("Argument must be str type.")

def doparsing(argv):
    if parsecommandstringline(argv):
        print("Arguments: OK - {0}".format(argv[1]))
        input = FileStream(argv[1])
        lexer = CPPGrammarLexer(input)
        stream = CommonTokenStream(lexer)
        parser = CPPGrammarParser(stream)
        print("*** Parser: START ***")
        start = currenttimemillis()
        tree = parser.code()
        print("*** Parser: END *** - {0} ms.".format(currenttimemillis()-start))
        pass

def main(argv):
    tree = doparsing(argv)
    pass

if __name__ == '__main__':
    main(sys.argv)

问题是解析很慢。一个包含 ~200 行的文件需要 5 分钟以上才能完成,而在 antlrworks 中解析同一文件只需要 1-2 秒。 分析 antlrworks 树,我注意到 expr 规则及其所有后代经常被调用,我认为我需要 simplify/change 这些规则来使解析器运行得更快:

我的假设是正确的还是我在转换语法时犯了一些错误?怎样才能使解析速度与 antlrworks 一样快?

更新: 我将相同的语法导出到 Java,只用了 795ms 就完成了解析。这个问题似乎更多地与 python 实现有关,而不是与语法本身有关。有什么可以加快 Python 解析的速度吗?
我读过 here python 比 java 慢 20-30 倍,但在我的情况下 python 慢了 ~400 倍!

我遇到了类似的问题,所以我决定用一个可能的解决方案来解决这个旧问题 post。我的语法 运行 立即使用 TestRig,但在 Python 上非常慢 3.

在我的例子中,错误是我用来生成单行注释的非贪婪标记(C/C++ 中的双斜杠,在我的例子中为 '%'):

TKCOMM : '%' ~[\r\n]* -> skip ;

这在某种程度上得到了来自 sharwell 的 post 的支持,在此讨论中:https://github.com/antlr/antlr4/issues/658

When performance is a concern, avoid using non-greedy operators, especially in parser rules.

要测试此场景,您可能需要从语法中删除非贪婪 rules/tokens。

我确认 Python 2 和 Python 3 运行时存在性能问题。通过几个补丁,我在 python3 运行时获得了 10 倍的加速(约 5 秒减少到约 400 毫秒)。 https://github.com/antlr/antlr4/pull/1010

张贴在这里,因为它可能对找到此主题的人有用。

自从这篇文章发布后,Antlr 的 Python 目标有了一些性能改进。也就是说,Python 解释器本质上会比 Java 或其他编译语言慢。

我已经为 Antlr 的 Python3 目标整合了一个 Python 加速器代码生成器。它使用 Antlr C++ 目标作为 Python 扩展。词法分析和解析完全在 C++ 中完成,然后使用自动生成的访问者在 Python 中重新构建生成的解析树。初步测试显示5x-25x 加速,具体取决于语法和输入,我对如何进一步改进它有一些想法。

这是代码生成工具:https://github.com/amykyta3/speedy-antlr-tool

这是一个功能齐全的示例:https://github.com/amykyta3/speedy-antlr-example

希望这对喜欢在 Python 中使用 Antlr 的人有用!

我最近在 python3 目标中使用 ANTLR。 一个 500~ 行的文件只需要不到 20 秒的时间来解析。 因此转向 Python3 目标可能会有所帮助