遵循以下规则:

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 ist调用了两次(不是我所期望的一次)
它)。

所以这样的代码:

 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;

}


不适用于所有and表达式。

所以以某种方式我会期望exprAnd和exprOr规则是
更贪婪。

一个人怎么能做到这一点?

最佳答案

但是禁止这样的语句:

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



最好是在解析后完成。您的语法接受(并且应该接受)。您只需要随后遍历解析树,并在遍历树时遇到它就拒绝它。


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


如果要将这些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;

09-25 22:06