最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【记录】折腾antlr的异常处理:使得当初错时,输出更详细的错误信息,包含堆栈信息

ANTLR crifan 3165浏览 0评论

【背景】

之前已经折腾:

【记录】尝试折腾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
}

然后去试试效果:

added more stack trace info when error

即,当出错时,输出的内容是:

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后,得到的效果还是很不错的:

当出错时,给出更加精准的信息后,有助于调试发现错误和解决错误。

转载请注明:在路上 » 【记录】折腾antlr的异常处理:使得当初错时,输出更详细的错误信息,包含堆栈信息

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
82 queries in 0.169 seconds, using 22.14MB memory