当前位置: 首页 > 知识库问答 >
问题:

xtext如何容忍解析错误?

柯建修
2023-03-14

我正在编写一种类似SQL的语言。假设正确的语法是

USE foo;
SELECT * FROM bar;

但我把它打到

US foo;
SELECT * FROM bar;

默认行为是Antlr将停止解析,我丢失了语法高亮显示和大纲视图。错误消息是“US”处缺少EOF。我将IParser重新绑定到RuntimeModule中的自定义解析器

@Override
public Class<? extends org.eclipse.xtext.parser.IParser> bindIParser() {
    return CustomCqlParser.class;
}

重写Parser

@Override
protected InternalCqlParser createParser(XtextTokenStream stream) {
    return new CustomInternalCqlParser(stream, getGrammarAccess());
}

并重写方法handle this partrecoverfrommatchedtoken以使用所有令牌直到分号

@Override
protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException {
    Object out = super.recoverFromMismatchedToken(input, ttype, follow);

    if (out == null) {

        beginResync();
        consumeUntil(input, RULE_T_SEMICOLON);
        input.consume();
        endResync();

        Object matchedSymbol = getCurrentInputSymbol(input);
        System.out.println(matchedSymbol);
        return matchedSymbol;
    }
    return out;
}

在这个匹配符号之后是SELECT,但是语法高亮仍然消失,antlr停止解析。我如何才能实现我的目标?

================编辑==================================

我复制super.recoverFromMismatchToken到我的自定义类,并将其从原始源代码中添加。

if (ttype != EOF) {
    beginResync();
    consumeUntil(input, RULE_T_SEMICOLON);
    input.consume();
    endResync();

    Object matchedSymbol = getCurrentInputSymbol(input);
    input.consume(); // move past ttype token as if all were ok
    return matchedSymbol;
}

如果令牌错误不是在开始时发生,也不是没有可行的替代异常,这将保持语法高亮显示。但是它仍然认为它仍然使用相同的解析规则,而不是开始一个新的规则。此外,如果我在开始时输入了错误的标记,那么预期的标记将是EOF。这将使我的“使用所有令牌直到分号”也失败。

=====================================编辑========================================

跟踪内部CqlParser。java,我发现如果输入错误发生在语句的第一个关键字中,它会得到一个ID并返回。之后我添加了一段代码片段

if (LA1_0 == RULE_IDENT) {
    beginResync();
    consumeUntil(input, RULE_T_SEMICOLON);
    input.consume();
    endResync();
    continue;
}

解析仍在继续,并且在错误语句之后仍保留语法突出显示。然而,错误行没有任何错误标记,我在那行之后失去了内容辅助功能。触发内容辅助的类是语句,但它不再工作。

共有1个答案

谷梁玺
2023-03-14

一般来说,基于lexer的解析器(比如由Antlr/Xtext生成的解析器)并不支持您的请求,因为lexer必须在不知道令牌可能匹配的解析器规则的情况下决定生成哪个令牌。

无论如何,我不建议尝试在Antlr级别解决这个问题,因为您必须在Xtext工具中进行大量定制。

如果可能的话,我建议大家考虑一些根本不涉及语法的替代解决方案:

>

如果您的用例在输入时支持用户,那么定制的自动编辑策略提供者可能是正确的。

如果您想支持用户修复现有查询中的错误,快速修复可能是一种方法(可以与语法错误消息结合使用,参见上面的链接)。

只有当这两个都不是选项,并且你真的想允许这种错误的语法输入时,你才应该尝试在语法层面上修复它。我想你说的是Cassandra的CQL的语法,我猜有不止一种类型的语句(例如select、insert等),因此,涉及被解释为关键字的标识符的黑客由于语法歧义(除了它们的丑陋;-)而不合格。所以我想你必须列出你愿意接受的所有单词作为替代。在这种情况下,我建议为每个关键字的错误类型变体创建一个数据类型规则,并为标识符(包括错误类型变体)创建另一个数据类型规则,因为我猜您不想禁止将“我们”作为标识符。例如。:

Use:
  ('USE' | MistypedUseKeyword) keyspaceName=Identifier ';';

CreateTable: 

MistypedUseKeyword:
  'US' | 'USW' | 'USEE';

MistypedCreateKeyword:
  'CREAT' | 'CREATW' | 'CERATE' | 'CRATE';

MistypedTableKeyword:
  'TABL' | 'TALBE' | 'TBLE' | 'TBALE' | 'TABEL';

MistypedKeyword:
  MistypedUseKeyword | MistypedCreateKeyword | MistypedTableKeyword;

Identifier:
  ID | MistypedKeyword;
 类似资料:
  • Taint(污点)和 Toleration(容忍)可以作用于 node 和 pod 上,其目的是优化 pod 在集群间的调度,这跟节点亲和性类似,只不过它们作用的方式相反,具有 taint 的 node 和 pod 是互斥关系,而具有节点亲和性关系的 node 和 pod 是相吸的。另外还有可以给 node 节点设置 label,通过给 pod 设置 nodeSelector 将 pod 调度到具

  • 问题内容: 我有以下JSON字符串来自外部输入源: 这是格式错误的JSON字符串(“ id”和“ value”必须用引号引起来),但无论如何我都需要对其进行解析。我已经尝试了simplejson和json- py,但似乎无法将其设置为解析此类字符串。 我正在Google App引擎上运行Python 2.5,因此任何基于C的解决方案(例如python-cjson)都不适用。 除了上面列出的JSON

  • 问题内容: 我用antlr 4.4编写了这样的语法: 然后我使用antlr 4.4生成解析器和词法分析器,此过程成功 生成类后,我编写了一些使用语法的Java代码 以上所有代码都是CSV字符串的解析器,例如:““ a”,“ b”,c“ 窗口输出: 我想知道如何从代码背后的方法(getErrors()或…)中获取此错误,而不是由于输出窗口的结果 谁能帮我 ? 问题答案: 使用ANTLR进行CSV解析

  • 我尝试安装< code>Lighttpd,但我得到了以下错误: 正在读取包列表…错误!E: 无法分析包文件/var/lib/dpkg/status(1)E:无法分析或打开包列表或状态文件。 因此,我在互联网上搜索并尝试删除和重新加载包裹列表: @ rasp:~ $ sudo RM/var/lib/apt/lists/*-VF removed '/var/lib/apt/lists/archive

  • null 总之,我有一种感觉,我没有按预定的方式去做。那么,打算的方式是什么呢?我应该如何做语义突出显示?

  • 前不久发布的 Eclipse 3.6—Helios 中包含 Xtext 1.0,一个语言开发框架。 Xtext是一种基于文本的领域特定语言(DSL)开发框架/工具。使用Xtext,你可以轻松的创建自己的编程语言和领域特定语言(DSL)。 对语法器而言,生成一个解析器或者基于语言的Eclipse编辑器(带有代码完成功能)是很有可能的。