代码之家  ›  专栏  ›  技术社区  ›  ahe

在ANTLR中使用固定节点而不是错误节点的AST

  •  1
  • ahe  · 技术社区  · 15 年前

    我有一个使用了C目标的ANTLR生成的Java解析器,它工作得很好。问题是,我还希望它解析错误代码并生成有意义的AST。如果我给它一个带有一个导入的最小Java类,在其中缺少分号时,它会产生两个“树错误节点”对象,其中“导入”令牌和导入类的令牌应该是。

    但是,由于它正确地解析了以下代码并为此代码生成了正确的节点,因此必须通过添加分号或重新同步来从错误中恢复。有没有办法让antlr反映出它在ast内部产生的固定输入?或者,我至少能得到那些以某种方式产生“树节点错误”的标记/文本吗?

    在C目标中 antlr3commontreeadaptor.c 在第200行中,下面的片段表示到目前为止,C目标只创建虚拟错误节点:

    static  pANTLR3_BASE_TREE
    errorNode                               (pANTLR3_BASE_TREE_ADAPTOR adaptor,   pANTLR3_TOKEN_STREAM ctnstream, pANTLR3_COMMON_TOKEN startToken, pANTLR3_COMMON_TOKEN stopToken, pANTLR3_EXCEPTION e)
    {
        // Use the supplied common tree node stream to get another tree from the factory
        // TODO: Look at creating the erronode as in Java, but this is complicated by the
        // need to track and free the memory allocated to it, so for now, we just
        // want something in the tree that isn't a NULL pointer.
        //
        return adaptor->createTypeText(adaptor, ANTLR3_TOKEN_INVALID, (pANTLR3_UINT8)"Tree Error Node");
    }
    

    我在这里运气不好,只有Java目标产生的错误节点允许我检索错误节点的文本吗?

    2 回复  |  直到 15 年前
        1
  •  0
  •   nategoose    15 年前

    我没有使用过很多antlr,但通常情况下,处理这种类型错误的方法是添加匹配错误语法的规则,使它们产生错误节点,并尝试在错误之后修复,以便继续解析。事后修复是个问题,因为在结束之前,您不希望一个错误为每个新令牌触发越来越多的错误。

        2
  •  0
  •   ahe    15 年前

    我通过在语法中为所有可能的错误语句添加新的替换规则来解决这个问题。

    每个Java导入语句都被翻译成AST子树,例如以人工符号导入为根。为了确保区分AST和正确代码和错误代码,错误语句的规则使用前缀为err_u的根符号将其重写为AST,因此在import语句的示例中,人工根符号将为err_u import。

    可以使用更多不同的根符号来编码有关分析错误的更详细信息。

    我的解析器现在和我需要的一样具有容错性,每当我需要时,很容易为新类型的错误输入添加规则。不过,你必须注意不要在语法中引入任何歧义。