【背景】
之前用antlr解析eddl,基本的简单的语法,已经支持。
现在需要做的是,去想办法,支持对应的异常处理,可以捕获异常,然后做一些动作。
比如一直忽略掉当前的整段,或者忽略当前的节点。
继续下一个节点去解析。
自己,先弄个了个示例的eddl的variable作为例子:
VARIABLE actuator_function_code
{
LABEL "Actuator function";
CLASS INPUT1;
HANDLING READ&WRITE;
TYPE ENUMERATED
{
{ 0, "Double acting" },
{ 1, "Single acting" }
}
}
VARIABLE set_units
{
LABEL "Setpoint";
CLASS INPUT;
HELP [digital_units_help];
TYPE ENUMERATED
{
{ 57, [Percent], [percent_help] },
{ 143, [degrees], [degrees_help] },
{ 39, [mA], [milliamperes_help] },
{ 49, [mm], [millimeters_help] },
{ 47, [in], [inches_help] },
{ 48, [cm], [centimeters_help] }
}
}
VARIABLE set_value
{
CLASS DYNAMIC & INPUT;
LABEL "Setpoint";
HELP "Setpoint value for the valve positioner. The dynamic value is generated by a control system or manually from an operator";
HANDLING READ&WRITE;
TYPE FLOAT
{
DISPLAY_FORMAT ".1f";
}
}其中actuator_function_code中的INPUT1,是故意写错的,应该是INPUT。
此处,看看能否捕获此异常,并做后续的动作。
【折腾过程】
1.关于antlr的异常处理,官网有些帖子:
2.后来在:
The Definitive ANTLR Reference.pdf
中看到相关的代码:
stat: expr ';'
{System.out.println("found expr: "+$stat.text);}
| ID '=' expr ';'
{System.out.println("found assign: "+$stat.text);}
;
catch [RecognitionException re] {
reportError(re);
consumeUntil(input, SEMI); // throw away all until ';'
input.consume(); // eat the ';'
}然后参考去试试。
3.把其中的代码,加到我当前的语法中:
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 ';'
}是可以实现,consume的效果的:
4.然后,想要实现,当出错时,一直consume,直到下一个别的VARIABLE:
VARIABLE : 'VARIABLE';
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
}结果也是可以实现对应效果的:
5.再去把代码,加到整个的variable的后面试试:
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
}*/
common_validity : 'TRUE' | 'FALSE'; //TODO: add boolean expression
/*******************************************************************************
7.27 VARIABLE
Table 138 – VARIABLE attributes
*******************************************************************************/
variable : VARIABLE variable_identifier '{' variable_body '}';
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
}结果是
即:
无法实现,对于整体VARIABLE中的CLASS的值INPUT1出错后,无法继续consume到下一个VARIABLE。
具体原因,暂时不太懂。
还是需要抽空把如上代码,整合到后续的解析AST的代码中,到解析代码中去调试,才或许能看懂内部逻辑到底如何。
6.从pdf教程中,可以看出,对应语法是:
r : ...
;
catch[RecognitionException e] { throw e; }或:
r : ...
;
catch[FailedPredicateException fpe] { ... }
catch[RecognitionException e] { ...; }或:
r : ...
;
// catch blocks go first
finally { System.out.println("exit rule r"); }7.而关于:RecognitionException
可以从:
的:
The root of the ANTLR exception hierarchy. |
看出:
RecognitionException,是最顶层的异常。
所以,处理一般的异常,就可以直接去捕获对应的RecognitionException,然后写处理代码即可。
另外,如果不想要处理此最底层的异常,则可以去捕获那些特定的异常,比如:
等等。
8.虽然:
是针对于antlr v2的,但是其异常的设计架构,和之后的antlr,也是一样的,值得参考:
9.有空也可以再参考这个帖子:
【总结】
转载请注明:在路上 » 【记录】尝试折腾antlr v3的异常处理和错误恢复:VARIABLE的CLASS的值INPUT故意写错为INPUT1