我有一个使用C目标的antlr生成的Java解析器,它运行良好。问题是我还希望它解析错误的代码并产生有意义的AST。如果我给它一个带有一个导入的最小Java类,之后缺少分号,它会生成两个“Tree Error Node”对象,其中“import”标记和导入类的标记应该是。
但是,由于它正确解析以下代码并为此代码生成正确的节点,因此必须通过添加分号或重新同步来从错误中恢复。有没有办法让antlr反映它在AST内部产生的固定输入?或者,我是否至少可以获得产生“树节点错误”的令牌/文本?
在C目标中 {200}在第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目标生成的错误节点才能让我检索错误节点的文本?
答案 0 :(得分:0)
我没有使用过多的antlr,但通常你处理这类错误的方法是添加规则以匹配错误的语法,使它们产生错误节点,并尝试在错误之后修复,以便你可以继续解析。之后修复是一个问题,因为您不希望一个错误在每个新令牌结束之前触发越来越多的错误。
答案 1 :(得分:0)
我通过在语法中为所有可能的错误陈述添加新的备用规则来解决问题。
每个Java import语句都被转换为AST子树,例如以人工符号IMPORT为根。为了确保我可以区分AST与正确和错误的代码,错误语句的规则将它们重写为带有前缀ERR_的根符号的AST,因此在import语句的示例中,人工根符号将是ERR_IMPORT。
可以使用更多不同的根符号来编码有关解析错误的更详细信息。
我的解析器现在可以像我需要的那样容错,并且每当我需要时,很容易为新类型的错误输入添加规则。不过,你必须注意不要在语法中引入任何含糊之处。