遵守以下规则:
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规则 更贪心。
怎么能实现这个目标?
答案 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;