如何在ANTLR4中实现错误处理

时间:2014-02-06 20:31:37

标签: java error-handling antlr4

我有以下语法来解析应用于图形的一阶逻辑公式:

grammar Graph;


/*------------------------------------------------------------------
* PARSER RULES
*------------------------------------------------------------------*/

input
: 
formula EOF
;

formula
:
TRUE 
| FALSE 
| formula AND formula
| formula OR formula
| quantifier formula
| ST condition
;


condition
:
atom EQUALS QUOTE? (assignment | atom) QUOTE?
;

quantifier 
:
(FOREACH | EXISTS) variable IN domain
;

domain
:
(GRAPH_A | GRAPH_B)
;

atom
:
variable DOT property
;


variable
:   
(nodev | edgev)
;


nodev
:
(NODE | NODE1)
;

edgev
:
(EDGE | EDGE1)
;

property
:
(COLOR | VALUE)
;

assignment
:
(COLORTYPE | NUMBER)
;


/*------------------------------------------------------------------
* LEXER RULES
*------------------------------------------------------------------*/

TRUE : 'True' ;

FALSE : 'False' ;

AND : '&' ;

OR : '|' ;

ST : '->' ; 

EXISTS  : 'Exists' ;

FOREACH : 'Foreach' ;

NODE : 'node' ;

NODE1 : 'node1' ;

EDGE : 'edge' ;

EDGE1 : 'edge1' ;

IN : 'in' ;

GRAPH_A : 'GraphA' ;

GRAPH_B : 'GraphB' ;

EQUALS : '=' ;

DOT : '.' ;

COLOR : 'color' ;

VALUE : 'value' ;

NUMBER : ('0'..'9')+ (DOT ('0'..'9')+)? ;

QUOTE : '\'' ;

COLORTYPE : ('a'..'z')+ ;

WS : [ \t\r\n]+ -> skip ;

我相信这是我的语法的最终版本所以现在我想为输入指定一些错误处理。问题是我不知道怎么做。我所知道的是,在我解析输入后,我可以迭代生成的AST,这是添加错误处理的地方。

如果解析失败,则返回解析异常;否则,我已指定以下情况返回错误消息。

  1. 条件等于-> condition时,不能有1个量词,后跟atom=atom(这是一个公式元素)。换句话说,如果只有quantifier,那么condition应该等于atom EQUALS assignment

  2. 如果有2个量词,则第一个应以FOREACH

  3. 开头
  4. 量词中的变量应在condition陈述中使用

  5. 在表达式的左侧不能有两个以上的量词(因为在我正在开发的应用程序中,只有两个图形)。因此,如果量词的数量大于那么两个返回错误

  6. 如果有2个量词,那么它们应该有不同的变量绑定

  7. 例如,当我们作为输入

    时,应该引发第一种情况
    Exists node in GraphA -> node.color = node1.color 
    

    因为node1未在表达式的左侧指定。

    第二种情况的例子是以下输入

    Exists node in GraphA Exists node1 in GraphB -> node.color = node1.color
    

    所以我的问题是我是否必须对生成的解析树实现所有错误检查,或者我可以使用一些java代码在语法中指定一些错误检查。如果在解析输入后发生错误处理,我可以使用ANTLR 4的哪些功能来实现错误情况?任何帮助或建议将不胜感激!

1 个答案:

答案 0 :(得分:6)

您可能希望在侦听器中与辅助访问者一起实现这些语义检查。以下是一些例子。

规则:quantifier中的变量应在condition

中使用

实现:

  1. 创建一个访问者,该访问者返回指定的分析树节点使用的变量。您需要覆盖defaultResult()aggregateResult(T, T)以完成大部分工作,然后覆盖visitNodevvisitEdgev以处理正在使用的特定变量。
  2. 在您的侦听器中,覆盖enterFormula方法。在此方法中,如果ctx.quantifier()不为null,则使用您的访问者获取ctx.quantifier()中声明的变量列表以及ctx.formula()中使用的变量列表。
  3. 根据两个结果报告错误。
  4. 规则:如果有2个量词,那么它们应该绑定不同的变量

    实现:

    1. 从上一个规则实施步骤1中描述的访问者开始。
    2. 在您的侦听器中,覆盖enterFormula方法。在该方法中,如果ctx.quantifier()不为null,则需要获取QuantifierContext返回的树下所有其他ctx.formula()个实例的集合。您可以致电XPath.findAll(ctx.formula(), "//quantifier", parser)
    3. 来完成此操作
    4. 使用上述访问者收集每个链接的QuantifierContext实例中声明的变量列表。如果任何集重叠,请报告错误。
    5. 规则:如果有2个量词,则第一个应以FOREACH

      开头

      实现:

      使用上一步中描述的侦听器模式来查找公式包含多个quantifier的情况。如果这些公式中的第一个具有ctx.quantifier().FOREACH() == null,则会在适当时发出错误。

      规则:量词不能超过两个......

      实现:

      如果XPath.findAllQuantifierContext的{​​{1}}中为formula返回多个quantifier,则更新上述第二条规则的实施,以报告错误。

      规则:量词条件限制

      实现:

      首先,创建一个ParseTreePattern对象。

      String patternString = "<quantifier> -> <condition>";
      ParseTreePattern pattern =
          parser.compileParseTreePattern(patternString, GraphParser.RULE_formula);
      

      然后,在解析树中找到此模式的所有实例。

      List<ParseTreeMatch> matches = pattern.findAll(tree, "//formula");
      

      验证匹配非常简单。

      for (ParseTreeMatch match : matches) {
        ConditionContext condition = (ConditionContext)match.get("condition");
        if (condition.assignment() == null) {
          // TODO: report error here
        }
      }