Exemplo n.º 1
0
        internal Expression ParseNextExpression(TokenStore ts, AnOperator leftOperator, ParseInfo parseInfo)
        {
            Expression exp = null, exp2 = null, exp3 = null;
            Type t = null;
            MethodInfo mi = null;
            AToken tok;
            while ((tok = ts.Current) != null)
            {
                if (leftOperator != null && tok.op != null && tok.op.precedence >= leftOperator.precedence) return exp;

                // current operator has high precedence than leftOp
                switch (tok.tok_type)
                {
                    case TOKEN_TYPE.INT: Assert(exp == null, tok); exp = Expression.Constant(int.Parse(tok.value)); break;
                    case TOKEN_TYPE.UINT: Assert(exp == null, tok); exp = Expression.Constant(uint.Parse(tok.value)); break;
                    case TOKEN_TYPE.LONG: Assert(exp == null, tok); exp = Expression.Constant(long.Parse(tok.value)); break;
                    case TOKEN_TYPE.ULONG: Assert(exp == null, tok); exp = Expression.Constant(ulong.Parse(tok.value)); break;
                    case TOKEN_TYPE.FLOAT: Assert(exp == null, tok); exp = Expression.Constant(float.Parse(tok.value)); break;
                    case TOKEN_TYPE.DOUBLE: Assert(exp == null, tok); exp = Expression.Constant(double.Parse(tok.value)); break;
                    case TOKEN_TYPE.DECIMAL: Assert(exp == null, tok); exp = Expression.Constant(decimal.Parse(tok.value, System.Globalization.NumberStyles.AllowExponent)); break;
                    case TOKEN_TYPE.BOOL: Assert(exp == null, tok); exp = Expression.Constant(bool.Parse(tok.value)); break;
                    case TOKEN_TYPE.TEXT: Assert(exp == null, tok); exp = Expression.Constant(tok.value); break;
                    case TOKEN_TYPE.IDENTIFIER:   // x, x[]
                        #region Parameter or Static Type reference
                        if (exp != null && exp is ConstantExpression && ((ConstantExpression)exp).Value is Type) // static type
                        {
                            #region declare local variable: T var1=exp1, var2=exp2;
                            t = (Type)((ConstantExpression)exp).Value;
                            Dictionary<string, ParameterExpression> localVaribles = parseInfo.localVariableStack.Peek();
                            List<Expression> exp_list = new List<Expression>();
                            while (ts.Current != null)
                            {
                                Assert(ts.Current.tok_type == TOKEN_TYPE.IDENTIFIER, ts.Current);
                                ParameterExpression var = Expression.Variable(t, ts.Current.value);
                                localVaribles.Add(ts.Current.value, var);
                                ts.Next();   // skip variable

                                if (ts.CurrentValue == "=") // variable initializer
                                {
                                    ts.Next();  // skip "="
                                    if (var.Type.IsArray && ts.CurrentValue == "{") // array initializer: T[] var = {1,2,3};
                                        exp = Expression.NewArrayInit(var.Type.GetElementType(), ParseParameters(ts, parseInfo, null, false));
                                    else
                                        exp = ParseNextExpression(ts, AnOperator.dicSystemOperator[","], parseInfo);
                                    if (exp.Type != t) exp = Expression.Convert(exp, t);
                                    exp_list.Add(Expression.Assign(var, exp));
                                }

                                if (ts.Current == null || ts.Current.value == ";") break;  // end of statement
                                if (ts.Current.value == ",") ts.Next(); // skip "," to next variable
                            }
                            if (exp_list.Count == 0) exp = null;
                            else if (exp_list.Count == 1) exp = exp_list[0];
                            else exp = Expression.Block(exp_list); 
                            #endregion
                        }
                        else
                        {
                            #region Parameter or Static Type reference
                            Assert(exp == null && (exp = ParseReferredParameterOrType(ts, parseInfo, true, true, true)) != null, ts.Current);
                            #endregion
                        }
                        break;
                        #endregion
                    case TOKEN_TYPE.OPERATOR:
                        #region Operator
                        switch (tok.op.op_type)
                        {
                            case OPERATOR_TYPE.OPEN:
                                #region Open operators: (, [. "{" will be proccessed in ParseStatement()
                                switch (tok.value)
                                {
                                    case "(":
                                        #region ParenthesisLeft: (nested expression)
                                        Assert(exp == null, tok);
                                        exp = ParseNextExpression(ts.NextUntilOperatorClose(), null, parseInfo);
                                        if (exp is ConstantExpression && ((ConstantExpression)exp).Value is Type) // (T)x
                                        {
                                            exp2 = ParseNextExpression(ts, AnOperator.dicSystemOperator["(T)"], parseInfo);
                                            if (exp2 != null)
                                                exp = Expression.Convert(exp2, (Type)((ConstantExpression)exp).Value);
                                        }
                                        break;
                                        #endregion
                                    case "[":
                                        #region BracketLeft: indexer[]
                                        Assert(exp != null, tok);
                                        {
                                            List<Type> param_types = new List<Type>();
                                            List<Expression> param_list = ParseParameters(ts, parseInfo, param_types, false);

                                            //TokenStore sub_ts = ts.NextUntilOperatorClose();
                                            //List<Expression> param_list = new List<Expression>();
                                            //while ((exp2 = GetNextExpression(sub_ts, AnOperator.dicSystemOperator[","], exprParameterList)) != null)
                                            //{
                                            //    param_list.Add(exp2);
                                            //    sub_ts.Next();   // to ','
                                            //}
                                            ////List<TokenStore> ts_list = ts.NextUntilOperatorClose().Split(OPERATOR_NAME.Comma);
                                            ////List<Expression> param_list = new List<Expression>();
                                            ////foreach (TokenStore one_ts in ts_list)
                                            ////{
                                            ////    if(one_ts.token_list.Count>0)
                                            ////        param_list.Add(GetNextExpression(one_ts, null, exprParameterList));
                                            ////}
                                            //List<Type> param_types = new List<Type>();
                                            //foreach (Expression e in param_list) param_types.Add(e.Type);
                                            if ((mi = exp.Type.GetMethod(tok.op.overload_name, BindingFlags.Instance | BindingFlags.Public, null, param_types.ToArray(), null)) != null)
                                                exp = Expression.Call(exp, mi, param_list.ToArray());
                                            else
                                                exp = Expression.ArrayIndex(exp, param_list.ToArray());
                                        }
                                        break;
                                        #endregion
                                    default:
                                        Assert(false, tok);
                                        break;
                                }
                                break; 
                                #endregion
                            case OPERATOR_TYPE.PREFIX_UNARY:
                                #region prefix unary operators
                                Assert(exp == null && ts.Next() != null, tok);
                                Assert((exp2 = ParseNextExpression(ts, tok.op, parseInfo)) != null, ts.Current);
                                mi = tok.op.overload_name == null ? null : exp2.Type.GetMethod(tok.op.overload_name, new Type[] { exp2.Type });
                                exp = ((d1m)tok.op.exp_call)(exp2, mi);
                                break;
                                #endregion
                            case OPERATOR_TYPE.POST_UNARY:
                                #region POST_UNARY
		                        Assert(exp != null, tok);
                                mi = tok.op.overload_name == null ? null : exp.Type.GetMethod(tok.op.overload_name, new Type[] { exp.Type });
                                exp = ((d1m)tok.op.exp_call)(exp, mi); 
                                break;
	                            #endregion
                            case OPERATOR_TYPE.BINARY:
                            case OPERATOR_TYPE.ASSIGN:
                                #region Binary or Assign Operators
                                Assert(exp != null && ts.Next() != null && (exp2 = ParseNextExpression(ts, tok.op, parseInfo)) != null, tok);
                                mi = null; t = null;
                                if (tok.value == "is")
                                {
                                    Assert(exp2 is ConstantExpression && ((ConstantExpression)exp2).Value is Type, tok);
                                    exp = Expression.TypeIs(exp, (Type)((ConstantExpression)exp2).Value);
                                    break;
                                }
                                else if (tok.value == "as")
                                {
                                    Assert(exp2 is ConstantExpression && ((ConstantExpression)exp2).Value is Type, tok);
                                    exp = Expression.TypeAs(exp, (Type)((ConstantExpression)exp2).Value);
                                    break;
                                }
                                if (tok.value == "+" && exp.Type == typeof(string) || exp2.Type == typeof(string))
                                {
                                    if (exp.Type != typeof(string)) exp = Expression.Convert(exp, typeof(string));
                                    if (exp2.Type != typeof(string)) exp2 = Expression.Convert(exp2, typeof(string));
                                    mi = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) });
                                }
                                else
                                {
                                    if (tok.op.overload_name != null)
                                    {
                                        mi = exp.Type.GetMethod(tok.op.overload_name, new Type[] { exp.Type, exp2.Type });
                                        if (mi == null)
                                            mi = exp2.Type.GetMethod(tok.op.overload_name, new Type[] { exp.Type, exp2.Type });
                                    }
                                    if (mi == null)
                                    {
                                        // use default operator, need implicit type conversion
                                        if (tok.op.required1stType != null) exp = Expression.Convert(exp, tok.op.required1stType);
                                        if (tok.op.required2ndType != null) exp2 = Expression.Convert(exp2, tok.op.required2ndType);
                                        if (tok.op.requiredOperandType == RequiredOperandType.SAME
                                            && exp.Type != exp2.Type
                                            && (t = QueryImplicitConversionType(exp, exp2)) != null)
                                        {
                                            if (exp.Type != t) exp = Expression.Convert(exp, t);
                                            if (exp2.Type != t) exp2 = Expression.Convert(exp2, t);
                                        }
                                    }
                                }
                                if (tok.op.exp_call is d2) exp = ((d2)tok.op.exp_call)(exp, exp2);
                                else if (tok.op.exp_call is d2m) exp = ((d2m)tok.op.exp_call)(exp, exp2, mi);
                                else exp = ((d2bm)tok.op.exp_call)(exp, exp2, false, mi);
                                break;
                                #endregion
                             case OPERATOR_TYPE.CONDITIONAL:
                                #region Conditional
                                Assert(exp != null && ts.Next()!=null && (exp2 = ParseNextExpression(ts, tok.op, parseInfo)) != null, tok);
                                Assert(ts.CurrentValue == ":" && ts.Next() != null, tok);
                                Assert((exp3 = ParseNextExpression(ts, tok.op, parseInfo)) != null, tok);
                                if (exp2.Type != exp3.Type && (t = QueryImplicitConversionType(exp2, exp3)) != null)
                                {
                                    if (exp2.Type != t) exp2 = Expression.Convert(exp2, t);
                                    if (exp3.Type != t) exp3 = Expression.Convert(exp3, t);
                                }
                                exp = Expression.Condition(exp, exp2, exp3);
                                break;
                                #endregion
                            case OPERATOR_TYPE.PRIMARY:
                                #region Primary: 
                                switch (tok.value)
                                {
                                    case "new":
                                        #region New
                                        {
                                            Assert(exp == null && ts.Next() != null && ts.Current.tok_type == TOKEN_TYPE.IDENTIFIER, tok); // skip "new"
                                            Assert((exp = ParseReferredParameterOrType(ts, parseInfo, true, false, false)) != null, tok);
                                            t = (Type)((ConstantExpression)exp).Value;
                                            Assert(ts.Current != null && ts.Current.value == "(" || ts.Current.value == "[", ts.Current);    // next is '(' or '['
                                            if (ts.Current.value == "(")   // new object().
                                            {
                                                List<Type> param_types = new List<Type>();
                                                List<Expression> param_list = ParseParameters(ts, parseInfo, param_types, false);

                                                ConstructorInfo ci = t.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, param_types.ToArray(), null);
                                                Assert(ci != null, ts.Current);
                                                // check parameter implicit conversion
                                                ParameterInfo[] pis = ci.GetParameters();
                                                for (int idx = 0; idx < param_list.Count; idx++)
                                                {
                                                    if (param_list[idx].Type != pis[idx].ParameterType)
                                                        param_list[idx] = Expression.Convert(param_list[idx], pis[idx].ParameterType);
                                                }
                                                exp = Expression.New(ci, param_list.ToArray());
                                            }
                                            else // new int[x,y] or new type[]{x,y}
                                            {
                                                List<Expression> param_list = ParseParameters(ts, parseInfo, null, false);  // [x,y]
                                                if (ts.CurrentValue == "{")   // array initializer {1,2,3}
                                                    exp = Expression.NewArrayInit(t, ParseParameters(ts, parseInfo, null, false));   // new array[] {x,y}
                                                else
                                                    exp = Expression.NewArrayBounds(t, param_list); // new array[x,y]
                                            }
                                        }
                                        break; 
                                        #endregion
                                    case "typeof":
                                        #region typeof
                                        Assert(exp == null && ts.Next() != null && ts.Current.value == "(", tok); // must be "("
                                        Assert((exp = ParseNextExpression(ts.NextUntilOperatorClose(), null, parseInfo)) != null, tok);
                                        Assert(exp is ConstantExpression && ((ConstantExpression)exp).Value is Type, "Invalid parameter for typeof(T)"); // typeof(T)
                                        break; 
                                        #endregion
                                    case "sizeof":
                                        #region sizeof
                                        Assert(exp == null, tok);
                                        Assert(ts.Next() != null && ts.Current.value == "(", tok); // must be "("
                                        Assert((exp = ParseNextExpression(ts.NextUntilOperatorClose(), null, parseInfo)) != null, tok);
                                        Assert(exp is ConstantExpression
                                            && ((ConstantExpression)exp).Value is Type
                                            && ((Type)((ConstantExpression)exp).Value).IsValueType, "Invalid parameter for sizeof(T)"); // sizeof(T)
                                        exp = Expression.Constant(System.Runtime.InteropServices.Marshal.SizeOf((Type)((ConstantExpression)exp).Value));
                                        break; 
                                        #endregion
                                    case ".":
                                        #region Property, Field or method call
                                        Assert(exp != null && (tok=ts.Next())!=null && tok.tok_type == TOKEN_TYPE.IDENTIFIER, tok); // skip "." => tok=variable
                                        ts.Next();  // skip variable
                                        if (ts.CurrentValue == "(")  // method call
                                        {
                                            #region Method Call
                                            List<Type> param_types = new List<Type>();
                                            List<Expression> param_list = ParseParameters(ts, parseInfo, param_types, false);

                                            if (exp is ConstantExpression && ((ConstantExpression)exp).Value is Type) // static call
                                            {
                                                t = (Type)(((ConstantExpression)exp).Value);
                                                Assert((mi = t.GetMethod(tok.value, BindingFlags.Static | BindingFlags.Public, null, param_types.ToArray(), null)) != null, tok);
                                                // check parameter implicit conversion
                                                ParameterInfo[] pis = mi.GetParameters();
                                                for (int idx = 0; idx < param_list.Count; idx++)
                                                {
                                                    Type et = (pis[idx].ParameterType.IsByRef) ? pis[idx].ParameterType.GetElementType() : pis[idx].ParameterType;
                                                    if (param_list[idx].Type != et)
                                                        param_list[idx] = Expression.Convert(param_list[idx], et);
                                                }
                                                exp = Expression.Call(mi, param_list.ToArray());
                                            }
                                            else // instance object method call
                                            {
                                                mi = exp.Type.GetMethod(tok.value, BindingFlags.Instance | BindingFlags.Public, null, param_types.ToArray(), null);
                                                Assert(mi != null, tok);
                                                // check parameter implicit conversion
                                                ParameterInfo[] pis = mi.GetParameters();
                                                for (int idx = 0; idx < param_list.Count; idx++)
                                                {
                                                    Type et = (pis[idx].ParameterType.IsByRef) ? pis[idx].ParameterType.GetElementType() : pis[idx].ParameterType;
                                                    if (param_list[idx].Type != et)
                                                        param_list[idx] = Expression.Convert(param_list[idx], et);
                                                }
                                                exp = Expression.Call(exp, mi, param_list.ToArray());
                                            } 
                                            #endregion
                                        }
                                        else if (exp is ConstantExpression && ((ConstantExpression)exp).Value is Type)
                                        {
                                            #region Static property of field
                                            PropertyInfo pi = null; FieldInfo fi = null;
                                            t = (Type)(((ConstantExpression)exp).Value);
                                            if ((pi = t.GetProperty(tok.value, BindingFlags.Public | BindingFlags.Static)) != null)
                                                exp = Expression.Property(null, pi);
                                            else if ((fi = t.GetField(tok.value, BindingFlags.Public | BindingFlags.Static)) != null)
                                                exp = Expression.Field(null, fi);
                                            else if ((pi = exp.Type.GetProperty(tok.value, BindingFlags.Instance | BindingFlags.Public)) != null)
                                                exp = Expression.Property(exp, pi);
                                            else if ((fi = exp.Type.GetField(tok.value, BindingFlags.Instance | BindingFlags.Public)) != null)
                                                exp = Expression.Field(exp, fi);
                                            else if (ts.CurrentValue == "<")
                                            {
                                                // v1.1: Static Generic Method call
                                                List<Type> param_types = new List<Type>();
                                                List<Expression> param_list = ParseParameters(ts, parseInfo, param_types, true);

                                                Assert((mi = t.GetMethod(tok.value, BindingFlags.Static | BindingFlags.Public).MakeGenericMethod(param_types.ToArray())) != null, tok);
                                                //Assert((mi = mi.MakeGenericMethod(param_types.ToArray())) != null, tok);
                                                Assert(ts.CurrentValue == "(", ts.Current);    // to "("

                                                param_list = ParseParameters(ts, parseInfo, null, false);
                                                exp = Expression.Call(mi, param_list.ToArray());
                                            }
                                            else
                                                Assert(false, tok); 
                                            #endregion
                                        }
                                        else
                                        {
                                            #region instance property or field
                                            PropertyInfo pi = null; FieldInfo fi = null;
                                            if ((pi = exp.Type.GetProperty(tok.value, BindingFlags.Instance | BindingFlags.Public)) != null)
                                                exp = Expression.Property(exp, pi);
                                            else if ((fi = exp.Type.GetField(tok.value, BindingFlags.Instance | BindingFlags.Public)) != null)
                                                exp = Expression.Field(exp, fi);
                                            else if (ts.CurrentValue == "<")
                                            {
                                                // v1.1: Instance Generic method call
                                                List<Type> param_types = new List<Type>();
                                                List<Expression> param_list = ParseParameters(ts, parseInfo, param_types, true);
                                                Assert((mi = exp.Type.GetMethod(tok.value, BindingFlags.Instance | BindingFlags.Public).MakeGenericMethod(param_types.ToArray())) != null, tok);
                                                //Assert((mi = mi.MakeGenericMethod(param_types.ToArray())) != null, tok);
                                                Assert(ts.CurrentValue == "(", ts.Current);    // to "("
                                                param_list = ParseParameters(ts, parseInfo, null, false);
                                                exp = Expression.Call(exp, mi, param_list.ToArray());
                                            }
                                            else
                                                Assert(false, tok); 
                                            #endregion
                                        }
                                        break; 
                                        #endregion
                                    default:
                                        // ,(not in method and indexer) and ;(need ASP.NET4.0)
                                        Assert(false, tok);
                                        break;
                                }
                                break;
                                #endregion
                        }
                        break;
                        #endregion
                    default:
                        Assert(false, tok);
                        break;
                }
                if (ts.Current == tok) ts.Next();
            }
            return exp;
        }
Exemplo n.º 2
0
 internal AToken(int start_pos/*, int end_pos*/, TOKEN_TYPE tok_type, AnOperator op, string value)
 {
     this.start_pos = start_pos;
     //this.end_pos = end_pos;
     this.tok_type = tok_type;
     this.op = op;
     this.value = value;
 }