Sto provando a convertire il formico ANTLR3 grammar in un ANTLR4 grammar, per poterlo utilizzare con il runtime antlr4-python2. Questa grammatica è un parser fuzzy C/C++.Parser lento ANTLR4 generato in Python, ma veloce in Java
Dopo la conversione esso (in pratica la rimozione di operatori di albero e predicati semantici/sintattica), ho generato i file python2 utilizzando:
java -jar antlr4.5-complete.jar -Dlanguage=Python2 CPPGrammar.g4
E il codice viene generato senza alcun errore, in modo da importare nel mio progetto Python (sto usando PyCharm) per fare alcuni test:
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)
Il problema è che l'analisi è molto lenta. Con un file contenente ~ 200 linee ci vogliono più di 5 minuti per completare, mentre l'analisi dello stesso file in antlrworks richiede solo 1-2 secondi. Analizzando l'albero antlrworks, ho notato che la regola expr
e tutti i suoi discendenti sono chiamati molto spesso e penso che ho bisogno di semplificare/modificare queste regole per rendere il parser operare più velocemente:
È la mia ipotesi corretta o ho fatto qualche errore durante la conversione della grammatica? Cosa si può fare per rendere l'analisi veloce come su antlrworks?
UPDATE: Ho esportato la stessa grammatica in Java e sono stati necessari solo 795 ms per completare l'analisi. Il problema sembra più correlato all'implementazione di Python rispetto alla grammatica stessa. C'è qualcosa che può essere fatto per accelerare l'analisi di Python?
Ho letto here che python può essere 20-30 volte più lento di java, ma nel mio caso python è ~ 400 volte più lento!
Devono rispettare i tempi di esecuzione delle regole per avere una certezza. Potrebbe essere l'uso pesante di set negati, letterali nel parser o qualcos'altro che sembra completamente benigno. – GRosenberg
@GRosenberg grazie per il commento. Non sono un esperto di ANTLR, ma non mi sembra che la mia grammatica e quella originale abbiano un sacco di set o letterali negati nel parser. Penso che sia un errore relativo a 'antlr4-python2-runtime' perché ci vuole solo 1 secondo per analizzare lo stesso file su java.Python può essere più lento, ma 400 volte più lento è troppo per pensare che sia un problema dalla mia parte. – Vektor88
Tuttavia, il modo migliore per identificare l'aspetto del tempo di esecuzione che non è performante consiste nel profilare le singole regole e identificare particolari aspetti delle regole che sono lenti da elaborare. Il problema è dalla tua parte solo nel senso che la tua grammatica sta facendo qualcosa per innescare il rallentamento. Quasi sicuramente sarà necessaria una modifica al runtime. La parte difficile è capire cosa aggiustare. La chiave, per fortuna, è da qualche parte nella tua grammatica. Fai ciò che puoi per isolare la causa e crea un problema sul repository di Github di Antlr. Questo è il modo più veloce per farlo riparare. – GRosenberg