我正在将基于 C# 的编程语言编译器从手动词法分析器/解析器迁移到 Antlr。
Antlr 一直让我很头疼,因为它通常大部分都能正常工作,但也有一些小部分不能正常工作,而且解决起来非常痛苦。
我发现我的大部分头痛是由 Antlr 的词法分析器部分引起的,而不是解析器。然后我注意到 parser grammar X;
并意识到也许我可以使用我手动编写的词法分析器,然后使用 Antlr 生成的解析器。
所以我正在寻找有关此主题的更多文档。我想自定义 ITokenStream 可以工作,但似乎几乎没有关于此主题的在线文档...
最佳答案
我发现了方法。这可能不是最好的方法,但它似乎确实有效。
- Antlr 解析器接收一个
ITokenStream
参数 - Antlr 词法分析器本身就是
ITokenSource
ITokenSource
是一个比ITokenStream
简单得多的接口(interface)
- 将
ITokenSource
转换为ITokenStream
的最简单方法是使用CommonSourceStream
,它接收ITokenSource
参数
所以现在我们只需要做两件事:
- 将语法调整为仅解析器
- 实现 ITokenSource
调整语法非常简单。只需删除所有词法分析器声明并确保将语法声明为 parser grammar
。为方便起见,此处发布了一个简单示例:
parser grammar mygrammar;
options
{
language=CSharp2;
}
@parser::namespace { MyNamespace }
document: (WORD {Console.WriteLine($WORD.text);} |
NUMBER {Console.WriteLine($NUMBER.text);})*;
请注意,以下文件将输出 class mygrammar
而不是 class mygrammarParser
。
所以现在我们要实现一个“假的”词法分析器。 我个人使用了以下伪代码:
TokenQueue q = new TokenQueue();
//Do normal lexer stuff and output to q
CommonTokenStream cts = new CommonTokenStream(q);
mygrammar g = new mygrammar(cts);
g.document();
最后,我们需要定义TokenQueue
。 TokenQueue
不是绝对必要的,但我使用它是为了方便。
它应该有接收词法分析器标记的方法,以及输出 Antlr 标记的方法。因此,如果不使用 Antlr native token ,则必须实现一种转换为 Antlr token 的方法。
此外,TokenQueue
必须实现 ITokenSource
。
请注意,正确设置 token 变量非常重要。最初,我遇到了一些问题,因为我错误地计算了 CharPositionInLine
。如果这些变量设置不正确,那么解析器可能会失败。
此外,正常 channel (未隐藏)为 0。
到目前为止,这似乎对我有用。我希望其他人也觉得它有用。 我愿意接受反馈。特别是,如果您找到更好的方法来解决这个问题,请随时发表单独的回复。
关于c# - 带有手动词法分析器的 ANTLR 解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4414166/