abstract sclass CtxExpr { // assumes that ctxContext() is set abstract bool get() { r S str() { ret get() ? "true" : "false"; } } abstract sclass CtxGeneral extends CtxExpr { bool get() { ret eqic(str(), "true"); } } abstract sclass CtxBool extends CtxExpr { S str() { ret get() ? "true" : "false"; } } CtxGeneral > CtxConst { S value; *() {} *(S *value) {} // assume it's a regexp when queried with get() // and a string constant when queried with str() S str() { ret value; } bool get() { ret ctxEvalPattern(pattern, value); } } CtxGeneral > CtxVar { S var; *() {} *(S *var) {} S str() { ret ctxGetVar(var); } } CtxBool > CtxNeg { CtxExpr e; *() {} *(CtxExpr *e) {} bool get() { ret !e.get(); } } CtxBool > CtxAnd { CtxExpr a, b; *() {} *(CtxExpr *a, CtxExpr *b) {} bool get() { ret a.get() && b.get(); } } CtxBool > CtxOr { CtxExpr a, b; *() {} *(CtxExpr *a, CtxExpr *b) {} bool get() { ret a.get() || b.get(); } } CtxBool > CtxRegexp { S pattern; *() {} *(S *pattern) {} bool get() { ret ctxEvalPattern(pattern); } } CtxBool > CtxComp { CtxExpr a, b; *() {} *(CtxExpr *a, CtxExpr *b) {} bool get() { ret eq(a.str(), b.str()); } } CtxBool > CtxUneq { S var1, var2; *() {} *(S *var1, S *var2) {} bool get() { ret neq(a.str(), b.str()); } } CtxBool > CtxMatch { CtxExpr var; S pattern; *() {} *(CtxExpr *var, S *pattern) {} bool get() { ret ctxEvalPattern(pattern, var.str()); } }