The way I have done this in the new EL grammar is to treat for_all and there_exists as Boolean leaf objects rather than binary operator, i.e.:
//
// Atomic Boolean-valued expression elements
//
booleanLeaf:
booleanValue
| forAllExpr
| thereExistsExpr
| '(' booleanExpr ')'
| constraintExpr
| SYM_DEFINED '(' valueRef ')'
| arithmeticComparisonExpr
| objectComparisonExpr
| valueRef
;
//
// Universal and existential quantifier
//
forAllExpr: SYM_FOR_ALL localVariableId ':' valueRef '|' booleanExpr ;
thereExistsExpr: SYM_THERE_EXISTS localVariableId ':' valueRef '|' booleanExpr ;
In the next generation object model (BMM) they don’t need matching objects, because for_all is really just syntax for calling a function for_all (lambda(v:T) {expr with v}: Boolean) on a Container type (List, Set etc). I.e. it resolves to a function call that is assumed to exist by the expression compiler.
In the old EL that we have in ADL/AOM2 there is no support for lambdas as such so it might be easier to support for_all and there_exists with model classes that will enable these expressions to be evaluated independently from container types.