Parse和Tree尽可能多的输入?

时间:2013-04-30 01:18:21

标签: antlr antlr3

我希望尽可能多地使用antlr来解析/树,以便信息可用于智能感知。也许这是错误的方法,但似乎是在输入不是100%有效时获得正确信息的唯一方法。

语法具有以分号分隔的语句。我特别想要的是antlr尝试解析/树分割由分号分隔的所有内容。含义1破坏的语句不应该阻止解析其他语句。

我能够使用以下内容轻松地将其添加到解析器语法中。

statements
    :   (statement (a=semicolon statement)*  b=semicolon?) -> ^(BLOCK statement ($a statement)* $b?)
    ;
semicolon //Consume invalid tokens until we find a SEMICOLON.
    :   { while(input.LA(1) != EOF && input.LA(1) != SEMICOLON) input.Consume(); } SEMICOLON
    ;

工作正常。以下是我为树重写所尝试的内容,消费不起作用。

block returns [Statement block = null]
@init{  var statements = new List<Statement>(); }
    :   ^(t=BLOCK (s=statement { statements.Add(s); }) (semicolon s=statement { statements.Add(s); }))* semicolon?) { block = new Statement(li(t), statements); }
    ;
semicolon
    :   { while(input.LA(1) != EOF && input.LA(1) != SEMICOLON) input.Consume(); } SEMICOLON
    ;

查看已编译的代码显示它在使用之前查找分号。哪个不起作用,因为分号前有无效的标记。

以下是我目前处理解析器规则错误的方法。

rule : (A B c) => A^ B c
     | A B { c(); } //Calling c reports the error without throwing an exception.

1 个答案:

答案 0 :(得分:2)

根据我的经验,有三种方法可以从ANTLR获取准确的信息,以用于代码完成和其他IDE功能。免责声明:我是以下所有项目的作者。

  1. (ANTLR 3/4)将你的语法重写为LL(1)。
  2. (ANTLR 3/4)将您的语法重写为LL(1),然后手写错误恢复代码以获取每个剩余的非LL(1)决策的有用信息。
  3. (仅限ANTLR 4)编写修改后的ANTLR运行时,该运行时作为通用解析器运行,允许并保留歧义。
    • 此方法用于Tunnel Vision Labs' GoWorks代码完成和其他功能(页面包含从5:01开始的代码完成功能的视频)。
  4. (非ANTLR)在ANTLR 4存在之前,我还编写了一个基于NFA模拟的自定义解析器,用于最新的ANTLR 3 extension for Visual Studio。这种方法不如选项3那么好,所以我打算最终更换它。
  5. 对于我正在进行的IDE工作,此时我只使用选项3。选项2在选项3存在之前提供了可接受的支持(GoWorks不存在用于比较,因此当创建nFringe时,它通常被视为例外)。