1

我希望让 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.
4

1 回答 1

2

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

  1. (ANTLR 3/4) 将你的语法重写为 LL(1)。
  2. (ANTLR 3/4) 将你的语法重写为主要是 LL(1),然后手写错误恢复代码,为每个剩余的非 LL(1) 决策获取有用的信息。
  3. (仅限 ANTLR 4)编写修改后的 ANTLR 运行时,它作为通用解析器运行,允许并保留歧义。
  4. (非 ANTLR)在 ANTLR 4 出现之前,我还编写了一个基于 NFA 模拟的自定义解析器,用于 Visual Studio 的最新 ANTLR 3 扩展。这种方法不如选项 3 好用,所以我计划最终更换它。

对于我正在进行的 IDE 工作,此时我只使用选项 3。选项 2 在选项 3 存在之前提供了可接受的支持(GoWorks 不存在用于比较,因此当创建 nFringe 时,它​​通常被视为例外)。

于 2013-04-30T13:15:20.817 回答