static ScimExpressionParser() { CaseInsensitiveString = from content in QuotedString select ScimExpression.String(content); IdentifierName = Parse.Identifier(Parse.Letter, Parse.LetterOrDigit); //compValue = false / null / true / number / string //; rules from JSON(RFC 7159) Literal = Parse.String("true").Return(ScimExpression.Constant(true)) .XOr(Parse.String("false").Return(ScimExpression.Constant(false))) .XOr(Parse.String("null").Return(ScimExpression.Constant(null))); //ATTRNAME = ALPHA * (nameChar) //nameChar = "-" / "_" / DIGIT / ALPHA // TODO : check - and _ AttrName = IdentifierName.Select(ScimExpression.Attribute); //valuePath = attrPath "[" valFilter "]" // ; FILTER uses sub - attributes of a parent attrPath ValuePath = from open in Parse.Char('[') from expr in Parse.Ref(() => Filter) from close in Parse.Char(']') select new Func <ScimExpression, ScimExpression>(r => ScimExpression.Binary("Where", r, expr)); //subAttr = "." ATTRNAME //; a sub-attribute of a complex attribute SubAttr = Parse.Char('.') .Then(_ => IdentifierName) .Then(n => Parse.Return(new Func <ScimExpression, ScimExpression>(r => ScimExpression.SubAttribute(n, r)))); //attrPath = [URI ":"] ATTRNAME * 1subAttr // ; SCIM attribute name // ; URI is SCIM "schema" URI AttrPath = AttrName .SelectMany(root => SubAttr.XOr(ValuePath).XMany(), (name, path) => path.Aggregate(name, (o, f) => f(o))); Operand = (ExpressionInParentheses .XOr(Literal.Or(AttrPath.Token())) .XOr(CaseInsensitiveString)).Token(); // compareOp = "eq" / "ne" / "co" / // "sw" / "ew" / // "gt" / "lt" / // "ge" / "le" Comparison = Parse.XChainOperator(Le.Or(Lt).XOr(Ge.Or(Gt)).XOr(Eq.Or(Ne)).XOr(Sw.Or(Ew)).XOr(Co).XOr(Pr), Operand, ScimExpression.Binary); // attrPath SP "pr" Presence = Operand.SelectMany(operand => Pr, (operand, pr) => ScimExpression.Unary(pr, operand)); // attrExp = (attrPath SP "pr") / // (attrPath SP compareOp SP compValue) AttributeExpression = Presence.Or(Comparison); // logExp = FILTER SP ("and" / "or") SP FILTER LogicalExpression = Parse.XChainOperator(Or.Or(And), AttributeExpression, ScimExpression.Binary); Filter = LogicalExpression; }
private Expression <Func <TResource, bool> > BuildExpression <TResource>(ScimExpression filter, IAttributeNameMapper mapper, string prefix) { var callExpression = filter as ScimCallExpression; if (callExpression != null && (callExpression.OperatorName == "And" || callExpression.OperatorName == "Or")) { return(this.BindLogicalExpression <TResource>(callExpression, mapper, prefix)); } if (callExpression != null && (callExpression.OperatorName != "And" || callExpression.OperatorName != "Or")) { return(this.BindAttributeExpression <TResource>(callExpression, mapper)); } throw new InvalidOperationException("Unknown node type"); }
public Expression <Func <TResource, bool> > Bind <TResource>(ScimExpression filter, string sortBy, bool ascending, IAttributeNameMapper mapper = null) { return(this.BuildExpression <TResource>(filter, mapper, null)); }
public static ScimExpression SubAttribute(string name, ScimExpression parent) { return(new ScimSubAttributeExpression(name, parent)); }
public static ScimExpression Unary(string opName, ScimExpression operand) { return(new ScimCallExpression(opName, operand)); }
public static ScimExpression Binary(string opName, ScimExpression leftOperand, ScimExpression rightOperand) { return(new ScimCallExpression(opName, leftOperand, rightOperand)); }