我正在使用 ANTLR4 为某些语言开发一个小型 IDE,并且需要在词法分析器无法匹配错误字符时给它们下划线。内置的org.antlr.v4.runtime.ANTLRErrorListener http://www.antlr.org/api/Java/org/antlr/v4/runtime/ANTLRErrorListener.html在这种情况下,实现会向 stderr 输出一条消息,类似于:
line 35:25 token recognition error at: 'foo\n'
我可以毫无疑问地理解如何获取有关错误的行和列的信息(作为参数传递给syntaxError
回调),但是我如何获得'foo\n'
回调中的字符串?
当解析器是错误源时,它会将有问题的标记作为第二个参数传递syntaxError
回调,因此提取有关错误输入的开始和停止偏移量的信息变得微不足道,参考书中也对此进行了解释。但是当源是词法分析器时情况又如何呢?在这种情况下,回调中的第二个参数为 null,大概是因为词法分析器无法形成标记。
我需要不匹配字符的长度来知道要下划线多少,但是在调试侦听器实现时,我无法在提供的回调参数中的任何位置找到此信息(除了通过字符串操作从提供的错误消息中提取它之外,这只是错误的)。这'foo\n'
显然可以通过某种方式获得字符串,那么我错过了什么?
我怀疑我可能找错地方了,我应该考虑扩展默认错误策略 http://www.antlr.org/api/Java/org/antlr/v4/runtime/DefaultErrorStrategy.html错误消息形成的地方。
您应该编写词法分析器,以便不可能出现语法错误。在 ANTLR 4 中,只需添加以下内容作为词法分析器的最后一条规则即可轻松完成此操作:
ErrorChar : . ;
通过这样做,您的错误将从词法分析器转移到解析器。
在某些情况下,您可以采取额外的步骤来帮助用户在 IDE 中编辑代码。例如,假设您的语言支持以下形式的双引号字符串,该字符串不能跨越多行:
StringLiteral : '"' ~[\r\n"]* '"';
您可以使用以下一对规则来改进 IDE 中的错误报告:
StringLiteral : '"' ~[\r\n"]* '"';
UnterminatedStringLiteral : '"' ~[\r\n"]*;
然后您可以覆盖emit()
方法来治疗UnterminatedStringLiteral
以一种特殊的方式。结果,用户会看到一条很大的错误消息,而解析器会看到一条StringLiteral
表明它通常可以很好地处理。
@Override
public Token emit() {
switch (getType()) {
case UnterminatedStringLiteral:
setType(StringLiteral);
Token result = super.emit();
// you'll need to define this method
reportError(result, "Unterminated string literal");
return result;
default:
return super.emit();
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)