我想创建自己的错误侦听器而不是默认的ANTLR 4错误侦听器,并且我正在使用notifyErrorListeners(String msg(函数,但ANTLR没有给我正确的错误行和位置,这是我的代码。
grammar DSL;
main: 'begin' assign* println* 'end';
assign: name = ID '=' value= (STRING | INTEGER);
println: 'println' value = ID;
fragment LETTER : [A-Za-z];
fragment DIGIT : [0-9];
ID : LETTER+; // match identifiers
/* data types */
STRING : '"' ( ~ '"' )* '"' ; // match string content
INTEGER: DIGIT+ ('.' DIGIT+)*;
LINE_COMMENT: '#' ~[rn]* -> skip;
NEWLINE:'r'? 'n' { skip(); };
WS : ( ' '|'t')+ { skip(); };
public class CustomError extends BaseErrorListener {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
String msg, RecognitionException e) {
System.out.println("line = " + line + ",position = " + charPositionInLine + ",msg = " + msg);
}
}
@Override
public void enterAssign(DSLParser.AssignContext ctx) {
String name = ctx.name.getText();
String value = ctx.value.getText().replace(""", "");
if (tmp_variables.containsKey(name)) {
// How can I get the correct line and position of the error from assignContext ?
dslParser.notifyErrorListeners("duplicate local variable");
} else {
tmp_variables.put(name, value);
}
}
因此,例如,如果我的输入是这样的.
begin
name = "name"
name = "name2"
println name
end
ANTLR 必须具有如下输出。
line = 4,position = 0,msg = duplicate local variable
但输出如下。
line = 7,position = 3,msg = duplicate local variable
在每次执行中,输出总是相同的(7对应于最后一行,3对应于最后一个字符(。 这是为什么呢?
NotifyErrorListeners 用于语法错误,而不是用于报告在树步行器中完成的语义错误。但是,如果您查看运行时的源代码,您将看到 notifyErrorListeners 将 CurrentToken 传递给内部方法。CurrentToken 与树无关,当前树节点甚至没有传递给通知方法。在调用 notifyErrorListeners 时,CurrentToken 位于文件末尾(即正确解析(,即第 7 行。这就是为什么你看到你所看到的。您将希望在侦听器中写出自己的错误消息。您可能需要注意错误在子树AssignContext的第一个标记的值上,而不是行/列处。此外,您应该在整个语法中使用"->跳过"来保持一致。您有两个操作块"{ skip((; }",它们与目标语言无关。