python - 导入后ANTLR4语法标记识别错误

标签 python parsing antlr antlr4

我正在使用 parser grammarlexer grammar用于来自 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; }。然而在 python 脚本中,我们仍然需要使用来自 PHPLexer 的词法分析器来使其工作。好吧,这个 PHPParentLexer 根本不可用。这就是为什么你得到了所有的错误。

要从组合语法中生成新的词法分析器,您需要像这样导入它:

grammar PHPParent;
import PHPLexer;

但是,导入时不支持modePHPLexer 本身就大量使用了mode。所以这也不是一个选择。

我们可以简单地将 PHPParentLexer 替换为 PHPLexer 吗?可悲的是没有。因为 PHPParentParser 是用 PHPParentLexer 生成的,所以它们是紧耦合的,不能单独使用。如果您使用 PHPLexerPHPParentParser 也将不起作用。至于这个语法,感谢错误恢复,它确实有效,但给出了一些错误。

似乎没有更好的办法,只能重写一些语法。 ANTLR4的这个import部分肯定有一些设计问题。

关于python - 导入后ANTLR4语法标记识别错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29630026/

相关文章:

json - 从 Itunes API 解包 JSON - IOS App

python - 为什么不是数组[:] copying the array?

excel - 使用字符串操作从 Excel 解析文本文件

创建从字典键到它的值的所有组合的 Pythonic 方法

java - 子级的 JSoup 格式输出

antlr - "!"、 "^"和 "$"在 Antlr3 中是否有特殊含义?

antlr - 如何在 Antlr 语法中抛出异常

ANTLR4 - 如何指定行不以特定字符开头?

python - 删除具有重复列 pandas 数据框的行 (Python)

python - Perforce - 创建和编辑更改列表