python - tomassetti - descargar antlr4
Error de reconocimiento de token de gramática ANTLR4 después de la importación (1)
Estoy usando una gramática del analizador y una gramática del lexer para antlr4 de GitHub para analizar PHP en Python3.
Cuando uso estas gramáticas directamente funciona mi código PoC:
antlr-test.py
from antlr4 import *
# from PHPParentLexer import PHPParentLexer
# from PHPParentParser import PHPParentParser
# from PHPParentParser import PHPParentListener
from PHPLexer import PHPLexer as PHPParentLexer
from PHPParser import PHPParser as PHPParentParser
from PHPParser import PHPParserListener as PHPParentListener
class PhpGrammarListener(PHPParentListener):
def enterFunctionInvocation(self, ctx):
print("enterFunctionInvocation " + ctx.getText())
if __name__ == "__main__":
scanner_input = FileStream(''test.php'')
lexer = PHPParentLexer(scanner_input)
stream = CommonTokenStream(lexer)
parser = PHPParentParser(stream)
tree = parser.htmlDocument()
walker = ParseTreeWalker()
printer = PhpGrammarListener()
walker.walk(printer, tree)
lo que da la salida
/opt/local/bin/python3.4 /Users/d/PycharmProjects/name/antlr-test.py
enterFunctionInvocation echo("hi")
enterFunctionInvocation another_method("String")
enterFunctionInvocation print("print statement")
Process finished with exit code 0
Cuando uso la siguiente gramática PHPParent.g4, recibo muchos errores:
grammar PHPParent;
options { tokenVocab=PHPLexer; }
import PHPParser;
Después de intercambiar comentarios sobre las importaciones de pitones, recibo este error
/opt/local/bin/python3.4 /Users/d/PycharmProjects/name/antlr-test.py
line 1:1 token recognition error at: ''?''
line 1:2 token recognition error at: ''p''
line 1:3 token recognition error at: ''h''
line 1:4 token recognition error at: ''p''
line 1:5 token recognition error at: ''/n''
...
line 2:8 no viable alternative at input ''<(''
line 2:14 mismatched input '';'' expecting {<EOF>, ''<'', ''{'', ''}'', '')'', ''?>'', ''list'', ''global'', ''continue'', ''return'', ''class'', ''do'', ''switch'', ''function'', ''break'', ''if'', ''for'', ''foreach'', ''while'', ''new'', ''clone'', ''&'', ''!'', ''-'', ''~'', ''@'', ''$'', <INVALID>, ''Interface'', ''abstract'', ''static'', Array, RequireOperator, DecimalNumber, HexNumber, OctalNumber, Float, Boolean, SingleQuotedString, DoubleQuotedString_Start, Identifier, IncrementOperator}
line 3:28 mismatched input '';'' expecting {<EOF>, ''<'', ''{'', ''}'', '')'', ''?>'', ''list'', ''global'', ''continue'', ''return'', ''class'', ''do'', ''switch'', ''function'', ''break'', ''if'', ''for'', ''foreach'', ''while'', ''new'', ''clone'', ''&'', ''!'', ''-'', ''~'', ''@'', ''$'', <INVALID>, ''Interface'', ''abstract'', ''static'', Array, RequireOperator, DecimalNumber, HexNumber, OctalNumber, Float, Boolean, SingleQuotedString, DoubleQuotedString_Start, Identifier, IncrementOperator}
line 4:28 mismatched input '';'' expecting {<EOF>, ''<'', ''{'', ''}'', '')'', ''?>'', ''list'', ''global'', ''continue'', ''return'', ''class'', ''do'', ''switch'', ''function'', ''break'', ''if'', ''for'', ''foreach'', ''while'', ''new'', ''clone'', ''&'', ''!'', ''-'', ''~'', ''@'', ''$'', <INVALID>, ''Interface'', ''abstract'', ''static'', Array, RequireOperator, DecimalNumber, HexNumber, OctalNumber, Float, Boolean, SingleQuotedString, DoubleQuotedString_Start, Identifier, IncrementOperator}
Sin embargo, no obtengo errores al ejecutar la herramienta antlr4 sobre las gramáticas. Estoy perplejo aquí, ¿qué podría estar causando este problema?
$ a4p PHPLexer.g4
warning(146): PHPLexer.g4:363:0: non-fragment lexer rule DoubleQuotedStringBody can match the empty string
$ a4p PHPParser.g4
warning(154): PHPParser.g4:523:0: rule doubleQuotedString contains an optional block with at least one alternative that can match an empty string
$ a4p PHPParent.g4
warning(154): PHPParent.g4:523:0: rule doubleQuotedString contains an optional block with at least one alternative that can match an empty string
Importar es ANTLR4 es un poco desordenado.
Primero, tokenVocab
no puede generar el lexer que necesita. Solo significa que esta gramática está utilizando los tokens de PHPLexer
. Si elimina PHPLexer.tokens
, ¡ni siquiera se compilará!
Eche un vistazo a PHPParser.g4
donde también usamos las options { tokenVocab=PHPLexer; }
options { tokenVocab=PHPLexer; }
. Sin embargo, en el script de Python todavía necesitamos usar el PHPLexer
de PHPLexer
para que funcione. Bueno, este PHPParentLexer
no es utilizable en absoluto. Es por eso que tienes todo el error.
Para generar un nuevo lexer a partir de la gramática combinada, necesita importarlo así:
grammar PHPParent;
import PHPLexer;
Sin embargo, el mode
no es compatible al importar. PHPLexer
sí usa mucho el mode
. Así que tampoco es una opción.
¿Podemos simplemente reemplazar PHPParentLexer
con PHPLexer
? Tristemente no. Debido a que PHPParentParser
se genera con PHPParentLexer
, están estrechamente acoplados y no se pueden usar por separado. Si usa PHPLexer
, PHPParentParser
tampoco funcionará. En cuanto a esta gramática, gracias a la recuperación de errores, realmente funciona, pero da un error.
Parece que no hay mejor manera que reescribir algo de la gramática. Definitivamente hay algunos problemas de diseño en esta parte de import
de ANTLR4.