java - 慢速 ANTLR4 在 Python 中生成解析器,但在 Java 中速度很快

标签 java python parsing antlr antlr4

我正在尝试转换 ant ANTLR3 grammarANTLR4 grammar ,以便将它与 antlr4-python2-runtime 一起使用。 该语法是一个 C/C++ 模糊解析器。

转换后(基本上删除了树运算符和语义/句法谓词),我使用以下方法生成了 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 规则及其所有后代经常被调用,我认为我需要简化/更改这些规则以使解析器运行得更快: expr_tree

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

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

最佳答案

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

关于java - 慢速 ANTLR4 在 Python 中生成解析器,但在 Java 中速度很快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31455500/

相关文章:

python - BeautifulSoup `find_all` 生成器

java - java 中的整个 try/catch 语句需要大括号吗?真的很奇怪的东西

java - Spring LDAP : creating connection

java - -libraryjars,proguard 的目的是什么?

java - 如何在Java中包装多个方法?枚举不是正确的方法吗?

python - Perl 到 Python 哈希表的翻译

python - 如何在pandas数据框中生成动态变量名称

python - 如何通过 SSH 将正则表达式参数传递给另一个脚本

解析源代码 - 不同语言的唯一标识符?

java - OpenNLP 头规则