9

我正在将基于 C# 的编程语言编译器从手动词法分析器/解析器迁移到 Antlr。

Antlr 一直让我头疼不已,因为它通常大部分都有效,但也有一些小部分无法解决,而且解决起来非常痛苦。

我发现我的大部分头痛是由 Antlr 的词法分析器部分引起的,而不是解析器。然后我注意到parser grammar X;并意识到也许我可以拥有我的手动编写的词法分析器,然后是 Antlr 生成的解析器。

因此,我正在寻找有关此主题的更多文档。我想自定义 ITokenStream 可以工作,但似乎几乎没有关于这个主题的在线文档......

4

1 回答 1

8

我发现了如何。这可能不是最好的方法,但它似乎确实有效。

  1. Antlr 解析器接收一个ITokenStream参数
  2. Antlr 词法分析器本身ITokenSource就是
  3. ITokenSource是一个简单得多的界面比ITokenStream
  4. ITokenSource将 a 转换为 a的最简单方法ITokenStream是使用 a CommonSourceStream,它接收一个ITokenSource参数

所以现在我们只需要做两件事:

  1. 将语法调整为仅解析器
  2. 实施 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。

到目前为止,这似乎对我有用。我希望其他人也觉得它有用。我愿意接受反馈。特别是,如果您找到解决此问题的更好方法,请随时单独回复。

于 2010-12-11T01:48:29.033 回答