导入后ANTLR4文法记号识别错误
ANTLR4 grammar token recognition error after import
我正在使用来自 GitHub 的 antlr4 的 parser grammar and a lexer grammar 来解析 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; }
的地方。然而在 python 脚本中,我们仍然需要使用 PHPLexer
中的词法分析器来使其工作。嗯,这个PHPParentLexer
根本就不能用。这就是你得到所有错误的原因。
要从组合语法中生成新的词法分析器,您需要像这样导入它:
grammar PHPParent;
import PHPLexer;
但是,导入时不支持mode
。 PHPLexer
本身经常使用 mode
。所以这也不是一个选择。
我们可以简单地将 PHPParentLexer
替换为 PHPLexer
吗?可悲的是没有。因为 PHPParentParser
是和 PHPParentLexer
生成的,所以它们是紧耦合的,不能单独使用。如果使用 PHPLexer
,PHPParentParser
也不起作用。至于这个语法,感谢错误恢复,它确实有效,但给出了一些错误。
似乎没有更好的办法,只能重写一些语法。 ANTLR4 的 import
部分肯定存在一些设计问题。
我正在使用来自 GitHub 的 antlr4 的 parser grammar and a lexer grammar 来解析 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; }
的地方。然而在 python 脚本中,我们仍然需要使用 PHPLexer
中的词法分析器来使其工作。嗯,这个PHPParentLexer
根本就不能用。这就是你得到所有错误的原因。
要从组合语法中生成新的词法分析器,您需要像这样导入它:
grammar PHPParent;
import PHPLexer;
但是,导入时不支持mode
。 PHPLexer
本身经常使用 mode
。所以这也不是一个选择。
我们可以简单地将 PHPParentLexer
替换为 PHPLexer
吗?可悲的是没有。因为 PHPParentParser
是和 PHPParentLexer
生成的,所以它们是紧耦合的,不能单独使用。如果使用 PHPLexer
,PHPParentParser
也不起作用。至于这个语法,感谢错误恢复,它确实有效,但给出了一些错误。
似乎没有更好的办法,只能重写一些语法。 ANTLR4 的 import
部分肯定存在一些设计问题。