我正在将基于C#的编程语言编译器从手动词法分析器/解析器迁移到Antlr。
Antlr一直给我带来严重的麻烦,因为它通常主要有效,但是有些小部分没有,并且难以解决。
我发现我的大部分头痛都是由Antlr的词法分析器部分而不是解析器引起的。然后我注意到parser grammar X;
并意识到也许我可以手动编写lexer,然后是Antlr生成的解析器。
所以我正在寻找有关此主题的更多文档。我想自定义ITokenStream可以工作,但似乎没有关于这个主题的在线文档...
答案 0 :(得分:7)
我发现了怎么样。它可能不是最好的方法,但它似乎肯定有效。
ITokenStream
参数ITokenSource
s ITokenSource
是比ITokenStream
ITokenSource
转换为ITokenStream
的最简单方法是使用CommonSourceStream
,其中会收到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本机令牌,则必须实现convert-to-Antlr-token方法。
此外,TokenQueue
必须实施ITokenSource
。
请注意,正确设置令牌变量非常重要。最初,我遇到了一些问题,因为我错误地估算了CharPositionInLine
。如果这些变量设置不正确,则解析器可能会失败。
此外,正常通道(未隐藏)为0。
到目前为止,这似乎对我有用。我希望其他人也觉得它很有用。 我愿意接受反馈。特别是,如果您找到更好的方法来解决此问题,请随时发布单独的回复。