【背景】
之前已经折腾:
【记录】尝试折腾antlr v3的异常处理和错误恢复:VARIABLE的CLASS的值INPUT故意写错为INPUT1
了,现在继续去折腾。
此处,是希望:
当出错时,可以输出更多信息,更加有效的信息,比如堆栈错误,
以便于在调试或允许时,更加清楚错误是错在哪里的。
【折腾过程】
1.继续参考:
The Definitive ANTLR Reference.pdf
看到其中的例子,然后去试试把:
http://media.pragprog.com/titles/tpantlr/code/errors/E2.g
中的相关代码:
@members {
public String getErrorMessage(RecognitionException e,
String[] tokenNames)
{
List stack = getRuleInvocationStack(e, this.getClass().getName());
String msg = null;
if ( e instanceof NoViableAltException ) {
NoViableAltException nvae = (NoViableAltException)e;
msg = " no viable alt; token="+e.token+
" (decision="+nvae.decisionNumber+
" state "+nvae.stateNumber+")"+
" decision=<<"+nvae.grammarDecisionDescription+">>";
}
else {
msg = super.getErrorMessage(e, tokenNames);
}
return stack+" "+msg;
}
public String getTokenErrorDisplay(Token t) {
return t.toString();
}
}加到我自己的.g文件中,变成:
grammar EddlVariableErrorHandle;
/*
Notes:
1. HART EDDL Spec
can find from
hart 7.3 -> SPEC500.pdf, that is Device Description Language Specification
*/
options {
output = AST;
ASTLabelType = CommonTree; // type of $stat.tree ref etc...
//k=3;//debug performance
//filter=true;//debug performance
}
@members {
//override default error handling with more rich error messages
public String getErrorMessage(RecognitionException e,
String[] tokenNames)
{
List stack = getRuleInvocationStack(e, this.getClass().getName());
String msg = null;
if ( e instanceof NoViableAltException ) {
NoViableAltException nvae = (NoViableAltException)e;
msg = " no viable alt; token="+e.token+
" (decision="+nvae.decisionNumber+
" state "+nvae.stateNumber+")"+
" decision=<<"+nvae.grammarDecisionDescription+">>";
}
else {
msg = super.getErrorMessage(e, tokenNames);
}
return stack+" "+msg;
}
public String getTokenErrorDisplay(Token t) {
return t.toString();
}
}
......
common_class : 'ALARM'| 'ANALOG_INPUT'| 'ANALOG_OUTPUT'| 'COMPUTATION'| 'CONTAINED'| 'CORRECTION'| 'DEVICE'| 'DIAGNOSTIC'| 'DIGITAL_INPUT'| 'DIGITAL_OUTPUT'| 'DISCRETE_INPUT'| 'DISCRETE_OUTPUT'| 'DYNAMIC'| 'FREQUENCY_INPUT'| 'FREQUENCY_OUTPUT'| 'HART'| 'INPUT'| 'LOCAL'| 'LOCAL_DISPLAY'| 'OPERATE'| 'OUTPUT'| 'SERVICE'| 'TUNE';
catch [RecognitionException re] {
reportError(re);
consumeUntil(input, SEMICOLON); // throw away all until ';'
//input.consume(); // eat the ';'
//consumeUntil(input, VARIABLE); // throw away all until next VARIABLE
}然后去试试效果:
即,当出错时,输出的内容是:
D:/DevRoot/eclipse/common_root/EddlVariableErrorHandle/src/demoEddlVariableError.ddl line 5:12 [startParse, variable, variable_body, variable_field, variable_class, class_value, single_class_value, common_class] mismatched input [@14,88:93=’INPUT1′,<12>,5:12] expecting set null |
相比之前,没有添加getErrorMessage的时候,所报错的信息:
| D:/DevRoot/eclipse/common_root/EddlVariableErrorHandle/src/demoEddlVariableError.ddl line 5:12 mismatched input ‘INPUT1’ expecting set null |
的确是增加了更多的信息:
(1)stack trace的方面的信息
[startParse, variable, variable_body, variable_field, variable_class, class_value, single_class_value, common_class] |
(2)具体错误的位置信息:从只报错INPUT1错误:
| ‘INPUT1’ |
到报错指出具体位置:
[@14,88:93=’INPUT1′,<12>,5:12] |
【总结】
总体上,通过覆写getErrorMessage后,得到的效果还是很不错的:
当出错时,给出更加精准的信息后,有助于调试发现错误和解决错误。