我正在将基于 C# 的编程语言编译器从手动词法分析器/解析器迁移到 Antlr。
Antlr 一直让我头疼,因为它通常mostly可以,但有些小部分却不能,而且解决起来非常痛苦。
我发现我的大部分头痛都是由 Antlr 的词法分析器部分引起的,而不是解析器。然后我注意到parser grammar X;
并意识到也许我可以手动编写词法分析器,然后使用 Antlr 生成的解析器。
因此,我正在寻找有关此主题的更多文档。我想自定义 ITokenStream 可以工作,但似乎几乎没有关于此主题的在线文档......
我知道怎么做了。这可能不是最好的方法,但它似乎确实有效。
- Antlr 解析器接收到
ITokenStream
范围
- Antlr 词法分析器本身就是
ITokenSource
s
-
ITokenSource
是一个比ITokenStream
- 最简单的转换方法
ITokenSource
to a 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 原生令牌,则必须实现一种转换为 Antlr 令牌的方法。
还,TokenQueue
必须执行ITokenSource
.
请注意,正确设置令牌变量非常重要。最初,我遇到了一些问题,因为我计算错误CharPositionInLine
。如果这些变量设置不正确,则解析器可能会失败。
另外,普通通道(未隐藏)为 0。
到目前为止,这似乎对我有用。我希望其他人也觉得它有用。
我愿意接受反馈。特别是,如果您找到更好的方法来解决这个问题,请随时单独回复。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)