遵循以下规则:
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;