[英]ANTLR4 grammar token recognition error after import
我正在使用GitHub中的antlr4 解析器語法和詞法分析器語法來解析Python3中的PHP。
當我直接使用這些語法時,我的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)
它給出了輸出
/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
當我使用以下PHPParent.g4語法時,我收到很多錯誤:
grammar PHPParent;
options { tokenVocab=PHPLexer; }
import PHPParser;
在交換關於pythons導入的注釋后,我收到此錯誤
/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}
但是,在語法上運行antlr4工具時,我沒有遇到任何錯誤。 我被困在這里 - 可能導致這個問題的原因是什么?
$ 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
導入是ANTLR4有點亂。
首先, tokenVocab
無法生成所需的詞法分析器。 它只是意味着這個語法使用了PHPLexer
的標記。 如果你刪除PHPLexer.tokens
,它甚至不會編譯!
看看PHPParser.g4
,我們也使用options { tokenVocab=PHPLexer; }
options { tokenVocab=PHPLexer; }
。 然而在python腳本中,我們仍然需要使用PHPLexer
lexer來使其工作。 好吧,這個PHPParentLexer
根本不可用。 這就是你得到所有錯誤的原因。
要從組合語法生成新的詞法分析器,您需要像這樣導入它:
grammar PHPParent;
import PHPLexer;
但是,導入時不支持mode
。 PHPLexer
本身使用了很多mode
。 所以它也不是一個選擇。
我們可以簡單地用PHPParentLexer
替換PHPLexer
嗎? 可悲的是沒有。 因為PHPParentParser
是使用PHPParentLexer
生成的,所以它們是緊密耦合的,不能單獨使用。 如果您使用PHPLexer
, PHPParentParser
也將無法正常工作。 至於這個語法,由於錯誤恢復,它實際上工作,但給出一些錯誤。
似乎沒有更好的方法,但重寫一些語法。 在ANTLR4的這個import
部分肯定存在一些設計問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.