1

使用以下规则:

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 规则更加贪婪。

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

4

1 回答 1

1

但禁止这样的陈述:

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

最好在解析后完成。你的语法接受这一点(它应该)。您只需要事后遍历解析树并在树遍历期间遇到它时拒绝它。

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

如果你想将这些ANDs 组合在一起,你应该做这样的事情,而不是在一个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;
于 2018-04-08T19:06:28.027 回答