我发现了如何。这可能不是最好的方法,但它似乎确实有效。
- Antlr 解析器接收一个
ITokenStream
参数
- Antlr 词法分析器本身
ITokenSource
就是
ITokenSource
是一个简单得多的界面比ITokenStream
ITokenSource
将 a 转换为 a的最简单方法ITokenStream
是使用 a 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-token 的方法。此外,TokenQueue
必须实施ITokenSource
.
请注意,正确设置令牌变量非常重要。最初,我遇到了一些问题,因为我计算错误CharPositionInLine
。如果这些变量设置不正确,则解析器可能会失败。此外,正常通道(未隐藏)为 0。
到目前为止,这似乎对我有用。我希望其他人也觉得它有用。我愿意接受反馈。特别是,如果您找到解决此问题的更好方法,请随时单独回复。