Медленный ANTLR4 генерируется парсер в Python, но быстро в Java

Я пытаюсь преобразовать ant ANTLR3 грамматики до ANTLR4 грамматики, чтобы использовать его с 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 парсинг?
Я читал здесь этот python может быть в 20-30 раз медленнее java, но в моем случае python ~В 400 раз медленнее!

2 ответов


Я подтверждаю, что среды выполнения Python 2 и Python 3 имеют проблемы с производительностью. С несколькими патчами я получил 10-кратное ускорение во время выполнения python3 (~5 секунд до ~400 мс). https://github.com/antlr/antlr4/pull/1010


Я сталкивался с подобной проблемой и поэтому я решил поднять этот старый пост с решением. Моя грамматика мгновенно работала с TestRig, но была невероятно медленной на Python 3.

в моем случае ошибкой был не-жадный токен, который я использовал для создания комментариев одной строки (двойная косая черта в C / C++, " % " в моем случае):

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

Это несколько подкреплено этим сообщением от sharwell в этом обсуждении здесь: https://github.com/antlr/antlr4/issues/658

когда производительность вызывает беспокойство, избегайте использования не-жадных операторов, особенно в правилах парсера.

чтобы проверить этот сценарий, вы можете удалить не-жадные правила / токены из своей грамматики.