【问题标题】:ANTLR Parser with manual lexer具有手动词法分析器的 ANTLR 解析器
【发布时间】:2010-12-10 23:21:20
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我的建议是可以借鉴现有的。但是,我只能找到使用 Antlr 的 NHibernate,而且用途相当有限。 :(
  • “但是还有一些小部分没有解决,而且解决起来非常痛苦” - 奇怪。语言的词法部分通常更容易实现。也许您可以解释一下哪些“小部件”给您带来了问题?
  • @Bart Kiers 我在实现范围和其他一些功能(例如 3.toString() 和 3.0.toString())时遇到了麻烦,其方式与常见问题解答中列出的方式不同。在手动创建的词法分析器中解决这类问题非常简单。
  • 抱歉,我不知道“实现范围有什么问题”“其他特性(例如3.toString()和3.0.toString()) " 的意思。我也不知道“他们的常见问题” 是什么。如果您不是在寻找在 ANTLR 中执行此操作的方法,则无需解释自己,但如果您有兴趣,请编辑您的原始问题,说明您无法在 ANTLR 词法分析器中做什么。
  • @Bart Kiers 现在,我找到了答案,所以我很满意。如果我确实想探索使用 Antlr 生成的词法分析器的可能性,那么我一定会发布一个单独的问题。但是,顺便说一句,“他们的常见问题解答”表示“Antlr 的常见问题解答”,范围表示“1..2”之类的东西,而 3.toString()/3.0.toString() 的意思正是:获取一个字段(或者,在这种情况下) 一个数字的方法,而没有 Antlr 可怕地死在 '.' 的多种可能含义上。

标签: c# antlr lexer parser-generator


【解决方案1】:

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

  1. Antlr 解析器接收ITokenStream 参数
  2. Antlr 词法分析器本身就是 ITokenSources
  3. ITokenSource 是一个比ITokenStream 简单得多的接口
  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();

最后,我们需要定义TokenQueueTokenQueue 不是绝对必要的,但我使用它是为了方便。 它应该具有接收词法分析器标记的方法和输出 Antlr 标记的方法。因此,如果不使用 Antlr 原生令牌,则必须实现转换为 Antlr-token 的方法。 此外,TokenQueue 必须实现 ITokenSource

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

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

【讨论】:

  • 干得好,你是如何处理 .tokens 文件的?我正在尝试做类似的事情,除了使用 pygments lexers
  • @Naveen 我根本不记得对 .tokens 文件做过任何事情。
  • 我让你的方法与 python 一起工作。其他人则使用 with jflex 和 stax。我在github上发布了一个简单的例子:github.com/tinku99/antlr-pygments
猜你喜欢
  • 2011-01-30
  • 1970-01-01
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多