ANTLR解析器与手动词法分析器

9

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

Antlr通常能够大多数地工作,但是总会有一些小部分不能正常运行,让我头疼不已。

我发现Antlr词法分析器部分引起了大部分问题,而不是语法分析器。然后我注意到parser grammar X;,意识到我可以拥有自己手写的词法分析器和Antlr生成的语法分析器。

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


我的建议是你可以从现有的代码中学习。然而,我只能找到使用Antlr的NHibernate,而且使用范围相当有限。 :( - Lex Li
“但是,总会有一些小部分不尽如人意,让人难以解决。” - 奇怪的是,语言的词法分析部分通常比较容易实现。也许您可以解释一下哪些“小部分”给您带来了问题? - Bart Kiers
@Bart Kiers 我在实现范围和其他一些功能(例如3.toString()和3.0.toString())方面遇到了麻烦,而且我想以不同于FAQ中列出的方式来解决这些问题。这些问题在手动创建的词法分析器中非常容易解决。 - luiscubal
抱歉,我不知道“实现范围的问题”和“其他功能(例如3.toString()和3.0.toString())”是什么意思。我也不知道“他们的常见问题解答”是什么。如果您不打算在ANTLR中解决此问题,则无需解释自己,但如果您有兴趣,请编辑原始问题并说明您在ANTLR词法分析器中无法完成的内容。 - Bart Kiers
@Bart Kiers,我现在找到了答案,所以我很满意。如果我想探索使用Antlr生成的词法分析器的可能性,那么我一定会发布一个单独的问题。顺便说一下,“他们的FAQ”是指“Antlr的FAQ”,范围意味着像“1..2”这样的东西,而3.toString()/3.0.toString()的意思就是:在没有Antlr对'.'的多种可能含义死得很惨的情况下获得数字字段(或在这种情况下的方法)。 - luiscubal
1个回答

8

我找到了方法。这可能不是最好的方法,但它似乎确实有效。

  1. Antlr解析器接收一个ITokenStream参数
  2. Antlr词法分析器本身就是ITokenSource
  3. ITokenSourceITokenStream接口简单得多
  4. ITokenSource转换为ITokenStream的最简单方法是使用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标记的方法。同时,TokenQueue必须实现ITokenSource
请注意,正确设置标记变量非常重要。最初,我因为计算错误的CharPositionInLine而遇到了一些问题。如果这些变量设置不正确,那么解析器可能会失败。 另外,普通通道(非隐藏)为0。
到目前为止,这对我来说似乎有效。我希望其他人也会发现它有用。我接受反馈意见。特别是,如果您找到更好的解决方法,请随时发布单独的回复。

干得好,你是如何处理.tokens文件的?我正在尝试做类似的事情,只不过使用pygments词法分析器。 - Naveen
@Naveen 我完全不记得对.tokens文件做过任何操作。 - luiscubal
我也用Python让你的方法运行成功了。其他人已经使用jflex和stax。我在github上发布了一个简单的示例:https://github.com/tinku99/antlr-pygments - Naveen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接