Java ANTLR4 Lexer错误报告(违规字符的长度)

Java ANTLR4 Lexer错误报告(违规字符的长度),java,error-handling,antlr4,Java,Error Handling,Antlr4,我正在为一些使用ANTLR4的语言开发一个小型IDE,当lexer无法匹配错误字符时,需要为它们加下划线。在这种情况下,内置实现会向stderr输出一条消息,如下所示: line 35:25 token recognition error at: 'foo\n' 我理解如何获取有关错误的行和列的信息(作为参数传递给syntaxErrorcallback)没有问题,但是如何获取回调中的'foo\n'字符串呢 当解析器是错误源时,它会将有问题的标记作为syntaxError回调的第二个参数传递,因

我正在为一些使用ANTLR4的语言开发一个小型IDE,当lexer无法匹配错误字符时,需要为它们加下划线。在这种情况下,内置实现会向stderr输出一条消息,如下所示:

line 35:25 token recognition error at: 'foo\n'
我理解如何获取有关错误的行和列的信息(作为参数传递给
syntaxError
callback)没有问题,但是如何获取回调中的
'foo\n'
字符串呢

当解析器是错误源时,它会将有问题的标记作为
syntaxError
回调的第二个参数传递,因此提取有关错误输入的开始和停止偏移量的信息变得很简单,参考书中也对此进行了解释。但是,当源是lexer时,情况又如何呢?在本例中,回调中的第二个参数为null,可能是因为lexer未能形成令牌

我需要不匹配字符的长度来知道需要加多少下划线,但是在调试侦听器实现时,我在提供的回调参数中的任何位置都找不到这些信息(除了通过字符串操作从提供的错误消息中提取这些信息,这将是错误的)。
'foo\n'
字符串可能以某种方式获得,那么我缺少什么呢


我怀疑我可能找错了地方,我应该在错误消息形成的地方扩展。你应该编写你的lexer,这样就不可能出现语法错误。在ANTLR 4中,只需添加以下内容作为lexer的最后一条规则,就可以轻松做到这一点:

ErrorChar : . ;
通过这样做,您的错误将从lexer移动到解析器

在某些情况下,您可以在用户在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();
    }
}

事实上,我从其他解析器生成器中了解到了ErrorChar技巧,但出于某种原因,我的印象是ANTLR4词法分析器隐式地实现了这一点。哦,好吧。。回答得很好,谢谢。我可能过早地将此答案标记为适合我的特定问题。虽然在我的lexer语法中添加
ErrorChar
模式后出现的错误消息肯定比前一条有所改进,但我仍然无法在整个有问题的字符串下面划线。只有它的第一个字符被制作成一个令牌——这给我留下了和以前一样的问题。我试图将定义更改为
ErrorChar:.+
但这不起作用。你需要按照答案中的“采取其他步骤”部分进行操作,这一部分对于特定的词法分析器非常具体。这需要我预测用户非法输入的语法,不是吗?不管怎么说,除了你建议的之外,你所做的可能回答了我关于如何获得违规字符串的长度的问题,而不仅仅是它们开始出现的位置。只需要确认一下。我能够使用基于此答案(以及我链接的答案)的解决方案来解决我的问题。非常感谢。