ANTLR Parser带有手动词法分析器

lui*_*bal 9 c# antlr parser-generator lexer

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

Antlr一直给我带来严重的头痛,因为它通常大部分都有效,但是有些小部件没有,而且难以解决.

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

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

lui*_*bal 7

我发现了怎么样.它可能不是最好的方法,但它似乎确实有效.

  1. Antlr解析器接收ITokenStream参数
  2. Antlr lexers本身就是ITokenSources
  3. ITokenSource 是一个非常简单的界面 ITokenStream
  4. 将a转换ITokenSource为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);})*;
Run Code Online (Sandbox Code Playgroud)

请注意,将输出以下文件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();
Run Code Online (Sandbox Code Playgroud)

最后,我们需要定义TokenQueue.TokenQueue并非严格必要,但为方便起见,我使用它.它应该有接收词法分析器令牌的方法,以及输出Antlr令牌的方法.因此,如果不使用Antlr本机令牌,则必须实现convert-to-Antlr-token方法.另外,TokenQueue必须实施ITokenSource.

请注意,正确设置标记变量非常重要.最初,我遇到了一些问题,因为我算错了CharPositionInLine.如果这些变量设置不正确,则解析器可能会失败.此外,正常通道(未隐藏)为0.

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