【背景】
之前已经折腾:
【记录】尝试折腾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后,得到的效果还是很不错的:
当出错时,给出更加精准的信息后,有助于调试发现错误和解决错误。