2015-04-14 14 views
17

Używam parser grammar i lexer grammar dla antlr4 z GitHub do parsowania PHP w Python3.Błąd rozpoznawania tokenu gramatyki ANTLR4 po zaimportowaniu

Kiedy używać tych gramatyk bezpośrednio mój kod PoC działa:

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) 

który daje wyjście

/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 

Gdy używam następujący PHPParent.g4 gramatyka, otrzymuję wiele błędów:

grammar PHPParent; 
options { tokenVocab=PHPLexer; } 
import PHPParser; 

Po zamianie komentarzy na temat pytonów importu, otrzymuję ten błąd

/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} 

Jednak mam żadnych błędów podczas uruchamiania narzędzia antlr4 nad gramatyk. Jestem tu zaskoczony - co może być przyczyną tego problemu?

$ 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 
+0

Czy twoja Gramatyka PHPParent składa się tylko z trzech linii? Jeśli nie: ukończyć gramatykę. – CoronA

+0

To robi - chciałem przetestować gramatykę importu w izolacji. – Diarmaid

+0

Jednak mogę tylko powiedzieć, że java nie pozwala na gramatykę bez reguł. Dodałem pseudo regułę: 'myfile: file;' i skompilowałem (i wywołałem plik myfile zamiast pliku w obiekcie analizatora składni). Jednak nie przetestowałem parsera, ponieważ nie mam środowiska python. Czy próbowałeś tego przy użyciu takiej reguły dla delegatów? – CoronA

Odpowiedz

5

Importowanie ANTLR4 jest trochę nieporządne.

Po pierwsze, tokenVocab nie może wygenerować potrzebnego leksera. Oznacza to po prostu, że ta gramatyka używa tokenów o wartości PHPLexer. Jeśli usuniesz PHPLexer.tokens, to nawet nie skompiluje!

Spójrz na PHPParser.g4 gdzie używamy również options { tokenVocab=PHPLexer; }. Jednak w skrypcie pythona nadal musimy używać lexera z PHPLexer, aby to działało. Cóż, ta PHPParentLexer nie jest w ogóle użyteczna. Właśnie dlatego masz cały ten błąd.

Aby wygenerować nowy lexer Spośród gramatyki połączonej, trzeba importować je tak:

grammar PHPParent; 
import PHPLexer; 

Jednak mode nie są obsługiwane podczas importowania. PHPLexer sam często używa mode. Więc nie jest to również opcja.

Czy możemy po prostu wymienić PHPParentLexer na PHPLexer? Niestety nie. Ponieważ PHPParentParser jest generowany z PHPParentLexer, są one ściśle sprzężone i nie mogą być używane osobno. Jeśli używasz PHPLexer, PHPParentParser również nie będzie działać. Jeśli chodzi o tę gramatykę, dzięki odzyskiwaniu błędów, to faktycznie działa, ale daje pewien błąd.

Wydaje się, że nie ma lepszego sposobu, jak przepisać część gramatyki. Zdecydowanie niektóre problemy z projektowaniem w tej części ANTLR4 stanowią import.

Powiązane problemy