/// <summary>
        /// Parses the specified text converting it into a expression action.
        /// </summary>
        /// <param name="text">The text to parse.</param>
        /// <returns></returns>
        public Expression <Func <decimal> > Parse(string text)
        {
            var body = language.Parse(text);

            body = ExpressionConversions.Convert(body, typeof(decimal));
            return(Expression.Lambda <Func <decimal> >(body));
        }
        /// <summary>
        /// Returns the definitions for logic operators used within the language.
        /// </summary>
        /// <returns></returns>
        protected virtual IEnumerable <GrammerDefinition> LogicalOperatorDefinitions()
        {
            return(new GrammerDefinition[]
            {
                new BinaryOperatorDefinition(
                    name: "EQ",
                    regex: @"\b(eq)\b",
                    orderOfPrecedence: 11,
                    expressionBuilder: ConvertEnumsIfRequired((left, right) => Expression.Equal(left, right))),
                new BinaryOperatorDefinition(
                    name: "NE",
                    regex: @"\b(ne)\b",
                    orderOfPrecedence: 12,
                    expressionBuilder: ConvertEnumsIfRequired((left, right) => Expression.NotEqual(left, right))),

                new BinaryOperatorDefinition(
                    name: "GT",
                    regex: @"\b(gt)\b",
                    orderOfPrecedence: 13,
                    expressionBuilder: (left, right) => Expression.GreaterThan(left, right)),
                new BinaryOperatorDefinition(
                    name: "GE",
                    regex: @"\b(ge)\b",
                    orderOfPrecedence: 14,
                    expressionBuilder: (left, right) => Expression.GreaterThanOrEqual(left, right)),

                new BinaryOperatorDefinition(
                    name: "LT",
                    regex: @"\b(lt)\b",
                    orderOfPrecedence: 15,
                    expressionBuilder: (left, right) => Expression.LessThan(left, right)),
                new BinaryOperatorDefinition(
                    name: "LE",
                    regex: @"\b(le)\b",
                    orderOfPrecedence: 16,
                    expressionBuilder: (left, right) => Expression.LessThanOrEqual(left, right)),

                new BinaryOperatorDefinition(
                    name: "AND",
                    regex: @"\b(and)\b",
                    orderOfPrecedence: 17,
                    expressionBuilder: (left, right) => Expression.And(left, right)),
                new BinaryOperatorDefinition(
                    name: "OR",
                    regex: @"\b(or)\b",
                    orderOfPrecedence: 18,
                    expressionBuilder: (left, right) => Expression.Or(left, right)),

                new UnaryOperatorDefinition(
                    name: "NOT",
                    regex: @"\b(not)\b",
                    orderOfPrecedence: 19,
                    operandPosition: RelativePosition.Right,
                    expressionBuilder: (arg) => {
                    ExpressionConversions.TryBoolean(ref arg);
                    return Expression.Not(arg);
                })
            });
        }
Esempio n. 3
0
        /// <summary>
        /// Returns the definitions for logic operators used within the language.
        /// </summary>
        /// <returns></returns>
        protected override IEnumerable <GrammerDefinition> LogicalOperatorDefinitions()
        {
            return(new GrammerDefinition[]
            {
                new BinaryOperatorDefinition(
                    name: "EQ",
                    regex: @"eq",
                    orderOfPrecedence: 11,
                    expressionBuilder: ConvertEnumsIfRequired((left, right) => Expression.Equal(left, right))),
                new BinaryOperatorDefinition(
                    name: "NE",
                    regex: @"ne",
                    orderOfPrecedence: 12,
                    expressionBuilder: ConvertEnumsIfRequired((left, right) => Expression.NotEqual(left, right))),

                new BinaryOperatorDefinition(
                    name: "GT",
                    regex: @"gt",
                    orderOfPrecedence: 13,
                    expressionBuilder: (left, right) => Expression.GreaterThan(left, right)),
                new BinaryOperatorDefinition(
                    name: "GE",
                    regex: @"ge",
                    orderOfPrecedence: 14,
                    expressionBuilder: (left, right) => Expression.GreaterThanOrEqual(left, right)),

                new BinaryOperatorDefinition(
                    name: "LT",
                    regex: @"lt",
                    orderOfPrecedence: 15,
                    expressionBuilder: (left, right) => Expression.LessThan(left, right)),
                new BinaryOperatorDefinition(
                    name: "LE",
                    regex: @"le",
                    orderOfPrecedence: 16,
                    expressionBuilder: (left, right) => Expression.LessThanOrEqual(left, right)),

                new BinaryOperatorDefinition(
                    name: "AND",
                    regex: @"and",
                    orderOfPrecedence: 17,
                    expressionBuilder: (left, right) => Expression.AndAlso(left, right)),
                new BinaryOperatorDefinition(
                    name: "OR",
                    regex: @"or",
                    orderOfPrecedence: 18,
                    expressionBuilder: (left, right) => Expression.OrElse(left, right)),

                new UnaryOperatorDefinition(
                    name: "NOT",
                    regex: @"not",
                    orderOfPrecedence: 19,
                    operandPosition: RelativePosition.Right,
                    expressionBuilder: (arg) => {
                    ExpressionConversions.TryBoolean(ref arg);
                    return Expression.Not(arg);
                })
            });
        }
        /// <summary>
        /// Parses the specified text converting it into an expression. The expression can take a single parameter
        /// </summary>
        /// <typeparam name="T">the type of the parameter.</typeparam>
        /// <param name="text">The text to parse.</param>
        /// <returns></returns>
        public Expression <Func <T, decimal> > Parse <T>(string text)
        {
            var parameters = new[] { Expression.Parameter(typeof(T)) };
            var body       = language.Parse(text, parameters);

            body = ExpressionConversions.Convert(body, typeof(decimal));
            return(Expression.Lambda <Func <T, decimal> >(body, parameters));
        }
        /// <summary>
        /// Parses the specified text converting it into a predicate expression
        /// </summary>
        /// <typeparam name="T">The input type</typeparam>
        /// <param name="text">The text to parse.</param>
        /// <returns></returns>
        public Expression <Func <T, bool> > Parse <T>(string text)
        {
            var parameters = new[] { Expression.Parameter(typeof(T)) };
            var body       = language.Parse(text, parameters);

            ExpressionConversions.TryBoolean(ref body);

            return(Expression.Lambda <Func <T, bool> >(body, parameters));
        }
        /// <summary>
        /// Wraps the function to convert any constants to enums if required
        /// </summary>
        /// <param name="expFn">Function to wrap</param>
        /// <returns></returns>
        protected Func <Expression, Expression, Expression> ConvertEnumsIfRequired(Func <Expression, Expression, Expression> expFn)
        {
            return((left, right) =>
            {
                var didConvertEnum = ExpressionConversions.TryEnumNumberConvert(ref left, ref right) ||
                                     ExpressionConversions.TryEnumStringConvert(ref left, ref right, ignoreCase: true);

                return expFn(left, right);
            });
        }
Esempio n. 7
0
        /// <summary>
        /// Applies the bracket operands. Executes the expressionBuilder with all the operands in the brackets.
        /// </summary>
        /// <param name="bracketOpen">The operator that opened the bracket.</param>
        /// <param name="bracketOperands">The list of operands within the brackets.</param>
        /// <param name="bracketClose">The operator that closed the bracket.</param>
        /// <param name="state">The current parse state.</param>
        /// <exception cref="FunctionArgumentCountException">When the number of opreands does not match the number of arguments</exception>
        /// <exception cref="FunctionArgumentTypeException">When argument Type does not match the type of the expression</exception>
        /// <exception cref="OperationInvalidException">When an error occured while executing the expressionBuilder</exception>
        public override void ApplyBracketOperands(Operator bracketOpen, Stack <Operand> bracketOperands, Operator bracketClose, ParseState state)
        {
            var operandSource     = StringSegment.Encompass(bracketOperands.Select(x => x.SourceMap));
            var functionArguments = bracketOperands.Select(x => x.Expression);

            //if we have been given specific argument types validate them
            if (ArgumentTypes != null)
            {
                var expectedArgumentCount = ArgumentTypes.Count;
                if (expectedArgumentCount != bracketOperands.Count)
                {
                    throw new FunctionArgumentCountException(
                              operandSource,
                              expectedArgumentCount,
                              bracketOperands.Count);
                }

                functionArguments = bracketOperands.Zip(ArgumentTypes, (o, t) => {
                    try
                    {
                        return(ExpressionConversions.Convert(o.Expression, t));
                    }
                    catch (InvalidOperationException)
                    {
                        //if we cant convert to the argument type then something is wrong with the argument
                        //so we will throw it up
                        throw new FunctionArgumentTypeException(o.SourceMap, t, o.Expression.Type);
                    }
                });
            }

            var        functionSourceMap      = StringSegment.Encompass(bracketOpen.SourceMap, operandSource);
            var        functionArgumentsArray = functionArguments.ToArray();
            Expression output;

            try
            {
                output = ExpressionBuilder(functionArgumentsArray);
            }
            catch (Exception ex)
            {
                throw new OperationInvalidException(functionSourceMap, ex);
            }
            if (output != null)
            {
                state.Operands.Push(new Operand(output, functionSourceMap));
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="BinaryOperatorDefinition"/> class.
 /// </summary>
 /// <param name="name">The name of the definition.</param>
 /// <param name="regex">The regex to match tokens.</param>
 /// <param name="orderOfPrecedence">The relative order this operator should be applied. Lower orders are applied first.</param>
 /// <param name="expressionBuilder">The function given the single operand expressions, outputs a new operand.</param>
 public BinaryOperatorDefinition(string name,
                                 string regex,
                                 int orderOfPrecedence,
                                 Func <Expression, Expression, Expression> expressionBuilder)
     : base(
         name: name,
         regex: regex,
         orderOfPrecedence: orderOfPrecedence,
         paramaterPositions: LeftRight,
         expressionBuilder: param =>
 {
     var left  = param[0];
     var right = param[1];
     ExpressionConversions.TryImplicitlyConvert(ref left, ref right);
     return(expressionBuilder(left, right));
 })
 {
 }