Esempio n. 1
0
        /// <summary>
        /// Takes the linked list of formed expressions and construct the arithmatic expressions based
        /// on the priority of calculation operators.
        /// Passes:
        /// 1- { "^" }
        /// 2- { "*", "/", "%" /*modulus*/ }
        /// 3- { "+", "-" }
        /// </summary>
        /// <param name="FirstEop"></param>
        /// <returns></returns>
        private Expression ConstructExpression(ExprOp FirstEop)
        {
            //Treat operators as groups
            //  means * and /  are in the same pass
            //  + and - are in the same pass

            // passes depends on priorities of operators.

            // Internal Higher Priority Group
            string[] HigherGroup = { "_h*" /* Higher Multiplication priority used internally in 
                                           * the case of -4  or 5^-3
                                             To be treated like -1_h*4   or 5^-1_h*4
                                           */};

            string[] Group = { "^"    /* Power for normal product '*' */ };


            string[] Group1 = { "*"   /* normal multiplication */, 
                                "/"   /* normal division */, 
                                "%"   /* modulus */ };

            string[] Group2 = { "+", "-" };


            string[] RelationalGroup = { "<", ">", "<=", ">=" };
            string[] EqualityGroup = { "==", "!=" };
            string[] AndGroup = { "and" };
            string[] OrGroup = { "or" };

            string[] AssignmentGroup = { "=" };


            /// Operator Groups Ordered by Priorities.
            string[][] OperatorGroups = { HigherGroup, Group, Group1, Group2, RelationalGroup, EqualityGroup, AndGroup, OrGroup, AssignmentGroup };

            foreach (var opg in OperatorGroups)
            {
                ExprOp eop = FirstEop;

                //Pass for '[op]' and merge it  but from top to child :)  {forward)
                while (eop.Next != null)
                {
                    //if the operator in node found in the opg (current operator group) then execute the logic

                    if (opg.Count(c => c.Equals(eop.Operation, StringComparison.OrdinalIgnoreCase)) > 0)
                    {
                        short skip;
                        eop.ValueExpression = ArithExpression(eop, out skip);

                        //drop eop.Next
                        if (eop.Next.Next != null)
                        {
                            while (skip > 0)
                            {
                                eop.Operation = eop.Next.Operation;

                                eop.Next = eop.Next.Next;

                                skip--;
                            }
                        }
                        else
                        {
                            //no more nodes exit the loop

                            eop.Next = null;      //last item were processed.
                            eop.Operation = string.Empty;
                        }
                    }
                    else
                    {
                        eop = eop.Next;
                    }
                }
            }

            return FirstEop.ValueExpression;
        }
Esempio n. 2
0
        /// <summary>
        /// The primary function that make the expression that will be compiled then evaluated.
        /// </summary>
        /// <param name="tokens"></param>
        /// <returns></returns>
        public Expression FormTheExpression(Token tokens)
        {
            Expression quantityExpression = null;
            ExprOp eop = null;

            ExprOp FirstEop = null;

            int ix = 0;                 //this is the index in the discovered tokens
            while (ix < tokens.Count)
            {
                string q = tokens[ix].TokenValue;
                string op = ix + 1 < tokens.Count ? tokens[ix + 1].TokenValue : string.Empty;

                if (q == "+" || q == "-")
                {
                    // unary prefix operator.

                    //consume another token for number

                    if (q == "+")
                    {
                        //q = tokens[ix].TokenValue;
                        quantityExpression = Expression.Constant(1.0);
                    }
                    else
                    {
                        quantityExpression = Expression.Constant(-1.0);
                    }

                    op = "_h*";
                    ix--;
                    goto ExpressionCompleted;

                }

                if (tokens[ix].TokenClassType == typeof(IfWordToken))
                {
                    // this is an If Word so we need to take all the tokens after it until we find THEN token
                    // and form expression.
                    int ifClosingIndex;
                    Token IfBodyToken = tokens.SubTokens(ix + 1, typeof(ThenWordToken), out ifClosingIndex);

                    int thenClosingIndex;
                    Token ThenBodyToken = null;

                    int elseClosingIndex;
                    Token ElseBodyToken = null;

                    ix = ifClosingIndex;

                    if (ix < tokens.Count)
                    {
                        if (tokens[ifClosingIndex].TokenClassType == typeof(ThenWordToken))
                        {
                            // True part evaluation
                            ThenBodyToken = tokens.SubTokens(ix + 1, typeof(ElseWordToken), out thenClosingIndex);
                            ix = thenClosingIndex;

                            if (ix < tokens.Count)
                            {
                                if (tokens[thenClosingIndex].TokenClassType == typeof(ElseWordToken))
                                {
                                    // True part evaluation
                                    ElseBodyToken = tokens.SubTokens(ix + 1, typeof(ElseWordToken), out elseClosingIndex);

                                    ix = elseClosingIndex;
                                }
                            }
                        }
                    }


                    Expression TestPart = FormTheExpression(IfBodyToken);
                    Expression TruePart;
                    Expression FalsePart;

                    if (ThenBodyToken != null)
                        TruePart = Expression.Convert(FormTheExpression(ThenBodyToken), typeof(object));
                    else
                        TruePart = Expression.Constant(true, typeof(object));

                    if (ElseBodyToken != null)
                        FalsePart = Expression.Convert(FormTheExpression(ElseBodyToken), typeof(object));
                    else
                        FalsePart = Expression.Constant(false, typeof(object)); 

                    quantityExpression = Expression.Condition(TestPart, TruePart, FalsePart);
                    
                }
                else if (tokens[ix].TokenClassType == typeof(ParenthesisCallToken))
                {
                    quantityExpression = FunctionCallExpression(tokens[ix]);
                }
                else if (tokens[ix].TokenClassType == typeof(ParenthesisGroupToken))
                {
                    // take the inner tokens and send it to be parsed again.
                    quantityExpression = FormTheExpression(tokens[ix].RemoveSpaceTokens().TrimTokens(1, 1));

                }
                else if (tokens[ix].TokenClassType == typeof(SymbolicToken))
                {
                    // 
                    quantityExpression = ExternalFieldHandleExpression(tokens[ix]);
                }
                else if (tokens[ix].TokenClassType == typeof(NumberToken))
                {
                    // 
                    quantityExpression = Expression.Constant(double.Parse(tokens[ix].TokenValue));
                }
                else if (tokens[ix].TokenClassType == typeof(WordToken))
                {
                    // we are taking about internal variable storage
                    quantityExpression = InternalFieldHandleExpression(tokens[ix]);
                }
                else if (tokens[ix].TokenClassType == typeof(TextToken))
                {
                    quantityExpression = Expression.Constant(tokens[ix].TrimTokens(1, 1).TokenValue);
                }
                else
                {
                    throw new UnRecognizedException("Token: " + tokens[ix].TokenValue + " was not identified");
                }

        ExpressionCompleted:
                if (eop == null)
                {
                    //firs time creation
                    FirstEop = new ExprOp();

                    eop = FirstEop;
                }
                else
                {
                    //use the next object to be eop.
                    eop.Next = new ExprOp();
                    eop = eop.Next;
                }

                eop.Operation = op;
                eop.ValueExpression = quantityExpression;

                ix += 2;

            }


            //then form the calculation expression
            return ConstructExpression(FirstEop);

        }
Esempio n. 3
0
        /// <summary>
        /// Just take the left and right expression with the operator and make arithmatic expression.
        /// </summary>
        /// <param name="left"></param>
        /// <param name="op"></param>
        /// <param name="right"></param>
        /// <returns></returns>
        private Expression ArithExpression(ExprOp eop, out short skip)
        {
            Expression NativeLeft = eop.ValueExpression;
            Expression left;
            if (NativeLeft.Type == typeof(FieldHandle))
            {
                //left = Expression.Constant(CurrentFieldsContext.GetFieldValue(((FieldHandle)((ConstantExpression)NativeLeft).Value).Name));
                left = Expression.Constant(((FieldHandle)((ConstantExpression)NativeLeft).Value).GetValue());
            }
            else
                left = NativeLeft;

            string op = eop.Operation;

            Expression NativeRight = eop.Next.ValueExpression;
            Expression right;

            if (NativeRight.Type == typeof(FieldHandle))
            {
                //right = Expression.Constant(CurrentFieldsContext.GetFieldValue(((FieldHandle)((ConstantExpression)NativeRight).Value).Name));
                right = Expression.Constant(((FieldHandle)((ConstantExpression)NativeRight).Value).GetValue());
            }
            else
                right = NativeRight;

            // also try to convert the right type to the left type if there is a suitable conversion.
            if (left.Type.IsPrimitive)
            {
                // left is primitive
            }

            skip = 1;

            Type aqType = typeof(object);

            if (op == "_h*") return Expression.Multiply(left, right);

            if (op == "^") return Expression.Power(left, right, aqType.GetMethod("Pow"));

            if (op == "*") return Expression.Multiply(left, right);

            if (op == "/") return Expression.Divide(left, right);
            if (op == "%") return Expression.Modulo(left, right);
            if (op == "+") return Expression.Add(left, right);
            if (op == "-") return Expression.Subtract(left, right);


            if (op == "<") return Expression.LessThan(left, right);
            if (op == ">") return Expression.GreaterThan(left, right);
            if (op == "<=") return Expression.LessThanOrEqual(left, right);
            if (op == ">=") return Expression.GreaterThanOrEqual(left, right);

            if (op == "==") return Expression.Equal(left, right);
            if (op == "!=") return Expression.NotEqual(left, right);

            if (op.Equals("and", StringComparison.OrdinalIgnoreCase))
                return Expression.And(left, right);

            if (op.Equals("or", StringComparison.OrdinalIgnoreCase))
                return Expression.Or(left, right);

            if (op == "=")
            {
                //MethodInfo mi = CurrentFieldsContext.GetType().GetMethod("SetField");
                MethodInfo mi = typeof(FieldHandle).GetMethod("SetValue");

                //return Expression.Call(Expression.Constant(CurrentFieldsContext), mi, NativeLeft, Expression.Convert(right, typeof(object)));
                return Expression.Call(Expression.Constant((FieldHandle)((ConstantExpression)NativeLeft).Value), mi, Expression.Convert(right, typeof(object)));
            }
          

            throw new NotSupportedException("Not Supported Operator '" + op + "'");
        }