ANTLR4在Python中生成的解析器很慢,但在J中生成的解析器很快

2024-09-28 20:51:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图将ant ANTLR3 grammar转换为ANTLR4 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中,只用了795毫秒就完成了解析。这个问题似乎更多地与python实现有关,而不是语法本身。有什么可以做的来加速Python解析的吗?
我读过here说python可能比java慢20-30倍,但在我的例子中python要慢大约400倍!在


Tags: 文件fromimportparseriftimemaindef
3条回答

我也遇到了类似的问题,所以我决定用一个可能的解决方案来取代这个旧帖子。我的语法在TestRig上运行很快,但是在python3上运行得非常慢。在

在我的例子中,错误是我用来生成一行注释的非贪婪令牌(C/C++中的双斜线,在我的情况下是'%'):

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

这在某种程度上得到了sharwell在本次讨论中的帖子的支持:https://github.com/antlr/antlr4/issues/658

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

为了测试这个场景,您可能需要从语法中删除非贪心的规则/标记。在

张贴在这里,因为它可能是有用的人找到这个线索。在

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

我为Antlr的Python3目标构建了一个Python加速器代码生成器。它使用ANTLR C++目标作为Python扩展。LISEN和解析是在C++中专门完成的,然后使用自动生成的访问者来重新构建Python中的结果解析树。最初的测试显示了一个5x-25x的加速,这取决于语法和输入,我对如何进一步改进它有一些想法。在

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

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

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

我确认python2和python3运行时存在性能问题。通过一些补丁,我在python3运行时得到了10倍的加速(大约5秒到400毫秒)。 https://github.com/antlr/antlr4/pull/1010

相关问题 更多 >