ANTLR4重复AND

时间:2018-04-08 18:29:28

标签: java parsing grammar antlr4 expr

遵守以下规则:

expr:
 '(' expr ')'  #exprExpr
|   expr ( AND expr )+  #exprAnd
|  expr ( OR expr )+  #exprOr
|  atom #exprAtom
|  ID  #exprId
;

atom:
  '[' ID RELOP INT ']'
;

我想允许这样的陈述:

[a<3] and [b<4]
[a<3] or [b<4]
[a<3] or ([b<4]and [c<5])

但禁止这样的陈述:

[a<3] or [b<4] and [c<5]

这个基本思想似乎适用于这种语法。 但有一个方面/副作用,我不明白:

解析具有3个原子的代码(如atom1和atom2和atom3) 方法exprAnd被调用两次(不是一次,正如我所料 它来)。

所以这样的代码:

 public String visitExprAnd(myParser.ExprAndContext ctx)  {
String res = "";
int type=-1;

int nAtoms = ctx.atom().size();
for (int i=0;i<nAtoms;i++) { 
  String s = visit(ctx.expr(i));
}
return s;

}

不能同时对所有和表达式起作用。

所以不知怎的,我原本期望exprAnd和exprOr规则 更贪心。

怎么能实现这个目标?

1 个答案:

答案 0 :(得分:1)

  

但禁止这样的陈述:

[a<3] or [b<4] and [c<5]

解析后最好这样做。你的语法接受这个(它应该)。你只需要在之后走遍解析树,并在树遍历中遇到它时拒绝它。

  

在解析具有3个原子的代码(如atom1和atom2和atom3)时,方法exprAnd被调用两次(不是一次,正如我所期望的那样)。

如果您想将这些AND组合在一起,您应该执行以下操作,而不是将它们全部归为一个expr规则:

orExpr
 : andExpr ( OR andExpr )*
 ;

andExpr
 : atom ( AND atom )*
 ;

atom
 : '(' expr ')'         #atomExpr
 | '[' ID RELOP INT ']' #atomBracket
 | ID                   #atomId
 ;

修改

一个完整的例子:

grammar Test;

parse
 : expr EOF
 ;

expr
 : orExpr
 ;

orExpr
 : andExpr ( OR andExpr )*
 ;

andExpr
 : atom ( AND atom )*
 ;

atom
 : '(' expr ')'            #atomExpr
 | '[' expr RELOP expr ']' #atomBracket
 | ID                      #atomId
 | INT                     #atomInt
 ;

RELOP : [<>] '='?;
AND   : 'and';
OR    : 'or';
INT   : [0-9]+;
ID    : [a-zA-Z_] [a-zA-Z_0-9]*;
SPACE : [ \t\r\n] -> skip;