C# Linq datatable动态groupby

来源:互联网 发布:淘宝pg美人网没了 编辑:程序博客网 时间:2024/05/17 22:26

声明:个人技术水平有限,欢迎指正。不喜勿喷
问题:可否传入分组列与合计列,自动进行分组合计
在网上找了很多,发现Scott大神写了一个动态的LinQ拼装方法,但是不支持DataTable的动态方法。个人做了一些修改。先看结果

对groupby 方法进行拓展,入参为一个字符串。(扩展方法在下面,非常长,大神写的源码,自己做了些修改)

举例:groupby 的入参为 字符串:new(Field("col1") as col1,Field("col2") as col2 ),调用结果就相当于一个linq:

var query = from p in source group p by new{ col1 = p.field("col1"),col2 = p.field("col2")}

上述的groupby 方法实现了之后,只要我实现一个动态拼接linq字符串的方法就可以啦!

 //拼写动态的group 字符串

[csharp] view plain copy
  1. string vDmyLinq = "";  
  2. for (int i = 0; i < vGroupColumns.Count; i++)  
  3. {  
  4.     if (string.IsNullOrEmpty(vDmyLinq))  
  5.     {  
  6.         vDmyLinq = @"new (Field(@" + i.ToString() + @") as " + vGroupColumns[i];  
  7.     }  
  8.     else  
  9.     {  
  10.         vDmyLinq = vDmyLinq + @" , Field(@" + i.ToString() + @") as " + vGroupColumns[i];  
  11.     }  
  12. }  
  13. if (!string.IsNullOrEmpty(vDmyLinq))  
  14. {  
  15.     vDmyLinq = vDmyLinq + ")";  
  16. }  
  17. //获取group结果  
  18. var queryList = source.AsEnumerable().GroupBy(vDmyLinq, vGroupColumns.ToArray(), types.ToArray());  

 
[csharp] view plain copy
  1. //拼装查询的动态linq  
  2.                 string vSelector = "";  
  3.                 //获取分组列  
  4.                 foreach (string item in vGroupColumns)  
  5.                 {  
  6.                     if (string.IsNullOrEmpty(vSelector))  
  7.                     {  
  8.                         vSelector = "new(Key." + item + " as " + item;  
  9.                     }  
  10.                     else  
  11.                     {  
  12.                         vSelector = vSelector + ",Key." + item + " as " + item;  
  13.                     }  
  14.                 }  
  15.                 //匹配计算方法,获取要合计的列  
  16.                 for (int i = 0; i < expColumns.Count; i++)  
  17.                 {  
  18.                     var item = expColumns[i];  
  19.                     #region 匹配计算方法  
  20.                     string expreesionStr = item.ExpressionStr;  
  21.                     string vMethodName = expreesionStr.Substring(0, expreesionStr.IndexOf("("));  
  22.                     string linqExpreeMethod = "";  
  23.                     CellExpCommon.eExpression sumType;  
  24.                     bool l_bIsSumType = Enum.TryParse<CellExpCommon.eExpression>(vMethodName, out sumType);  
  25.                     if (l_bIsSumType)  
  26.                     {  
  27.                         if (sumType == CellExpCommon.eExpression.Avg)  
  28.                         {  
  29.                             linqExpreeMethod = "Average";  
  30.   
  31.   
  32.                             vSelector = vSelector + "," + linqExpreeMethod + "(Field(@" + i.ToString() + ")) as " + item.ColumnName;  
  33.                         }  
  34.                         else if (sumType == CellExpCommon.eExpression.Sum)  
  35.                         {  
  36.                             linqExpreeMethod = "Sum";  
  37.   
  38.   
  39.                             vSelector = vSelector + "," + linqExpreeMethod + "(Field(@" + i.ToString() + ")) as " + item.ColumnName;  
  40.                         }  
  41.   
  42.   
  43.   
  44.   
  45.                         else if (sumType == CellExpCommon.eExpression.Max)  
  46.                         {  
  47.                             linqExpreeMethod = "Max";  
  48.                             vSelector = vSelector + "," + linqExpreeMethod + "() as " + item.ColumnName;  
  49.                         }  
  50.                         else if (sumType == CellExpCommon.eExpression.Min)  
  51.                         {  
  52.                             linqExpreeMethod = "Min";  
  53.                             vSelector = vSelector + "," + linqExpreeMethod + "() as " + item.ColumnName;  
  54.                         }  
  55.                         else if (sumType == CellExpCommon.eExpression.Count)  
  56.                         {  
  57.                             linqExpreeMethod = "Count";  
  58.                             vSelector = vSelector + "," + linqExpreeMethod + "() as " + item.ColumnName;  
  59.                         }  
  60.   
  61.   
  62.                     }  
  63.                     #endregion  
  64.                     vSumCols.Add(item.ColumnName);  
  65.                     sumTypes.Add(table.Columns[item.ColumnName].DataType);  
  66.                 }  
  67.                 vSelector = vSelector + ")";  
  68.   
  69.   
  70.                 var queryLIst2 = queryList.Select(vSelector, vSumCols.ToArray(), sumTypes.ToArray());  

以上是拼装和调用GroupBy的方法,是不是很简单,只要传入分组列与合计列就OK了!

下面是对Scott大神的代码修改之后的动态拼装修改!也就是实现DataTable的GroupBy拓展方法!

[csharp] view plain copy
  1. using System.Collections.Generic;  
  2. using System.Text;  
  3. using System.Linq;  
  4. using System.Linq.Expressions;  
  5. using System.Reflection;  
  6. using System.Reflection.Emit;  
  7. using System.Threading;  
  8. using System.Data;  
  9. using System.Collections;  
  10.   
  11. namespace System.Data  
  12. {  
  13.     public static class DynamicQueryable  
  14.     {  
  15.   
  16.          
  17.         public static IEnumerable Select(this IEnumerable sourceEnum, string keySelector, string[] values, Type[] types)  
  18.         {  
  19.             if (sourceEnum == nullthrow new ArgumentNullException("source");  
  20.             if (keySelector == nullthrow new ArgumentNullException("keySelector");  
  21.             IQueryable source = sourceEnum.AsQueryable();  
  22.   
  23.             LambdaExpression keyLambda = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, values, types);  
  24.   
  25.             return source.Provider.Execute<IEnumerable>(  
  26.                  Expression.Call(  
  27.                      typeof(Enumerable), "Select",  
  28.                      new Type[] { source.ElementType, keyLambda.Body.Type },  
  29.                      source.Expression, keyLambda  
  30.                      )  
  31.                      );  
  32.         }  
  33.          
  34.         public static IEnumerable GroupBy(this IEnumerable<DataRow> sourceEnum, string keySelector, string[] values,Type[] types)  
  35.         {  
  36.             if (sourceEnum == nullthrow new ArgumentNullException("source");  
  37.             if (keySelector == nullthrow new ArgumentNullException("keySelector");  
  38.             IQueryable<DataRow> source = sourceEnum.AsQueryable();  
  39.   
  40.             LambdaExpression keyLambda = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, values,types);  
  41.   
  42.             return source.Provider.Execute<IEnumerable>(  
  43.                  Expression.Call(  
  44.                      typeof(Enumerable), "GroupBy",  
  45.                      new Type[] { source.ElementType, keyLambda.Body.Type },  
  46.                      source.Expression, keyLambda  
  47.                      )  
  48.                      );  
  49.         }  
  50.         public static IQueryable<T> Where<T>(this IQueryable<T> source, string predicate, params object[] values)  
  51.         {  
  52.             return (IQueryable<T>)Where((IQueryable)source, predicate, values);  
  53.         }  
  54.   
  55.         public static IQueryable Where(this IQueryable source, string predicate, params object[] values)  
  56.         {  
  57.             if (source == nullthrow new ArgumentNullException("source");  
  58.             if (predicate == nullthrow new ArgumentNullException("predicate");  
  59.             LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values);  
  60.             return source.Provider.CreateQuery(  
  61.                 Expression.Call(  
  62.                     typeof(Queryable), "Where",  
  63.                     new Type[] { source.ElementType },  
  64.                     source.Expression, Expression.Quote(lambda)));  
  65.         }  
  66.   
  67.         public static IQueryable Select(this IQueryable source, string selector, params object[] values)  
  68.         {  
  69.             if (source == nullthrow new ArgumentNullException("source");  
  70.             if (selector == nullthrow new ArgumentNullException("selector");  
  71.             LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, null, selector, values);  
  72.             return source.Provider.CreateQuery(  
  73.                 Expression.Call(  
  74.                     typeof(Queryable), "Select",  
  75.                     new Type[] { source.ElementType, lambda.Body.Type },  
  76.                     source.Expression, Expression.Quote(lambda)));  
  77.         }  
  78.   
  79.         public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values)  
  80.         {  
  81.             return (IQueryable<T>)OrderBy((IQueryable)source, ordering, values);  
  82.         }  
  83.   
  84.         public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values)  
  85.         {  
  86.             if (source == nullthrow new ArgumentNullException("source");  
  87.             if (ordering == nullthrow new ArgumentNullException("ordering");  
  88.             ParameterExpression[] parameters = new ParameterExpression[] {  
  89.                 Expression.Parameter(source.ElementType, "") };  
  90.             ExpressionParser parser = new ExpressionParser(parameters, ordering, values);  
  91.             IEnumerable<DynamicOrdering> orderings = parser.ParseOrdering();  
  92.             Expression queryExpr = source.Expression;  
  93.             string methodAsc = "OrderBy";  
  94.             string methodDesc = "OrderByDescending";  
  95.             foreach (DynamicOrdering o in orderings)  
  96.             {  
  97.                 queryExpr = Expression.Call(  
  98.                     typeof(Queryable), o.Ascending ? methodAsc : methodDesc,  
  99.                     new Type[] { source.ElementType, o.Selector.Type },  
  100.                     queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)));  
  101.                 methodAsc = "ThenBy";  
  102.                 methodDesc = "ThenByDescending";  
  103.             }  
  104.             return source.Provider.CreateQuery(queryExpr);  
  105.         }  
  106.   
  107.         public static IQueryable Take(this IQueryable source, int count)  
  108.         {  
  109.             if (source == nullthrow new ArgumentNullException("source");  
  110.             return source.Provider.CreateQuery(  
  111.                 Expression.Call(  
  112.                     typeof(Queryable), "Take",  
  113.                     new Type[] { source.ElementType },  
  114.                     source.Expression, Expression.Constant(count)));  
  115.         }  
  116.   
  117.         public static IQueryable Skip(this IQueryable source, int count)  
  118.         {  
  119.             if (source == nullthrow new ArgumentNullException("source");  
  120.             return source.Provider.CreateQuery(  
  121.                 Expression.Call(  
  122.                     typeof(Queryable), "Skip",  
  123.                     new Type[] { source.ElementType },  
  124.                     source.Expression, Expression.Constant(count)));  
  125.         }  
  126.   
  127.         public static IQueryable GroupBy(this IQueryable source, string keySelector, string elementSelector, params object[] values)  
  128.         {  
  129.             if (source == nullthrow new ArgumentNullException("source");  
  130.             if (keySelector == nullthrow new ArgumentNullException("keySelector");  
  131.             if (elementSelector == nullthrow new ArgumentNullException("elementSelector");  
  132.             LambdaExpression keyLambda = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, values);  
  133.             LambdaExpression elementLambda = DynamicExpression.ParseLambda(source.ElementType, null, elementSelector, values);  
  134.             return source.Provider.CreateQuery(  
  135.                 Expression.Call(  
  136.                     typeof(Queryable), "GroupBy",  
  137.                     new Type[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },  
  138.                     source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)));  
  139.         }  
  140.   
  141.         public static bool Any(this IQueryable source)  
  142.         {  
  143.             if (source == nullthrow new ArgumentNullException("source");  
  144.             return (bool)source.Provider.Execute(  
  145.                 Expression.Call(  
  146.                     typeof(Queryable), "Any",  
  147.                     new Type[] { source.ElementType }, source.Expression));  
  148.         }  
  149.   
  150.         public static int Count(this IQueryable source)  
  151.         {  
  152.             if (source == nullthrow new ArgumentNullException("source");  
  153.             return (int)source.Provider.Execute(  
  154.                 Expression.Call(  
  155.                     typeof(Queryable), "Count",  
  156.                     new Type[] { source.ElementType }, source.Expression));  
  157.         }  
  158.     }  
  159.   
  160.     public abstract class DynamicClass  
  161.     {  
  162.         public override string ToString()  
  163.         {  
  164.             PropertyInfo[] props = this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);  
  165.             StringBuilder sb = new StringBuilder();  
  166.             sb.Append("{");  
  167.             for (int i = 0; i < props.Length; i++)  
  168.             {  
  169.                 if (i > 0) sb.Append(", ");  
  170.                 sb.Append(props[i].Name);  
  171.                 sb.Append("=");  
  172.                 sb.Append(props[i].GetValue(thisnull));  
  173.             }  
  174.             sb.Append("}");  
  175.             return sb.ToString();  
  176.         }  
  177.     }  
  178.   
  179.     public class DynamicProperty  
  180.     {  
  181.         string name;  
  182.         Type type;  
  183.   
  184.         public DynamicProperty(string name, Type type)  
  185.         {  
  186.             if (name == nullthrow new ArgumentNullException("name");  
  187.             if (type == nullthrow new ArgumentNullException("type");  
  188.             this.name = name;  
  189.             this.type = type;  
  190.         }  
  191.   
  192.         public string Name  
  193.         {  
  194.             get { return name; }  
  195.         }  
  196.   
  197.         public Type Type  
  198.         {  
  199.             get { return type; }  
  200.         }  
  201.     }  
  202.   
  203.     public static class DynamicExpression  
  204.     {  
  205.         public static Expression Parse(Type resultType, string expression, params object[] values)  
  206.         {  
  207.             ExpressionParser parser = new ExpressionParser(null, expression, values);  
  208.             return parser.Parse(resultType);  
  209.         }  
  210.   
  211.         public static LambdaExpression ParseLambda(Type itType, Type resultType, string expression, params object[] values)  
  212.         {  
  213.             return ParseLambda(new ParameterExpression[] { Expression.Parameter(itType, "") }, resultType, expression, values);  
  214.         }  
  215.         
  216.         public static LambdaExpression ParseLambda(Type itType, Type resultType, string expression, string[] values,Type[] types)  
  217.         {  
  218.             return ParseLambda(new ParameterExpression[] { Expression.Parameter(itType, "") }, resultType, expression, values,types);  
  219.         }  
  220.         public static LambdaExpression ParseLambda(ParameterExpression[] parameters, Type resultType, string expression, params object[] values)  
  221.         {  
  222.             ExpressionParser parser = new ExpressionParser(parameters, expression, values);  
  223.             return Expression.Lambda(parser.Parse(resultType), parameters);  
  224.         }  
  225.           
  226.         public static LambdaExpression ParseLambda(ParameterExpression[] parameters, Type resultType, string expression, string[] values,Type[] types)  
  227.         {  
  228.             ExpressionParser parser = new ExpressionParser(parameters, expression, values,types);  
  229.             return Expression.Lambda(parser.Parse(resultType), parameters);  
  230.         }  
  231.         public static Expression<Func<T, S>> ParseLambda<T, S>(string expression, params object[] values)  
  232.         {  
  233.             return (Expression<Func<T, S>>)ParseLambda(typeof(T), typeof(S), expression, values);  
  234.         }  
  235.   
  236.         public static Type CreateClass(params DynamicProperty[] properties)  
  237.         {  
  238.             return ClassFactory.Instance.GetDynamicClass(properties);  
  239.         }  
  240.   
  241.         public static Type CreateClass(IEnumerable<DynamicProperty> properties)  
  242.         {  
  243.             return ClassFactory.Instance.GetDynamicClass(properties);  
  244.         }  
  245.     }  
  246.   
  247.     internal class DynamicOrdering  
  248.     {  
  249.         public Expression Selector;  
  250.         public bool Ascending;  
  251.     }  
  252.   
  253.     internal class Signature : IEquatable<Signature>  
  254.     {  
  255.         public DynamicProperty[] properties;  
  256.         public int hashCode;  
  257.   
  258.         public Signature(IEnumerable<DynamicProperty> properties)  
  259.         {  
  260.             this.properties = properties.ToArray();  
  261.             hashCode = 0;  
  262.             foreach (DynamicProperty p in properties)  
  263.             {  
  264.                 hashCode ^= p.Name.GetHashCode() ^ p.Type.GetHashCode();  
  265.             }  
  266.         }  
  267.   
  268.         public override int GetHashCode()  
  269.         {  
  270.             return hashCode;  
  271.         }  
  272.   
  273.         public override bool Equals(object obj)  
  274.         {  
  275.             return obj is Signature ? Equals((Signature)obj) : false;  
  276.         }  
  277.   
  278.         public bool Equals(Signature other)  
  279.         {  
  280.             if (properties.Length != other.properties.Length) return false;  
  281.             for (int i = 0; i < properties.Length; i++)  
  282.             {  
  283.                 if (properties[i].Name != other.properties[i].Name ||  
  284.                     properties[i].Type != other.properties[i].Type) return false;  
  285.             }  
  286.             return true;  
  287.         }  
  288.     }  
  289.   
  290.     internal class ClassFactory  
  291.     {  
  292.         public static readonly ClassFactory Instance = new ClassFactory();  
  293.   
  294.         static ClassFactory() { }  // Trigger lazy initialization of static fields  
  295.   
  296.         ModuleBuilder module;  
  297.         Dictionary<Signature, Type> classes;  
  298.         int classCount;  
  299.         ReaderWriterLock rwLock;  
  300.   
  301.         private ClassFactory()  
  302.         {  
  303.             AssemblyName name = new AssemblyName("DynamicClasses");  
  304.             AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);  
  305. #if ENABLE_LINQ_PARTIAL_TRUST  
  306.             new ReflectionPermission(PermissionState.Unrestricted).Assert();  
  307. #endif  
  308.             try  
  309.             {  
  310.                 module = assembly.DefineDynamicModule("Module");  
  311.             }  
  312.             finally  
  313.             {  
  314. #if ENABLE_LINQ_PARTIAL_TRUST  
  315.                 PermissionSet.RevertAssert();  
  316. #endif  
  317.             }  
  318.             classes = new Dictionary<Signature, Type>();  
  319.             rwLock = new ReaderWriterLock();  
  320.         }  
  321.   
  322.         public Type GetDynamicClass(IEnumerable<DynamicProperty> properties)  
  323.         {  
  324.             rwLock.AcquireReaderLock(Timeout.Infinite);  
  325.             try  
  326.             {  
  327.                 Signature signature = new Signature(properties);  
  328.                 Type type;  
  329.                 if (!classes.TryGetValue(signature, out type))  
  330.                 {  
  331.                     type = CreateDynamicClass(signature.properties);  
  332.                     classes.Add(signature, type);  
  333.                 }  
  334.                 return type;  
  335.             }  
  336.             finally  
  337.             {  
  338.                 rwLock.ReleaseReaderLock();  
  339.             }  
  340.         }  
  341.   
  342.         Type CreateDynamicClass(DynamicProperty[] properties)  
  343.         {  
  344.             LockCookie cookie = rwLock.UpgradeToWriterLock(Timeout.Infinite);  
  345.             try  
  346.             {  
  347.                 string typeName = "DynamicClass" + (classCount + 1);  
  348. #if ENABLE_LINQ_PARTIAL_TRUST  
  349.                 new ReflectionPermission(PermissionState.Unrestricted).Assert();  
  350. #endif  
  351.                 try  
  352.                 {  
  353.                     TypeBuilder tb = this.module.DefineType(typeName, TypeAttributes.Class |  
  354.                         TypeAttributes.Public, typeof(DynamicClass));  
  355.                     FieldInfo[] fields = GenerateProperties(tb, properties);  
  356.                     GenerateEquals(tb, fields);  
  357.                     GenerateGetHashCode(tb, fields);  
  358.                     Type result = tb.CreateType();  
  359.                     classCount++;  
  360.                     return result;  
  361.                 }  
  362.                 finally  
  363.                 {  
  364. #if ENABLE_LINQ_PARTIAL_TRUST  
  365.                     PermissionSet.RevertAssert();  
  366. #endif  
  367.                 }  
  368.             }  
  369.             finally  
  370.             {  
  371.                 rwLock.DowngradeFromWriterLock(ref cookie);  
  372.             }  
  373.         }  
  374.   
  375.         FieldInfo[] GenerateProperties(TypeBuilder tb, DynamicProperty[] properties)  
  376.         {  
  377.             FieldInfo[] fields = new FieldBuilder[properties.Length];  
  378.             for (int i = 0; i < properties.Length; i++)  
  379.             {  
  380.                 DynamicProperty dp = properties[i];  
  381.                 FieldBuilder fb = tb.DefineField("_" + dp.Name, dp.Type, FieldAttributes.Private);  
  382.                 PropertyBuilder pb = tb.DefineProperty(dp.Name, System.Reflection.PropertyAttributes.HasDefault, dp.Type, null);  
  383.                 MethodBuilder mbGet = tb.DefineMethod("get_" + dp.Name,  
  384.                     MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,  
  385.                     dp.Type, Type.EmptyTypes);  
  386.                 ILGenerator genGet = mbGet.GetILGenerator();  
  387.                 genGet.Emit(OpCodes.Ldarg_0);  
  388.                 genGet.Emit(OpCodes.Ldfld, fb);  
  389.                 genGet.Emit(OpCodes.Ret);  
  390.                 MethodBuilder mbSet = tb.DefineMethod("set_" + dp.Name,  
  391.                     MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,  
  392.                     nullnew Type[] { dp.Type });  
  393.                 ILGenerator genSet = mbSet.GetILGenerator();  
  394.                 genSet.Emit(OpCodes.Ldarg_0);  
  395.                 genSet.Emit(OpCodes.Ldarg_1);  
  396.                 genSet.Emit(OpCodes.Stfld, fb);  
  397.                 genSet.Emit(OpCodes.Ret);  
  398.                 pb.SetGetMethod(mbGet);  
  399.                 pb.SetSetMethod(mbSet);  
  400.                 fields[i] = fb;  
  401.             }  
  402.             return fields;  
  403.         }  
  404.   
  405.         void GenerateEquals(TypeBuilder tb, FieldInfo[] fields)  
  406.         {  
  407.             MethodBuilder mb = tb.DefineMethod("Equals",  
  408.                 MethodAttributes.Public | MethodAttributes.ReuseSlot |  
  409.                 MethodAttributes.Virtual | MethodAttributes.HideBySig,  
  410.                 typeof(bool), new Type[] { typeof(object) });  
  411.             ILGenerator gen = mb.GetILGenerator();  
  412.             LocalBuilder other = gen.DeclareLocal(tb);  
  413.             Label next = gen.DefineLabel();  
  414.             gen.Emit(OpCodes.Ldarg_1);  
  415.             gen.Emit(OpCodes.Isinst, tb);  
  416.             gen.Emit(OpCodes.Stloc, other);  
  417.             gen.Emit(OpCodes.Ldloc, other);  
  418.             gen.Emit(OpCodes.Brtrue_S, next);  
  419.             gen.Emit(OpCodes.Ldc_I4_0);  
  420.             gen.Emit(OpCodes.Ret);  
  421.             gen.MarkLabel(next);  
  422.             foreach (FieldInfo field in fields)  
  423.             {  
  424.                 Type ft = field.FieldType;  
  425.                 Type ct = typeof(EqualityComparer<>).MakeGenericType(ft);  
  426.                 next = gen.DefineLabel();  
  427.                 gen.EmitCall(OpCodes.Call, ct.GetMethod("get_Default"), null);  
  428.                 gen.Emit(OpCodes.Ldarg_0);  
  429.                 gen.Emit(OpCodes.Ldfld, field);  
  430.                 gen.Emit(OpCodes.Ldloc, other);  
  431.                 gen.Emit(OpCodes.Ldfld, field);  
  432.                 gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("Equals"new Type[] { ft, ft }), null);  
  433.                 gen.Emit(OpCodes.Brtrue_S, next);  
  434.                 gen.Emit(OpCodes.Ldc_I4_0);  
  435.                 gen.Emit(OpCodes.Ret);  
  436.                 gen.MarkLabel(next);  
  437.             }  
  438.             gen.Emit(OpCodes.Ldc_I4_1);  
  439.             gen.Emit(OpCodes.Ret);  
  440.         }  
  441.   
  442.         void GenerateGetHashCode(TypeBuilder tb, FieldInfo[] fields)  
  443.         {  
  444.             MethodBuilder mb = tb.DefineMethod("GetHashCode",  
  445.                 MethodAttributes.Public | MethodAttributes.ReuseSlot |  
  446.                 MethodAttributes.Virtual | MethodAttributes.HideBySig,  
  447.                 typeof(int), Type.EmptyTypes);  
  448.             ILGenerator gen = mb.GetILGenerator();  
  449.             gen.Emit(OpCodes.Ldc_I4_0);  
  450.             foreach (FieldInfo field in fields)  
  451.             {  
  452.                 Type ft = field.FieldType;  
  453.                 Type ct = typeof(EqualityComparer<>).MakeGenericType(ft);  
  454.                 gen.EmitCall(OpCodes.Call, ct.GetMethod("get_Default"), null);  
  455.                 gen.Emit(OpCodes.Ldarg_0);  
  456.                 gen.Emit(OpCodes.Ldfld, field);  
  457.                 gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("GetHashCode"new Type[] { ft }), null);  
  458.                 gen.Emit(OpCodes.Xor);  
  459.             }  
  460.             gen.Emit(OpCodes.Ret);  
  461.         }  
  462.     }  
  463.   
  464.     public sealed class ParseException : Exception  
  465.     {  
  466.         int position;  
  467.   
  468.         public ParseException(string message, int position)  
  469.             : base(message)  
  470.         {  
  471.             this.position = position;  
  472.         }  
  473.   
  474.         public int Position  
  475.         {  
  476.             get { return position; }  
  477.         }  
  478.   
  479.         public override string ToString()  
  480.         {  
  481.             return string.Format(Res.ParseExceptionFormat, Message, position);  
  482.         }  
  483.     }  
  484.   
  485.     internal class ExpressionParser  
  486.     {  
  487.         struct Token  
  488.         {  
  489.             public TokenId id;  
  490.             public string text;  
  491.             public int pos;  
  492.         }  
  493.   
  494.         enum TokenId  
  495.         {  
  496.             Unknown,  
  497.             End,  
  498.             Identifier,  
  499.             StringLiteral,  
  500.             IntegerLiteral,  
  501.             RealLiteral,  
  502.             Exclamation,  
  503.             Percent,  
  504.             Amphersand,  
  505.             OpenParen,  
  506.             CloseParen,  
  507.             Asterisk,  
  508.             Plus,  
  509.             Comma,  
  510.             Minus,  
  511.             Dot,  
  512.             Slash,  
  513.             Colon,  
  514.             LessThan,  
  515.             Equal,  
  516.             GreaterThan,  
  517.             Question,  
  518.             OpenBracket,  
  519.             CloseBracket,  
  520.             Bar,  
  521.             ExclamationEqual,  
  522.             DoubleAmphersand,  
  523.             LessThanEqual,  
  524.             LessGreater,  
  525.             DoubleEqual,  
  526.             GreaterThanEqual,  
  527.             DoubleBar  
  528.         }  
  529.   
  530.         interface ILogicalSignatures  
  531.         {  
  532.             void F(bool x, bool y);  
  533.             void F(bool? x, bool? y);  
  534.         }  
  535.   
  536.         interface IArithmeticSignatures  
  537.         {  
  538.             void F(int x, int y);  
  539.             void F(uint x, uint y);  
  540.             void F(long x, long y);  
  541.             void F(ulong x, ulong y);  
  542.             void F(float x, float y);  
  543.             void F(double x, double y);  
  544.             void F(decimal x, decimal y);  
  545.             void F(int? x, int? y);  
  546.             void F(uint? x, uint? y);  
  547.             void F(long? x, long? y);  
  548.             void F(ulong? x, ulong? y);  
  549.             void F(float? x, float? y);  
  550.             void F(double? x, double? y);  
  551.             void F(decimal? x, decimal? y);  
  552.         }  
  553.   
  554.         interface IRelationalSignatures : IArithmeticSignatures  
  555.         {  
  556.             void F(string x, string y);  
  557.             void F(char x, char y);  
  558.             void F(DateTime x, DateTime y);  
  559.             void F(TimeSpan x, TimeSpan y);  
  560.             void F(char? x, char? y);  
  561.             void F(DateTime? x, DateTime? y);  
  562.             void F(TimeSpan? x, TimeSpan? y);  
  563.         }  
  564.   
  565.         interface IEqualitySignatures : IRelationalSignatures  
  566.         {  
  567.             void F(bool x, bool y);  
  568.             void F(bool? x, bool? y);  
  569.         }  
  570.   
  571.         interface IAddSignatures : IArithmeticSignatures  
  572.         {  
  573.             void F(DateTime x, TimeSpan y);  
  574.             void F(TimeSpan x, TimeSpan y);  
  575.             void F(DateTime? x, TimeSpan? y);  
  576.             void F(TimeSpan? x, TimeSpan? y);  
  577.         }  
  578.   
  579.         interface ISubtractSignatures : IAddSignatures  
  580.         {  
  581.             void F(DateTime x, DateTime y);  
  582.             void F(DateTime? x, DateTime? y);  
  583.         }  
  584.   
  585.         interface INegationSignatures  
  586.         {  
  587.             void F(int x);  
  588.             void F(long x);  
  589.             void F(float x);  
  590.             void F(double x);  
  591.             void F(decimal x);  
  592.             void F(int? x);  
  593.             void F(long? x);  
  594.             void F(float? x);  
  595.             void F(double? x);  
  596.             void F(decimal? x);  
  597.         }  
  598.   
  599.         interface INotSignatures  
  600.         {  
  601.             void F(bool x);  
  602.             void F(bool? x);  
  603.         }  
  604.   
  605.         interface IEnumerableSignatures  
  606.         {  
  607.             void Where(bool predicate);  
  608.             void Any();  
  609.             void Any(bool predicate);  
  610.             void All(bool predicate);  
  611.             void Count();  
  612.             void Count(bool predicate);  
  613.             void Min(object selector);  
  614.             void Max(object selector);  
  615.             void Sum(int selector);  
  616.             void Sum(int? selector);  
  617.             void Sum(long selector);  
  618.             void Sum(long? selector);  
  619.             void Sum(float selector);  
  620.             void Sum(float? selector);  
  621.             void Sum(double selector);  
  622.             void Sum(double? selector);  
  623.             void Sum(decimal selector);  
  624.             void Sum(decimal? selector);  
  625.             void Average(int selector);  
  626.             void Average(int? selector);  
  627.             void Average(long selector);  
  628.             void Average(long? selector);  
  629.             void Average(float selector);  
  630.             void Average(float? selector);  
  631.             void Average(double selector);  
  632.             void Average(double? selector);  
  633.             void Average(decimal selector);  
  634.             void Average(decimal? selector);  
  635.         }  
  636.   
  637.         static readonly Type[] predefinedTypes = {  
  638.             typeof(Object),  
  639.             typeof(Boolean),  
  640.             typeof(Char),  
  641.             typeof(String),  
  642.             typeof(SByte),  
  643.             typeof(Byte),  
  644.             typeof(Int16),  
  645.             typeof(UInt16),  
  646.             typeof(Int32),  
  647.             typeof(UInt32),  
  648.             typeof(Int64),  
  649.             typeof(UInt64),  
  650.             typeof(Single),  
  651.             typeof(Double),  
  652.             typeof(Decimal),  
  653.             typeof(DateTime),  
  654.             typeof(TimeSpan),  
  655.             typeof(Guid),  
  656.             typeof(Math),  
  657.             typeof(Convert),  
  658.             typeof(System.Data.DataRowExtensions)  
  659.         };  
  660.   
  661.         static readonly Expression trueLiteral = Expression.Constant(true);  
  662.         static readonly Expression falseLiteral = Expression.Constant(false);  
  663.         static readonly Expression nullLiteral = Expression.Constant(null);  
  664.   
  665.         static readonly string keywordIt = "it";  
  666.         static readonly string keywordIif = "iif";  
  667.         static readonly string keywordNew = "new";  
  668.   
  669.         static Dictionary<stringobject> keywords;  
  670.   
  671.         Dictionary<stringobject> symbols;  
  672.         Dictionary<string, Type> symTypes;  
  673.         IDictionary<stringobject> externals;  
  674.         Dictionary<Expression, string> literals;  
  675.         ParameterExpression it;  
  676.         string text;  
  677.         int textPos;  
  678.         int textLen;  
  679.         char ch;  
  680.         Token token;  
  681.         string currentMothedName = "";  
  682.          
  683.         string currentValuekey;  
  684.   
  685.         public ExpressionParser(ParameterExpression[] parameters, string expression, object[] values)  
  686.         {  
  687.             if (expression == nullthrow new ArgumentNullException("expression");  
  688.             if (keywords == null) keywords = CreateKeywords();  
  689.             symbols = new Dictionary<stringobject>(StringComparer.OrdinalIgnoreCase);  
  690.             literals = new Dictionary<Expression, string>();  
  691.             if (parameters != null) ProcessParameters(parameters);  
  692.             if (values != null) ProcessValues(values);  
  693.             text = expression;  
  694.             textLen = text.Length;  
  695.             SetTextPos(0);  
  696.             NextToken();  
  697.         }  
  698.         
  699.         public ExpressionParser(ParameterExpression[] parameters, string expression, object[] values,Type[] types)  
  700.         {  
  701.             if (expression == nullthrow new ArgumentNullException("expression");  
  702.             if (keywords == null) keywords = CreateKeywords();  
  703.             symbols = new Dictionary<stringobject>(StringComparer.OrdinalIgnoreCase);  
  704.             symTypes = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);  
  705.             literals = new Dictionary<Expression, string>();  
  706.             if (parameters != null) ProcessParameters(parameters);  
  707.             if (values != null) ProcessValues(values,types);  
  708.             text = expression;  
  709.             textLen = text.Length;  
  710.             SetTextPos(0);  
  711.             NextToken();  
  712.         }  
  713.         void ProcessParameters(ParameterExpression[] parameters)  
  714.         {  
  715.             foreach (ParameterExpression pe in parameters)  
  716.                 if (!String.IsNullOrEmpty(pe.Name))  
  717.                     AddSymbol(pe.Name, pe);  
  718.             if (parameters.Length == 1 && String.IsNullOrEmpty(parameters[0].Name))  
  719.                 it = parameters[0];  
  720.         }  
  721.   
  722.         void ProcessValues(object[] values)  
  723.         {  
  724.             for (int i = 0; i < values.Length; i++)  
  725.             {  
  726.                 object value = values[i];  
  727.                 if (i == values.Length - 1 && value is IDictionary<stringobject>)  
  728.                 {  
  729.                     externals = (IDictionary<stringobject>)value;  
  730.                 }  
  731.                 else  
  732.                 {  
  733.                     AddSymbol("@" + i.ToString(System.Globalization.CultureInfo.InvariantCulture), value);  
  734.                       
  735.                 }  
  736.             }  
  737.         }  
  738.         void ProcessValues(object[] values,Type[] types)  
  739.         {  
  740.             for (int i = 0; i < values.Length; i++)  
  741.             {  
  742.                 object value = values[i];  
  743.                 if (i == values.Length - 1 && value is IDictionary<stringobject>)  
  744.                 {  
  745.                     externals = (IDictionary<stringobject>)value;  
  746.                 }  
  747.                 else  
  748.                 {  
  749.                     AddSymbol("@" + i.ToString(System.Globalization.CultureInfo.InvariantCulture), value,types[i]);  
  750.   
  751.                 }  
  752.             }  
  753.         }  
  754.         void AddSymbol(string name, object value)  
  755.         {  
  756.             if (symbols.ContainsKey(name))  
  757.                 throw ParseError(Res.DuplicateIdentifier, name);  
  758.             symbols.Add(name, value);  
  759.         }  
  760.         
  761.         void AddSymbol(string name, object value,Type returnType)  
  762.         {  
  763.             if (symbols.ContainsKey(name))  
  764.                 throw ParseError(Res.DuplicateIdentifier, name);  
  765.             symbols.Add(name, value);  
  766.   
  767.             symTypes.Add(name, returnType);  
  768.         }  
  769.         public Expression Parse(Type resultType)  
  770.         {  
  771.             int exprPos = token.pos;  
  772.             Expression expr = ParseExpression();  
  773.             if (resultType != null)  
  774.                 if ((expr = PromoteExpression(expr, resultType, true)) == null)  
  775.                     throw ParseError(exprPos, Res.ExpressionTypeMismatch, GetTypeName(resultType));  
  776.             ValidateToken(TokenId.End, Res.SyntaxError);  
  777.             return expr;  
  778.         }  
  779.  
  780. #pragma warning disable 0219  
  781.         public IEnumerable<DynamicOrdering> ParseOrdering()  
  782.         {  
  783.             List<DynamicOrdering> orderings = new List<DynamicOrdering>();  
  784.             while (true)  
  785.             {  
  786.                 Expression expr = ParseExpression();  
  787.                 bool ascending = true;  
  788.                 if (TokenIdentifierIs("asc") || TokenIdentifierIs("ascending"))  
  789.                 {  
  790.                     NextToken();  
  791.                 }  
  792.                 else if (TokenIdentifierIs("desc") || TokenIdentifierIs("descending"))  
  793.                 {  
  794.                     NextToken();  
  795.                     ascending = false;  
  796.                 }  
  797.                 orderings.Add(new DynamicOrdering { Selector = expr, Ascending = ascending });  
  798.                 if (token.id != TokenId.Comma) break;  
  799.                 NextToken();  
  800.             }  
  801.             ValidateToken(TokenId.End, Res.SyntaxError);  
  802.             return orderings;  
  803.         }  
  804. #pragma warning restore 0219  
  805.   
  806.         // ?: operator  
  807.         Expression ParseExpression()  
  808.         {  
  809.             //将方法名置空,以免再datarow构造参数时,少参数  
  810.             currentMothedName = "";  
  811.             int errorPos = token.pos;  
  812.             Expression expr = ParseLogicalOr();  
  813.             if (token.id == TokenId.Question)  
  814.             {  
  815.                 NextToken();  
  816.                 Expression expr1 = ParseExpression();  
  817.                 ValidateToken(TokenId.Colon, Res.ColonExpected);  
  818.                 NextToken();  
  819.                 Expression expr2 = ParseExpression();  
  820.                 expr = GenerateConditional(expr, expr1, expr2, errorPos);  
  821.             }  
  822.             return expr;  
  823.         }  
  824.   
  825.         // ||, or operator  
  826.         Expression ParseLogicalOr()  
  827.         {  
  828.             Expression left = ParseLogicalAnd();  
  829.             while (token.id == TokenId.DoubleBar || TokenIdentifierIs("or"))  
  830.             {  
  831.                 Token op = token;  
  832.                 NextToken();  
  833.                 Expression right = ParseLogicalAnd();  
  834.                 CheckAndPromoteOperands(typeof(ILogicalSignatures), op.text, ref left, ref right, op.pos);  
  835.                 left = Expression.OrElse(left, right);  
  836.             }  
  837.             return left;  
  838.         }  
  839.   
  840.         // &&, and operator  
  841.         Expression ParseLogicalAnd()  
  842.         {  
  843.             Expression left = ParseComparison();  
  844.             while (token.id == TokenId.DoubleAmphersand || TokenIdentifierIs("and"))  
  845.             {  
  846.                 Token op = token;  
  847.                 NextToken();  
  848.                 Expression right = ParseComparison();  
  849.                 CheckAndPromoteOperands(typeof(ILogicalSignatures), op.text, ref left, ref right, op.pos);  
  850.                 left = Expression.AndAlso(left, right);  
  851.             }  
  852.             return left;  
  853.         }  
  854.   
  855.         // =, ==, !=, <>, >, >=, <, <= operators  
  856.         Expression ParseComparison()  
  857.         {  
  858.             Expression left = ParseAdditive();  
  859.             while (token.id == TokenId.Equal || token.id == TokenId.DoubleEqual ||  
  860.                 token.id == TokenId.ExclamationEqual || token.id == TokenId.LessGreater ||  
  861.                 token.id == TokenId.GreaterThan || token.id == TokenId.GreaterThanEqual ||  
  862.                 token.id == TokenId.LessThan || token.id == TokenId.LessThanEqual)  
  863.             {  
  864.                 Token op = token;  
  865.                 NextToken();  
  866.                 Expression right = ParseAdditive();  
  867.                 bool isEquality = op.id == TokenId.Equal || op.id == TokenId.DoubleEqual ||  
  868.                     op.id == TokenId.ExclamationEqual || op.id == TokenId.LessGreater;  
  869.                 if (isEquality && !left.Type.IsValueType && !right.Type.IsValueType)  
  870.                 {  
  871.                     if (left.Type != right.Type)  
  872.                     {  
  873.                         if (left.Type.IsAssignableFrom(right.Type))  
  874.                         {  
  875.                             right = Expression.Convert(right, left.Type);  
  876.                         }  
  877.                         else if (right.Type.IsAssignableFrom(left.Type))  
  878.                         {  
  879.                             left = Expression.Convert(left, right.Type);  
  880.                         }  
  881.                         else  
  882.                         {  
  883.                             throw IncompatibleOperandsError(op.text, left, right, op.pos);  
  884.                         }  
  885.                     }  
  886.                 }  
  887.                 else if (IsEnumType(left.Type) || IsEnumType(right.Type))  
  888.                 {  
  889.                     if (left.Type != right.Type)  
  890.                     {  
  891.                         Expression e;  
  892.                         if ((e = PromoteExpression(right, left.Type, true)) != null)  
  893.                         {  
  894.                             right = e;  
  895.                         }  
  896.                         else if ((e = PromoteExpression(left, right.Type, true)) != null)  
  897.                         {  
  898.                             left = e;  
  899.                         }  
  900.                         else  
  901.                         {  
  902.                             throw IncompatibleOperandsError(op.text, left, right, op.pos);  
  903.                         }  
  904.                     }  
  905.                 }  
  906.                 else  
  907.                 {  
  908.                     CheckAndPromoteOperands(isEquality ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures),  
  909.                         op.text, ref left, ref right, op.pos);  
  910.                 }  
  911.                 switch (op.id)  
  912.                 {  
  913.                     case TokenId.Equal:  
  914.                     case TokenId.DoubleEqual:  
  915.                         left = GenerateEqual(left, right);  
  916.                         break;  
  917.                     case TokenId.ExclamationEqual:  
  918.                     case TokenId.LessGreater:  
  919.                         left = GenerateNotEqual(left, right);  
  920.                         break;  
  921.                     case TokenId.GreaterThan:  
  922.                         left = GenerateGreaterThan(left, right);  
  923.                         break;  
  924.                     case TokenId.GreaterThanEqual:  
  925.                         left = GenerateGreaterThanEqual(left, right);  
  926.                         break;  
  927.                     case TokenId.LessThan:  
  928.                         left = GenerateLessThan(left, right);  
  929.                         break;  
  930.                     case TokenId.LessThanEqual:  
  931.                         left = GenerateLessThanEqual(left, right);  
  932.                         break;  
  933.                 }  
  934.             }  
  935.             return left;  
  936.         }  
  937.   
  938.         // +, -, & operators  
  939.         Expression ParseAdditive()  
  940.         {  
  941.             Expression left = ParseMultiplicative();  
  942.             while (token.id == TokenId.Plus || token.id == TokenId.Minus ||  
  943.                 token.id == TokenId.Amphersand)  
  944.             {  
  945.                 Token op = token;  
  946.                 NextToken();  
  947.                 Expression right = ParseMultiplicative();  
  948.                 switch (op.id)  
  949.                 {  
  950.                     case TokenId.Plus:  
  951.                         if (left.Type == typeof(string) || right.Type == typeof(string))  
  952.                             goto case TokenId.Amphersand;  
  953.                         CheckAndPromoteOperands(typeof(IAddSignatures), op.text, ref left, ref right, op.pos);  
  954.                         left = GenerateAdd(left, right);  
  955.                         break;  
  956.                     case TokenId.Minus:  
  957.                         CheckAndPromoteOperands(typeof(ISubtractSignatures), op.text, ref left, ref right, op.pos);  
  958.                         left = GenerateSubtract(left, right);  
  959.                         break;  
  960.                     case TokenId.Amphersand:  
  961.                         left = GenerateStringConcat(left, right);  
  962.                         break;  
  963.                 }  
  964.             }  
  965.             return left;  
  966.         }  
  967.   
  968.         // *, /, %, mod operators  
  969.         Expression ParseMultiplicative()  
  970.         {  
  971.             Expression left = ParseUnary();  
  972.             while (token.id == TokenId.Asterisk || token.id == TokenId.Slash ||  
  973.                 token.id == TokenId.Percent || TokenIdentifierIs("mod"))  
  974.             {  
  975.                 Token op = token;  
  976.                 NextToken();  
  977.                 Expression right = ParseUnary();  
  978.                 CheckAndPromoteOperands(typeof(IArithmeticSignatures), op.text, ref left, ref right, op.pos);  
  979.                 switch (op.id)  
  980.                 {  
  981.                     case TokenId.Asterisk:  
  982.                         left = Expression.Multiply(left, right);  
  983.                         break;  
  984.                     case TokenId.Slash:  
  985.                         left = Expression.Divide(left, right);  
  986.                         break;  
  987.                     case TokenId.Percent:  
  988.                     case TokenId.Identifier:  
  989.                         left = Expression.Modulo(left, right);  
  990.                         break;  
  991.                 }  
  992.             }  
  993.             return left;  
  994.         }  
  995.   
  996.         // -, !, not unary operators  
  997.         Expression ParseUnary()  
  998.         {  
  999.             if (token.id == TokenId.Minus || token.id == TokenId.Exclamation ||  
  1000.                 TokenIdentifierIs("not"))  
  1001.             {  
  1002.                 Token op = token;  
  1003.                 NextToken();  
  1004.                 if (op.id == TokenId.Minus && (token.id == TokenId.IntegerLiteral ||  
  1005.                     token.id == TokenId.RealLiteral))  
  1006.                 {  
  1007.                     token.text = "-" + token.text;  
  1008.                     token.pos = op.pos;  
  1009.                     return ParsePrimary();  
  1010.                 }  
  1011.                 Expression expr = ParseUnary();  
  1012.                 if (op.id == TokenId.Minus)  
  1013.                 {  
  1014.                     CheckAndPromoteOperand(typeof(INegationSignatures), op.text, ref expr, op.pos);  
  1015.                     expr = Expression.Negate(expr);  
  1016.                 }  
  1017.                 else  
  1018.                 {  
  1019.                     CheckAndPromoteOperand(typeof(INotSignatures), op.text, ref expr, op.pos);  
  1020.                     expr = Expression.Not(expr);  
  1021.                 }  
  1022.                 return expr;  
  1023.             }  
  1024.             return ParsePrimary();  
  1025.         }  
  1026.   
  1027.         Expression ParsePrimary()  
  1028.         {  
  1029.             Expression expr = ParsePrimaryStart();  
  1030.             while (true)  
  1031.             {  
  1032.                 if (token.id == TokenId.Dot)  
  1033.                 {  
  1034.                     NextToken();  
  1035.                     expr = ParseMemberAccess(null, expr);  
  1036.                 }  
  1037.                 else if (token.id == TokenId.OpenBracket)  
  1038.                 {  
  1039.                     expr = ParseElementAccess(expr);  
  1040.                 }  
  1041.                 else  
  1042.                 {  
  1043.                     break;  
  1044.                 }  
  1045.             }  
  1046.             return expr;  
  1047.         }  
  1048.   
  1049.         Expression ParsePrimaryStart()  
  1050.         {  
  1051.             switch (token.id)  
  1052.             {  
  1053.                 case TokenId.Identifier:  
  1054.                     return ParseIdentifier();  
  1055.                 case TokenId.StringLiteral:  
  1056.                     return ParseStringLiteral();  
  1057.                 case TokenId.IntegerLiteral:  
  1058.                     return ParseIntegerLiteral();  
  1059.                 case TokenId.RealLiteral:  
  1060.                     return ParseRealLiteral();  
  1061.                 case TokenId.OpenParen:  
  1062.                     return ParseParenExpression();  
  1063.                 default:  
  1064.                     throw ParseError(Res.ExpressionExpected);  
  1065.             }  
  1066.         }  
  1067.   
  1068.         Expression ParseStringLiteral()  
  1069.         {  
  1070.             ValidateToken(TokenId.StringLiteral);  
  1071.             char quote = token.text[0];  
  1072.             string s = token.text.Substring(1, token.text.Length - 2);  
  1073.             int start = 0;  
  1074.             while (true)  
  1075.             {  
  1076.                 int i = s.IndexOf(quote, start);  
  1077.                 if (i < 0) break;  
  1078.                 s = s.Remove(i, 1);  
  1079.                 start = i + 1;  
  1080.             }  
  1081.             if (quote == '\'')  
  1082.             {  
  1083.                 if (s.Length != 1)  
  1084.                     throw ParseError(Res.InvalidCharacterLiteral);  
  1085.                 NextToken();  
  1086.                 return CreateLiteral(s[0], s);  
  1087.             }  
  1088.             NextToken();  
  1089.             return CreateLiteral(s, s);  
  1090.         }  
  1091.   
  1092.         Expression ParseIntegerLiteral()  
  1093.         {  
  1094.             ValidateToken(TokenId.IntegerLiteral);  
  1095.             string text = token.text;  
  1096.             if (text[0] != '-')  
  1097.             {  
  1098.                 ulong value;  
  1099.                 if (!UInt64.TryParse(text, out value))  
  1100.                     throw ParseError(Res.InvalidIntegerLiteral, text);  
  1101.                 NextToken();  
  1102.                 if (value <= (ulong)Int32.MaxValue) return CreateLiteral((int)value, text);  
  1103.                 if (value <= (ulong)UInt32.MaxValue) return CreateLiteral((uint)value, text);  
  1104.                 if (value <= (ulong)Int64.MaxValue) return CreateLiteral((long)value, text);  
  1105.                 return CreateLiteral(value, text);  
  1106.             }  
  1107.             else  
  1108.             {  
  1109.                 long value;  
  1110.                 if (!Int64.TryParse(text, out value))  
  1111.                     throw ParseError(Res.InvalidIntegerLiteral, text);  
  1112.                 NextToken();  
  1113.                 if (value >= Int32.MinValue && value <= Int32.MaxValue)  
  1114.                     return CreateLiteral((int)value, text);  
  1115.                 return CreateLiteral(value, text);  
  1116.             }  
  1117.         }  
  1118.   
  1119.         Expression ParseRealLiteral()  
  1120.         {  
  1121.             ValidateToken(TokenId.RealLiteral);  
  1122.             string text = token.text;  
  1123.             object value = null;  
  1124.             char last = text[text.Length - 1];  
  1125.             if (last == 'F' || last == 'f')  
  1126.             {  
  1127.                 float f;  
  1128.                 if (Single.TryParse(text.Substring(0, text.Length - 1), out f)) value = f;  
  1129.             }  
  1130.             else  
  1131.             {  
  1132.                 double d;  
  1133.                 if (Double.TryParse(text, out d)) value = d;  
  1134.             }  
  1135.             if (value == nullthrow ParseError(Res.InvalidRealLiteral, text);  
  1136.             NextToken();  
  1137.             return CreateLiteral(value, text);  
  1138.         }  
  1139.   
  1140.         Expression CreateLiteral(object value, string text)  
  1141.         {  
  1142.             ConstantExpression expr = Expression.Constant(value);  
  1143.             literals.Add(expr, text);  
  1144.             return expr;  
  1145.         }  
  1146.   
  1147.         Expression ParseParenExpression()  
  1148.         {  
  1149.             ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);  
  1150.             NextToken();  
  1151.             Expression e = ParseExpression();  
  1152.             ValidateToken(TokenId.CloseParen, Res.CloseParenOrOperatorExpected);  
  1153.             NextToken();  
  1154.             return e;  
  1155.         }  
  1156.   
  1157.         Expression ParseIdentifier()  
  1158.         {  
  1159.             ValidateToken(TokenId.Identifier);  
  1160.             object value;  
  1161.             if (keywords.TryGetValue(token.text, out value))  
  1162.             {  
  1163.                 if (value is Type) return ParseTypeAccess((Type)value);  
  1164.                 if (value == (object)keywordIt) return ParseIt();  
  1165.                 if (value == (object)keywordIif) return ParseIif();  
  1166.                 if (value == (object)keywordNew) return ParseNew();  
  1167.                 NextToken();  
  1168.                 return (Expression)value;  
  1169.             }  
  1170.             if (symbols.TryGetValue(token.text, out value) ||  
  1171.                 externals != null && externals.TryGetValue(token.text, out value))  
  1172.             {  
  1173.                 currentValuekey = token.text;  
  1174.                 Expression expr = value as Expression;  
  1175.                 if (expr == null)  
  1176.                 {  
  1177.                     expr = Expression.Constant(value);  
  1178.                 }  
  1179.                 else  
  1180.                 {  
  1181.                     LambdaExpression lambda = expr as LambdaExpression;  
  1182.                     if (lambda != nullreturn ParseLambdaInvocation(lambda);  
  1183.                 }  
  1184.                 NextToken();  
  1185.                 return expr;  
  1186.             }  
  1187.             if (it != nullreturn ParseMemberAccess(null, it);  
  1188.             throw ParseError(Res.UnknownIdentifier, token.text);  
  1189.         }  
  1190.   
  1191.         Expression ParseIt()  
  1192.         {  
  1193.             if (it == null)  
  1194.                 throw ParseError(Res.NoItInScope);  
  1195.             NextToken();  
  1196.             return it;  
  1197.         }  
  1198.   
  1199.         Expression ParseIif()  
  1200.         {  
  1201.             int errorPos = token.pos;  
  1202.             NextToken();  
  1203.             Expression[] args = ParseArgumentList();  
  1204.             if (args.Length != 3)  
  1205.                 throw ParseError(errorPos, Res.IifRequiresThreeArgs);  
  1206.             return GenerateConditional(args[0], args[1], args[2], errorPos);  
  1207.         }  
  1208.   
  1209.         Expression GenerateConditional(Expression test, Expression expr1, Expression expr2, int errorPos)  
  1210.         {  
  1211.             if (test.Type != typeof(bool))  
  1212.                 throw ParseError(errorPos, Res.FirstExprMustBeBool);  
  1213.             if (expr1.Type != expr2.Type)  
  1214.             {  
  1215.                 Expression expr1as2 = expr2 != nullLiteral ? PromoteExpression(expr1, expr2.Type, true) : null;  
  1216.                 Expression expr2as1 = expr1 != nullLiteral ? PromoteExpression(expr2, expr1.Type, true) : null;  
  1217.                 if (expr1as2 != null && expr2as1 == null)  
  1218.                 {  
  1219.                     expr1 = expr1as2;  
  1220.                 }  
  1221.                 else if (expr2as1 != null && expr1as2 == null)  
  1222.                 {  
  1223.                     expr2 = expr2as1;  
  1224.                 }  
  1225.                 else  
  1226.                 {  
  1227.                     string type1 = expr1 != nullLiteral ? expr1.Type.Name : "null";  
  1228.                     string type2 = expr2 != nullLiteral ? expr2.Type.Name : "null";  
  1229.                     if (expr1as2 != null && expr2as1 != null)  
  1230.                         throw ParseError(errorPos, Res.BothTypesConvertToOther, type1, type2);  
  1231.                     throw ParseError(errorPos, Res.NeitherTypeConvertsToOther, type1, type2);  
  1232.                 }  
  1233.             }  
  1234.             return Expression.Condition(test, expr1, expr2);  
  1235.         }  
  1236.   
  1237.         Expression ParseNew()  
  1238.         {  
  1239.             NextToken();  
  1240.             ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);  
  1241.             NextToken();  
  1242.             List<DynamicProperty> properties = new List<DynamicProperty>();  
  1243.             List<Expression> expressions = new List<Expression>();  
  1244.             while (true)  
  1245.             {  
  1246.                 int exprPos = token.pos;  
  1247.                 Expression expr = ParseExpression();  
  1248.                 string propName;  
  1249.                 if (TokenIdentifierIs("as"))  
  1250.                 {  
  1251.                     NextToken();  
  1252.                     propName = GetIdentifier();  
  1253.                     NextToken();  
  1254.                 }  
  1255.                 else  
  1256.                 {  
  1257.                     MemberExpression me = expr as MemberExpression;  
  1258.                     if (me == nullthrow ParseError(exprPos, Res.MissingAsClause);  
  1259.                     propName = me.Member.Name;  
  1260.                 }  
  1261.                 expressions.Add(expr);  
  1262.                 properties.Add(new DynamicProperty(propName, expr.Type));  
  1263.                 if (token.id != TokenId.Comma) break;  
  1264.                 NextToken();  
  1265.             }  
  1266.             ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected);  
  1267.             NextToken();  
  1268.             Type type = DynamicExpression.CreateClass(properties);  
  1269.             MemberBinding[] bindings = new MemberBinding[properties.Count];  
  1270.             for (int i = 0; i < bindings.Length; i++)  
  1271.                 bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]);  
  1272.             return Expression.MemberInit(Expression.New(type), bindings);  
  1273.         }  
  1274.   
  1275.         Expression ParseLambdaInvocation(LambdaExpression lambda)  
  1276.         {  
  1277.             int errorPos = token.pos;  
  1278.             NextToken();  
  1279.             Expression[] args = ParseArgumentList();  
  1280.             MethodBase method;  
  1281.             if (FindMethod(lambda.Type, "Invoke"false, args, out method) != 1)  
  1282.                 throw ParseError(errorPos, Res.ArgsIncompatibleWithLambda);  
  1283.             return Expression.Invoke(lambda, args);  
  1284.         }  
  1285.   
  1286.         Expression ParseTypeAccess(Type type)  
  1287.         {  
  1288.             int errorPos = token.pos;  
  1289.             NextToken();  
  1290.             if (token.id == TokenId.Question)  
  1291.             {  
  1292.                 if (!type.IsValueType || IsNullableType(type))  
  1293.                     throw ParseError(errorPos, Res.TypeHasNoNullableForm, GetTypeName(type));  
  1294.                 type = typeof(Nullable<>).MakeGenericType(type);  
  1295.                 NextToken();  
  1296.             }  
  1297.             if (token.id == TokenId.OpenParen)  
  1298.             {  
  1299.                 Expression[] args = ParseArgumentList();  
  1300.                 MethodBase method;  
  1301.                 switch (FindBestMethod(type.GetConstructors(), args, out method))  
  1302.                 {  
  1303.                     case 0:  
  1304.                         if (args.Length == 1)  
  1305.                             return GenerateConversion(args[0], type, errorPos);  
  1306.                         throw ParseError(errorPos, Res.NoMatchingConstructor, GetTypeName(type));  
  1307.                     case 1:  
  1308.                         return Expression.New((ConstructorInfo)method, args);  
  1309.                     default:  
  1310.                         throw ParseError(errorPos, Res.AmbiguousConstructorInvocation, GetTypeName(type));  
  1311.                 }  
  1312.             }  
  1313.             ValidateToken(TokenId.Dot, Res.DotOrOpenParenExpected);  
  1314.             NextToken();  
  1315.             return ParseMemberAccess(type, null);  
  1316.         }  
  1317.   
  1318.         Expression GenerateConversion(Expression expr, Type type, int errorPos)  
  1319.         {  
  1320.             Type exprType = expr.Type;  
  1321.             if (exprType == type) return expr;  
  1322.             if (exprType.IsValueType && type.IsValueType)  
  1323.             {  
  1324.                 if ((IsNullableType(exprType) || IsNullableType(type)) &&  
  1325.                     GetNonNullableType(exprType) == GetNonNullableType(type))  
  1326.                     return Expression.Convert(expr, type);  
  1327.                 if ((IsNumericType(exprType) || IsEnumType(exprType)) &&  
  1328.                     (IsNumericType(type)) || IsEnumType(type))  
  1329.                     return Expression.ConvertChecked(expr, type);  
  1330.             }  
  1331.             if (exprType.IsAssignableFrom(type) || type.IsAssignableFrom(exprType) ||  
  1332.                 exprType.IsInterface || type.IsInterface)  
  1333.                 return Expression.Convert(expr, type);  
  1334.             throw ParseError(errorPos, Res.CannotConvertValue,  
  1335.                 GetTypeName(exprType), GetTypeName(type));  
  1336.         }  
  1337.   
  1338.         Expression ParseMemberAccess(Type type, Expression instance)  
  1339.         {  
  1340.             if (instance != null) type = instance.Type;  
  1341.             int errorPos = token.pos;  
  1342.             string id = GetIdentifier();  
  1343.   
  1344.             NextToken();  
  1345.             if (token.id == TokenId.OpenParen)  
  1346.             {  
  1347.                 if (instance != null && type != typeof(string))  
  1348.                 {  
  1349.                     Type enumerableType = FindGenericType(typeof(IEnumerable<>), type);  
  1350.                     if (enumerableType != null)  
  1351.                     {  
  1352.                         Type elementType = enumerableType.GetGenericArguments()[0];  
  1353.                         return ParseAggregate(instance, elementType, id, errorPos);  
  1354.                     }  
  1355.                 }  
  1356.                 Expression[] args = ParseArgumentList();  
  1357.                 MethodBase mb;  
  1358.                 bool isStatic = instance == null;  
  1359.                 Type paraType = type;  
  1360.                 if (it.Type == typeof(System.Data.DataRow))  
  1361.                 {  
  1362.                     isStatic = true;  
  1363.                     paraType = typeof(System.Data.DataRowExtensions);  
  1364.                 }  
  1365.   
  1366.                 switch (FindMethod(paraType, id, isStatic, args, out mb))  
  1367.                 {  
  1368.                     case 0:  
  1369.                         throw ParseError(errorPos, Res.NoApplicableMethod,  
  1370.                             id, GetTypeName(type));  
  1371.                     case 1:  
  1372.                         MethodInfo method = (MethodInfo)mb;  
  1373.                         if (!IsPredefinedType(method.DeclaringType))  
  1374.                             throw ParseError(errorPos, Res.MethodsAreInaccessible, GetTypeName(method.DeclaringType));  
  1375.                         if (method.ReturnType == typeof(void))  
  1376.                             throw ParseError(errorPos, Res.MethodIsVoid,  
  1377.                                 id, GetTypeName(method.DeclaringType));  
  1378.                         if (paraType == typeof(System.Data.DataRowExtensions))  
  1379.                         {  
  1380.                             Type currentType;  
  1381.                             bool isGetType = this.symTypes.TryGetValue(this.currentValuekey, out currentType);  
  1382.                             if (isGetType)  
  1383.                             {  
  1384.                                 return Expression.Call(paraType, id, new Type[] { currentType }, args);  
  1385.                             }  
  1386.                         }  
  1387.                         return Expression.Call(instance, (MethodInfo)method, args);  
  1388.                     default:  
  1389.                         throw ParseError(errorPos, Res.AmbiguousMethodInvocation,  
  1390.                             id, GetTypeName(type));  
  1391.                 }  
  1392.             }  
  1393.             else  
  1394.             {  
  1395.                 MemberInfo member = FindPropertyOrField(type, id, instance == null);  
  1396.                 if (member == null)  
  1397.                     throw ParseError(errorPos, Res.UnknownPropertyOrField,  
  1398.                         id, GetTypeName(type));  
  1399.                 return member is PropertyInfo ?  
  1400.                     Expression.Property(instance, (PropertyInfo)member) :  
  1401.                     Expression.Field(instance, (FieldInfo)member);  
  1402.             }  
  1403.         }  
  1404.   
  1405.         static Type FindGenericType(Type generic, Type type)  
  1406.         {  
  1407.             while (type != null && type != typeof(object))  
  1408.             {  
  1409.                 if (type.IsGenericType && type.GetGenericTypeDefinition() == generic) return type;  
  1410.                 if (generic.IsInterface)  
  1411.                 {  
  1412.                     foreach (Type intfType in type.GetInterfaces())  
  1413.                     {  
  1414.                         Type found = FindGenericType(generic, intfType);  
  1415.                         if (found != nullreturn found;  
  1416.                     }  
  1417.                 }  
  1418.                 type = type.BaseType;  
  1419.             }  
  1420.             return null;  
  1421.         }  
  1422.   
  1423.         Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos)  
  1424.         {  
  1425.             ParameterExpression outerIt = it;  
  1426.             ParameterExpression innerIt = Expression.Parameter(elementType, "");  
  1427.             currentMothedName = methodName;  
  1428.             it = innerIt;  
  1429.             Expression[] args = ParseArgumentList();  
  1430.             it = outerIt;  
  1431.             MethodBase signature;  
  1432.             if (FindMethod(typeof(IEnumerableSignatures), methodName, false, args, out signature) != 1)  
  1433.                 throw ParseError(errorPos, Res.NoApplicableAggregate, methodName);  
  1434.             Type[] typeArgs;  
  1435.             if (signature.Name == "Min" || signature.Name == "Max")  
  1436.             {  
  1437.                 typeArgs = new Type[] { elementType, args[0].Type };  
  1438.             }  
  1439.             else  
  1440.             {  
  1441.                 typeArgs = new Type[] { elementType };  
  1442.             }  
  1443.             if (args.Length == 0)  
  1444.             {  
  1445.                 args = new Expression[] { instance };  
  1446.             }  
  1447.             else  
  1448.             {  
  1449.                 args = new Expression[] { instance, Expression.Lambda(args[0], innerIt) };  
  1450.             }  
  1451.             currentMothedName = "";  
  1452.             return Expression.Call(typeof(Enumerable), signature.Name, typeArgs, args);  
  1453.         }  
  1454.   
  1455.         Expression[] ParseArgumentList()  
  1456.         {  
  1457.             ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);  
  1458.             NextToken();  
  1459.             Expression[] args = token.id != TokenId.CloseParen ? ParseArguments() : new Expression[0];  
  1460.             ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected);  
  1461.             NextToken();  
  1462.             return args;  
  1463.         }  
  1464.   
  1465.         Expression[] ParseArguments()  
  1466.         {  
  1467.             List<Expression> argList = new List<Expression>();  
  1468.             while (true)  
  1469.             {  
  1470.                 ///入参是datarow 则datarow也做为参数传入,以形成 p.field<decimal>("columnname")方式,  
  1471.                 ///但是嵌套 如 select(new { p=>p.key.dlr,p.sum(order=>order.field<decimal>("columnname"))})时,计算SUM值的时候  
  1472.                 ///这里的it表示入参“order”的时候,也是datarow。导致判断出问题  
  1473.                 ///问题:计算SUM 的入参时。在递归调用中,将it赋值称 datarow 类型的入参,导致调用方法出错  
  1474.                 ///解决办法:在调用sum等系统函数时,按方法名判断,方法名不为空,表示调用系统函数 暂时只在ParseAggregate中写入方法名  
  1475.                 ///备注:大神写的代码无限递归,仅仅看明白一小部分,待高手来解决问题吧,目前只能这样了  
  1476.                 if (it != null && it.Type == typeof(System.Data.DataRow) && string.IsNullOrEmpty(currentMothedName))  
  1477.                 {  
  1478.                     argList.Add(it);  
  1479.                 }  
  1480.                
  1481.                 argList.Add(ParseExpression());  
  1482.                 if (token.id != TokenId.Comma) break;  
  1483.                 NextToken();  
  1484.             }  
  1485.             return argList.ToArray();  
  1486.         }  
  1487.   
  1488.         Expression ParseElementAccess(Expression expr)  
  1489.         {  
  1490.             int errorPos = token.pos;  
  1491.             ValidateToken(TokenId.OpenBracket, Res.OpenParenExpected);  
  1492.             NextToken();  
  1493.             Expression[] args = ParseArguments();  
  1494.             ValidateToken(TokenId.CloseBracket, Res.CloseBracketOrCommaExpected);  
  1495.             NextToken();  
  1496.             if (expr.Type.IsArray)  
  1497.             {  
  1498.                 if (expr.Type.GetArrayRank() != 1 || args.Length != 1)  
  1499.                     throw ParseError(errorPos, Res.CannotIndexMultiDimArray);  
  1500.                 Expression index = PromoteExpression(args[0], typeof(int), true);  
  1501.                 if (index == null)  
  1502.                     throw ParseError(errorPos, Res.InvalidIndex);  
  1503.                 return Expression.ArrayIndex(expr, index);  
  1504.             }  
  1505.             else  
  1506.             {  
  1507.                 MethodBase mb;  
  1508.                 switch (FindIndexer(expr.Type, args, out mb))  
  1509.                 {  
  1510.                     case 0:  
  1511.                         throw ParseError(errorPos, Res.NoApplicableIndexer,  
  1512.                             GetTypeName(expr.Type));  
  1513.                     case 1:  
  1514.                         return Expression.Call(expr, (MethodInfo)mb, args);  
  1515.                     default:  
  1516.                         throw ParseError(errorPos, Res.AmbiguousIndexerInvocation,  
  1517.                             GetTypeName(expr.Type));  
  1518.                 }  
  1519.             }  
  1520.         }  
  1521.   
  1522.         static bool IsPredefinedType(Type type)  
  1523.         {  
  1524.             foreach (Type t in predefinedTypes) if (t == type) return true;  
  1525.             return false;  
  1526.         }  
  1527.   
  1528.         static bool IsNullableType(Type type)  
  1529.         {  
  1530.             return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);  
  1531.         }  
  1532.   
  1533.         static Type GetNonNullableType(Type type)  
  1534.         {  
  1535.             return IsNullableType(type) ? type.GetGenericArguments()[0] : type;  
  1536.         }  
  1537.   
  1538.         static string GetTypeName(Type type)  
  1539.         {  
  1540.             Type baseType = GetNonNullableType(type);  
  1541.             string s = baseType.Name;  
  1542.             if (type != baseType) s += '?';  
  1543.             return s;  
  1544.         }  
  1545.   
  1546.         static bool IsNumericType(Type type)  
  1547.         {  
  1548.             return GetNumericTypeKind(type) != 0;  
  1549.         }  
  1550.   
  1551.         static bool IsSignedIntegralType(Type type)  
  1552.         {  
  1553.             return GetNumericTypeKind(type) == 2;  
  1554.         }  
  1555.   
  1556.         static bool IsUnsignedIntegralType(Type type)  
  1557.         {  
  1558.             return GetNumericTypeKind(type) == 3;  
  1559.         }  
  1560.   
  1561.         static int GetNumericTypeKind(Type type)  
  1562.         {  
  1563.             type = GetNonNullableType(type);  
  1564.             if (type.IsEnum) return 0;  
  1565.             switch (Type.GetTypeCode(type))  
  1566.             {  
  1567.                 case TypeCode.Char:  
  1568.                 case TypeCode.Single:  
  1569.                 case TypeCode.Double:  
  1570.                 case TypeCode.Decimal:  
  1571.                     return 1;  
  1572.                 case TypeCode.SByte:  
  1573.                 case TypeCode.Int16:  
  1574.                 case TypeCode.Int32:  
  1575.                 case TypeCode.Int64:  
  1576.                     return 2;  
  1577.                 case TypeCode.Byte:  
  1578.                 case TypeCode.UInt16:  
  1579.                 case TypeCode.UInt32:  
  1580.                 case TypeCode.UInt64:  
  1581.                     return 3;  
  1582.                 default:  
  1583.                     return 0;  
  1584.             }  
  1585.         }  
  1586.   
  1587.         static bool IsEnumType(Type type)  
  1588.         {  
  1589.             return GetNonNullableType(type).IsEnum;  
  1590.         }  
  1591.   
  1592.         void CheckAndPromoteOperand(Type signatures, string opName, ref Expression expr, int errorPos)  
  1593.         {  
  1594.             Expression[] args = new Expression[] { expr };  
  1595.             MethodBase method;  
  1596.             if (FindMethod(signatures, "F"false, args, out method) != 1)  
  1597.                 throw ParseError(errorPos, Res.IncompatibleOperand,  
  1598.                     opName, GetTypeName(args[0].Type));  
  1599.             expr = args[0];  
  1600.         }  
  1601.   
  1602.         void CheckAndPromoteOperands(Type signatures, string opName, ref Expression left, ref Expression right, int errorPos)  
  1603.         {  
  1604.             Expression[] args = new Expression[] { left, right };  
  1605.             MethodBase method;  
  1606.             if (FindMethod(signatures, "F"false, args, out method) != 1)  
  1607.                 throw IncompatibleOperandsError(opName, left, right, errorPos);  
  1608.             left = args[0];  
  1609.             right = args[1];  
  1610.         }  
  1611.   
  1612.         Exception IncompatibleOperandsError(string opName, Expression left, Expression right, int pos)  
  1613.         {  
  1614.             return ParseError(pos, Res.IncompatibleOperands,  
  1615.                 opName, GetTypeName(left.Type), GetTypeName(right.Type));  
  1616.         }  
  1617.   
  1618.         MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess)  
  1619.         {  
  1620.             BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly |  
  1621.                 (staticAccess ? BindingFlags.Static : BindingFlags.Instance);  
  1622.             foreach (Type t in SelfAndBaseTypes(type))  
  1623.             {  
  1624.                 MemberInfo[] members = t.FindMembers(MemberTypes.Property | MemberTypes.Field,  
  1625.                     flags, Type.FilterNameIgnoreCase, memberName);  
  1626.                 if (members.Length != 0) return members[0];  
  1627.             }  
  1628.             return null;  
  1629.         }  
  1630.   
  1631.         int FindMethod(Type type, string methodName, bool staticAccess, Expression[] args, out MethodBase method)  
  1632.         {  
  1633.             BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly |  
  1634.                 (staticAccess ? BindingFlags.Static : BindingFlags.Instance);  
  1635.             foreach (Type t in SelfAndBaseTypes(type))  
  1636.             {  
  1637.                 MemberInfo[] members = t.FindMembers(MemberTypes.Method,  
  1638.                     flags, Type.FilterNameIgnoreCase, methodName);  
  1639.                 int count = FindBestMethod(members.Cast<MethodBase>(), args, out method);  
  1640.                 if (count != 0) return count;  
  1641.             }  
  1642.             method = null;  
  1643.             return 0;  
  1644.         }  
  1645.   
  1646.         int FindIndexer(Type type, Expression[] args, out MethodBase method)  
  1647.         {  
  1648.             foreach (Type t in SelfAndBaseTypes(type))  
  1649.             {  
  1650.                 MemberInfo[] members = t.GetDefaultMembers();  
  1651.                 if (members.Length != 0)  
  1652.                 {  
  1653.                     IEnumerable<MethodBase> methods = members.  
  1654.                         OfType<PropertyInfo>().  
  1655.                         Select(p => (MethodBase)p.GetGetMethod()).  
  1656.                         Where(m => m != null);  
  1657.                     int count = FindBestMethod(methods, args, out method);  
  1658.                     if (count != 0) return count;  
  1659.                 }  
  1660.             }  
  1661.             method = null;  
  1662.             return 0;  
  1663.         }  
  1664.   
  1665.         static IEnumerable<Type> SelfAndBaseTypes(Type type)  
  1666.         {  
  1667.             if (type.IsInterface)  
  1668.             {  
  1669.                 List<Type> types = new List<Type>();  
  1670.                 AddInterface(types, type);  
  1671.                 return types;  
  1672.             }  
  1673.             return SelfAndBaseClasses(type);  
  1674.         }  
  1675.   
  1676.         static IEnumerable<Type> SelfAndBaseClasses(Type type)  
  1677.         {  
  1678.             while (type != null)  
  1679.             {  
  1680.                 yield return type;  
  1681.                 type = type.BaseType;  
  1682.             }  
  1683.         }  
  1684.   
  1685.         static void AddInterface(List<Type> types, Type type)  
  1686.         {  
  1687.             if (!types.Contains(type))  
  1688.             {  
  1689.                 types.Add(type);  
  1690.                 foreach (Type t in type.GetInterfaces()) AddInterface(types, t);  
  1691.             }  
  1692.         }  
  1693.   
  1694.         class MethodData  
  1695.         {  
  1696.             public MethodBase MethodBase;  
  1697.             public ParameterInfo[] Parameters;  
  1698.             public Expression[] Args;  
  1699.         }  
  1700.   
  1701.         int FindBestMethod(IEnumerable<MethodBase> methods, Expression[] args, out MethodBase method)  
  1702.         {  
  1703.             MethodData[] applicable = methods.  
  1704.                 Select(m => new MethodData { MethodBase = m, Parameters = m.GetParameters() }).  
  1705.                 Where(m => IsApplicable(m, args)).  
  1706.                 ToArray();  
  1707.             if (applicable.Length > 1)  
  1708.             {  
  1709.                 applicable = applicable.  
  1710.                     Where(m => applicable.All(n => m == n || IsBetterThan(args, m, n))).  
  1711.                     ToArray();  
  1712.             }  
  1713.             if (applicable.Length == 1)  
  1714.             {  
  1715.                 MethodData md = applicable[0];  
  1716.                 for (int i = 0; i < args.Length; i++) args[i] = md.Args[i];  
  1717.                 method = md.MethodBase;  
  1718.             }  
  1719.             else  
  1720.             {  
  1721.                 method = null;  
  1722.             }  
  1723.             return applicable.Length;  
  1724.         }  
  1725.   
  1726.         bool IsApplicable(MethodData method, Expression[] args)  
  1727.         {  
  1728.             if (method.Parameters.Length != args.Length) return false;  
  1729.             Expression[] promotedArgs = new Expression[args.Length];  
  1730.             for (int i = 0; i < args.Length; i++)  
  1731.             {  
  1732.                 ParameterInfo pi = method.Parameters[i];  
  1733.                 if (pi.IsOut) return false;  
  1734.                 Expression promoted = PromoteExpression(args[i], pi.ParameterType, false);  
  1735.                 if (promoted == nullreturn false;  
  1736.                 promotedArgs[i] = promoted;  
  1737.             }  
  1738.             method.Args = promotedArgs;  
  1739.             return true;  
  1740.         }  
  1741.   
  1742.         Expression PromoteExpression(Expression expr, Type type, bool exact)  
  1743.         {  
  1744.             if (expr.Type == type) return expr;  
  1745.             if (expr is ConstantExpression)  
  1746.             {  
  1747.                 ConstantExpression ce = (ConstantExpression)expr;  
  1748.                 if (ce == nullLiteral)  
  1749.                 {  
  1750.                     if (!type.IsValueType || IsNullableType(type))  
  1751.                         return Expression.Constant(null, type);  
  1752.                 }  
  1753.                 else  
  1754.                 {  
  1755.                     string text;  
  1756.                     if (literals.TryGetValue(ce, out text))  
  1757.                     {  
  1758.                         Type target = GetNonNullableType(type);  
  1759.                         Object value = null;  
  1760.                         switch (Type.GetTypeCode(ce.Type))  
  1761.                         {  
  1762.                             case TypeCode.Int32:  
  1763.                             case TypeCode.UInt32:  
  1764.                             case TypeCode.Int64:  
  1765.                             case TypeCode.UInt64:  
  1766.                                 value = ParseNumber(text, target);  
  1767.                                 break;  
  1768.                             case TypeCode.Double:  
  1769.                                 if (target == typeof(decimal)) value = ParseNumber(text, target);  
  1770.                                 break;  
  1771.                             case TypeCode.String:  
  1772.                                 value = ParseEnum(text, target);  
  1773.                                 break;  
  1774.                         }  
  1775.                         if (value != null)  
  1776.                             return Expression.Constant(value, type);  
  1777.                     }  
  1778.                 }  
  1779.             }  
  1780.             if (IsCompatibleWith(expr.Type, type))  
  1781.             {  
  1782.                 if (type.IsValueType || exact) return Expression.Convert(expr, type);  
  1783.                 return expr;  
  1784.             }  
  1785.             return null;  
  1786.         }  
  1787.   
  1788.         static object ParseNumber(string text, Type type)  
  1789.         {  
  1790.             switch (Type.GetTypeCode(GetNonNullableType(type)))  
  1791.             {  
  1792.                 case TypeCode.SByte:  
  1793.                     sbyte sb;  
  1794.                     if (sbyte.TryParse(text, out sb)) return sb;  
  1795.                     break;  
  1796.                 case TypeCode.Byte:  
  1797.                     byte b;  
  1798.                     if (byte.TryParse(text, out b)) return b;  
  1799.                     break;  
  1800.                 case TypeCode.Int16:  
  1801.                     short s;  
  1802.                     if (short.TryParse(text, out s)) return s;  
  1803.                     break;  
  1804.                 case TypeCode.UInt16:  
  1805.                     ushort us;  
  1806.                     if (ushort.TryParse(text, out us)) return us;  
  1807.                     break;  
  1808.                 case TypeCode.Int32:  
  1809.                     int i;  
  1810.                     if (int.TryParse(text, out i)) return i;  
  1811.                     break;  
  1812.                 case TypeCode.UInt32:  
  1813.                     uint ui;  
  1814.                     if (uint.TryParse(text, out ui)) return ui;  
  1815.                     break;  
  1816.                 case TypeCode.Int64:  
  1817.                     long l;  
  1818.                     if (long.TryParse(text, out l)) return l;  
  1819.                     break;  
  1820.                 case TypeCode.UInt64:  
  1821.                     ulong ul;  
  1822.                     if (ulong.TryParse(text, out ul)) return ul;  
  1823.                     break;  
  1824.                 case TypeCode.Single:  
  1825.                     float f;  
  1826.                     if (float.TryParse(text, out f)) return f;  
  1827.                     break;  
  1828.                 case TypeCode.Double:  
  1829.                     double d;  
  1830.                     if (double.TryParse(text, out d)) return d;  
  1831.                     break;  
  1832.                 case TypeCode.Decimal:  
  1833.                     decimal e;  
  1834.                     if (decimal.TryParse(text, out e)) return e;  
  1835.                     break;  
  1836.             }  
  1837.             return null;  
  1838.         }  
  1839.   
  1840.         static object ParseEnum(string name, Type type)  
  1841.         {  
  1842.             if (type.IsEnum)  
  1843.             {  
  1844.                 MemberInfo[] memberInfos = type.FindMembers(MemberTypes.Field,  
  1845.                     BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static,  
  1846.                     Type.FilterNameIgnoreCase, name);  
  1847.                 if (memberInfos.Length != 0) return ((FieldInfo)memberInfos[0]).GetValue(null);  
  1848.             }  
  1849.             return null;  
  1850.         }  
  1851.   
  1852.         static bool IsCompatibleWith(Type source, Type target)  
  1853.         {  
  1854.             if (source == target) return true;  
  1855.             if (!target.IsValueType) return target.IsAssignableFrom(source);  
  1856.             Type st = GetNonNullableType(source);  
  1857.             Type tt = GetNonNullableType(target);  
  1858.             if (st != source && tt == target) return false;  
  1859.             TypeCode sc = st.IsEnum ? TypeCode.Object : Type.GetTypeCode(st);  
  1860.             TypeCode tc = tt.IsEnum ? TypeCode.Object : Type.GetTypeCode(tt);  
  1861.             switch (sc)  
  1862.             {  
  1863.                 case TypeCode.SByte:  
  1864.                     switch (tc)  
  1865.                     {  
  1866.                         case TypeCode.SByte:  
  1867.                         case TypeCode.Int16:  
  1868.                         case TypeCode.Int32:  
  1869.                         case TypeCode.Int64:  
  1870.                         case TypeCode.Single:  
  1871.                         case TypeCode.Double:  
  1872.                         case TypeCode.Decimal:  
  1873.                             return true;  
  1874.                     }  
  1875.                     break;  
  1876.                 case TypeCode.Byte:  
  1877.                     switch (tc)  
  1878.                     {  
  1879.                         case TypeCode.Byte:  
  1880.                         case TypeCode.Int16:  
  1881.                         case TypeCode.UInt16:  
  1882.                         case TypeCode.Int32:  
  1883.                         case TypeCode.UInt32:  
  1884.                         case TypeCode.Int64:  
  1885.                         case TypeCode.UInt64:  
  1886.                         case TypeCode.Single:  
  1887.                         case TypeCode.Double:  
  1888.                         case TypeCode.Decimal:  
  1889.                             return true;  
  1890.                     }  
  1891.                     break;  
  1892.                 case TypeCode.Int16:  
  1893.                     switch (tc)  
  1894.                     {  
  1895.                         case TypeCode.Int16:  
  1896.                         case TypeCode.Int32:  
  1897.                         case TypeCode.Int64:  
  1898.                         case TypeCode.Single:  
  1899.                         case TypeCode.Double:  
  1900.                         case TypeCode.Decimal:  
  1901.                             return true;  
  1902.                     }  
  1903.                     break;  
  1904.                 case TypeCode.UInt16:  
  1905.                     switch (tc)  
  1906.                     {  
  1907.                         case TypeCode.UInt16:  
  1908.                         case TypeCode.Int32:  
  1909.                         case TypeCode.UInt32:  
  1910.                         case TypeCode.Int64:  
  1911.                         case TypeCode.UInt64:  
  1912.                         case TypeCode.Single:  
  1913.                         case TypeCode.Double:  
  1914.                         case TypeCode.Decimal:  
  1915.                             return true;  
  1916.                     }  
  1917.                     break;  
  1918.                 case TypeCode.Int32:  
  1919.                     switch (tc)  
  1920.                     {  
  1921.                         case TypeCode.Int32:  
  1922.                         case TypeCode.Int64:  
  1923.                         case TypeCode.Single:  
  1924.                         case TypeCode.Double:  
  1925.                         case TypeCode.Decimal:  
  1926.                             return true;  
  1927.                     }  
  1928.                     break;  
  1929.                 case TypeCode.UInt32:  
  1930.                     switch (tc)  
  1931.                     {  
  1932.                         case TypeCode.UInt32:  
  1933.                         case TypeCode.Int64:  
  1934.                         case TypeCode.UInt64:  
  1935.                         case TypeCode.Single:  
  1936.                         case TypeCode.Double:  
  1937.                         case TypeCode.Decimal:  
  1938.                             return true;  
  1939.                     }  
  1940.                     break;  
  1941.                 case TypeCode.Int64:  
  1942.                     switch (tc)  
  1943.                     {  
  1944.                         case TypeCode.Int64:  
  1945.                         case TypeCode.Single:  
  1946.                         case TypeCode.Double:  
  1947.                         case TypeCode.Decimal:  
  1948.                             return true;  
  1949.                     }  
  1950.                     break;  
  1951.                 case TypeCode.UInt64:  
  1952.                     switch (tc)  
  1953.                     {  
  1954.                         case TypeCode.UInt64:  
  1955.                         case TypeCode.Single:  
  1956.                         case TypeCode.Double:  
  1957.                         case TypeCode.Decimal:  
  1958.                             return true;  
  1959.                     }  
  1960.                     break;  
  1961.                 case TypeCode.Single:  
  1962.                     switch (tc)  
  1963.                     {  
  1964.                         case TypeCode.Single:  
  1965.                         case TypeCode.Double:  
  1966.                             return true;  
  1967.                     }  
  1968.                     break;  
  1969.                 default:  
  1970.                     if (st == tt) return true;  
  1971.                     break;  
  1972.             }  
  1973.             return false;  
  1974.         }  
  1975.   
  1976.         static bool IsBetterThan(Expression[] args, MethodData m1, MethodData m2)  
  1977.         {  
  1978.             bool better = false;  
  1979.             for (int i = 0; i < args.Length; i++)  
  1980.             {  
  1981.                 int c = CompareConversions(args[i].Type,  
  1982.                     m1.Parameters[i].ParameterType,  
  1983.                     m2.Parameters[i].ParameterType);  
  1984.                 if (c < 0) return false;  
  1985.                 if (c > 0) better = true;  
  1986.             }  
  1987.             return better;  
  1988.         }  
  1989.   
  1990.         // Return 1 if s -> t1 is a better conversion than s -> t2  
  1991.         // Return -1 if s -> t2 is a better conversion than s -> t1  
  1992.         // Return 0 if neither conversion is better  
  1993.         static int CompareConversions(Type s, Type t1, Type t2)  
  1994.         {  
  1995.             if (t1 == t2) return 0;  
  1996.             if (s == t1) return 1;  
  1997.             if (s == t2) return -1;  
  1998.             bool t1t2 = IsCompatibleWith(t1, t2);  
  1999.             bool t2t1 = IsCompatibleWith(t2, t1);  
  2000.             if (t1t2 && !t2t1) return 1;  
  2001.             if (t2t1 && !t1t2) return -1;  
  2002.             if (IsSignedIntegralType(t1) && IsUnsignedIntegralType(t2)) return 1;  
  2003.             if (IsSignedIntegralType(t2) && IsUnsignedIntegralType(t1)) return -1;  
  2004.             return 0;  
  2005.         }  
  2006.   
  2007.         Expression GenerateEqual(Expression left, Expression right)  
  2008.         {  
  2009.             return Expression.Equal(left, right);  
  2010.         }  
  2011.   
  2012.         Expression GenerateNotEqual(Expression left, Expression right)  
  2013.         {  
  2014.             return Expression.NotEqual(left, right);  
  2015.         }  
  2016.   
  2017.         Expression GenerateGreaterThan(Expression left, Expression right)  
  2018.         {  
  2019.             if (left.Type == typeof(string))  
  2020.             {  
  2021.                 return Expression.GreaterThan(  
  2022.                     GenerateStaticMethodCall("Compare", left, right),  
  2023.                     Expression.Constant(0)  
  2024.                 );  
  2025.             }  
  2026.             return Expression.GreaterThan(left, right);  
  2027.         }  
  2028.   
  2029.         Expression GenerateGreaterThanEqual(Expression left, Expression right)  
  2030.         {  
  2031.             if (left.Type == typeof(string))  
  2032.             {  
  2033.                 return Expression.GreaterThanOrEqual(  
  2034.                     GenerateStaticMethodCall("Compare", left, right),  
  2035.                     Expression.Constant(0)  
  2036.                 );  
  2037.             }  
  2038.             return Expression.GreaterThanOrEqual(left, right);  
  2039.         }  
  2040.   
  2041.         Expression GenerateLessThan(Expression left, Expression right)  
  2042.         {  
  2043.             if (left.Type == typeof(string))  
  2044.             {  
  2045.                 return Expression.LessThan(  
  2046.                     GenerateStaticMethodCall("Compare", left, right),  
  2047.                     Expression.Constant(0)  
  2048.                 );  
  2049.             }  
  2050.             return Expression.LessThan(left, right);  
  2051.         }  
  2052.   
  2053.         Expression GenerateLessThanEqual(Expression left, Expression right)  
  2054.         {  
  2055.             if (left.Type == typeof(string))  
  2056.             {  
  2057.                 return Expression.LessThanOrEqual(  
  2058.                     GenerateStaticMethodCall("Compare", left, right),  
  2059.                     Expression.Constant(0)  
  2060.                 );  
  2061.             }  
  2062.             return Expression.LessThanOrEqual(left, right);  
  2063.         }  
  2064.   
  2065.         Expression GenerateAdd(Expression left, Expression right)  
  2066.         {  
  2067.             if (left.Type == typeof(string) && right.Type == typeof(string))  
  2068.             {  
  2069.                 return GenerateStaticMethodCall("Concat", left, right);  
  2070.             }  
  2071.             return Expression.Add(left, right);  
  2072.         }  
  2073.   
  2074.         Expression GenerateSubtract(Expression left, Expression right)  
  2075.         {  
  2076.             return Expression.Subtract(left, right);  
  2077.         }  
  2078.   
  2079.         Expression GenerateStringConcat(Expression left, Expression right)  
  2080.         {  
  2081.             return Expression.Call(  
  2082.                 null,  
  2083.                 typeof(string).GetMethod("Concat"new[] { typeof(object), typeof(object) }),  
  2084.                 new[] { left, right });  
  2085.         }  
  2086.   
  2087.         MethodInfo GetStaticMethod(string methodName, Expression left, Expression right)  
  2088.         {  
  2089.             return left.Type.GetMethod(methodName, new[] { left.Type, right.Type });  
  2090.         }  
  2091.   
  2092.         Expression GenerateStaticMethodCall(string methodName, Expression left, Expression right)  
  2093.         {  
  2094.             return Expression.Call(null, GetStaticMethod(methodName, left, right), new[] { left, right });  
  2095.         }  
  2096.   
  2097.         void SetTextPos(int pos)  
  2098.         {  
  2099.             textPos = pos;  
  2100.             ch = textPos < textLen ? text[textPos] : '\0';  
  2101.         }  
  2102.   
  2103.         void NextChar()  
  2104.         {  
  2105.             if (textPos < textLen) textPos++;  
  2106.             ch = textPos < textLen ? text[textPos] : '\0';  
  2107.         }  
  2108.   
  2109.         void NextToken()  
  2110.         {  
  2111.             while (Char.IsWhiteSpace(ch)) NextChar();  
  2112.             TokenId t;  
  2113.             int tokenPos = textPos;  
  2114.             switch (ch)  
  2115.             {  
  2116.                 case '!':  
  2117.                     NextChar();  
  2118.                     if (ch == '=')  
  2119.                     {  
  2120.                         NextChar();  
  2121.                         t = TokenId.ExclamationEqual;  
  2122.                     }  
  2123.                     else  
  2124.                     {  
  2125.                         t = TokenId.Exclamation;  
  2126.                     }  
  2127.                     break;  
  2128.                 case '%':  
  2129.                     NextChar();  
  2130.                     t = TokenId.Percent;  
  2131.                     break;  
  2132.                 case '&':  
  2133.                     NextChar();  
  2134.                     if (ch == '&')  
  2135.                     {  
  2136.                         NextChar();  
  2137.                         t = TokenId.DoubleAmphersand;  
  2138.                     }  
  2139.                     else  
  2140.                     {  
  2141.                         t = TokenId.Amphersand;  
  2142.                     }  
  2143.                     break;  
  2144.                 case '(':  
  2145.                     NextChar();  
  2146.                     t = TokenId.OpenParen;  
  2147.                     break;  
  2148.                 case ')':  
  2149.                     NextChar();  
  2150.                     t = TokenId.CloseParen;  
  2151.                     break;  
  2152.                 case '*':  
  2153.                     NextChar();  
  2154.                     t = TokenId.Asterisk;  
  2155.                     break;  
  2156.                 case '+':  
  2157.                     NextChar();  
  2158.                     t = TokenId.Plus;  
  2159.                     break;  
  2160.                 case ',':  
  2161.                     NextChar();  
  2162.                     t = TokenId.Comma;  
  2163.                     break;  
  2164.                 case '-':  
  2165.                     NextChar();  
  2166.                     t = TokenId.Minus;  
  2167.                     break;  
  2168.                 case '.':  
  2169.                     NextChar();  
  2170.                     t = TokenId.Dot;  
  2171.                     break;  
  2172.                 case '/':  
  2173.                     NextChar();  
  2174.                     t = TokenId.Slash;  
  2175.                     break;  
  2176.                 case ':':  
  2177.                     NextChar();  
  2178.                     t = TokenId.Colon;  
  2179.                     break;  
  2180.                 case '<':  
  2181.                     NextChar();  
  2182.                     if (ch == '=')  
  2183.                     {  
  2184.                         NextChar();  
  2185.                         t = TokenId.LessThanEqual;  
  2186.                     }  
  2187.                     else if (ch == '>')  
  2188.                     {  
  2189.                         NextChar();  
  2190.                         t = TokenId.LessGreater;  
  2191.                     }  
  2192.                     else  
  2193.                     {  
  2194.                         t = TokenId.LessThan;  
  2195.                     }  
  2196.                     break;  
  2197.                 case '=':  
  2198.                     NextChar();  
  2199.                     if (ch == '=')  
  2200.                     {  
  2201.                         NextChar();  
  2202.                         t = TokenId.DoubleEqual;  
  2203.                     }  
  2204.                     else  
  2205.                     {  
  2206.                         t = TokenId.Equal;  
  2207.                     }  
  2208.                     break;  
  2209.                 case '>':  
  2210.                     NextChar();  
  2211.                     if (ch == '=')  
  2212.                     {  
  2213.                         NextChar();  
  2214.                         t = TokenId.GreaterThanEqual;  
  2215.                     }  
  2216.                     else  
  2217.                     {  
  2218.                         t = TokenId.GreaterThan;  
  2219.                     }  
  2220.                     break;  
  2221.                 case '?':  
  2222.                     NextChar();  
  2223.                     t = TokenId.Question;  
  2224.                     break;  
  2225.                 case '[':  
  2226.                     NextChar();  
  2227.                     t = TokenId.OpenBracket;  
  2228.                     break;  
  2229.                 case ']':  
  2230.                     NextChar();  
  2231.                     t = TokenId.CloseBracket;  
  2232.                     break;  
  2233.                 case '|':  
  2234.                     NextChar();  
  2235.                     if (ch == '|')  
  2236.                     {  
  2237.                         NextChar();  
  2238.                         t = TokenId.DoubleBar;  
  2239.                     }  
  2240.                     else  
  2241.                     {  
  2242.                         t = TokenId.Bar;  
  2243.                     }  
  2244.                     break;  
  2245.                 case '"':  
  2246.                 case '\'':  
  2247.                     char quote = ch;  
  2248.                     do  
  2249.                     {  
  2250.                         NextChar();  
  2251.                         while (textPos < textLen && ch != quote) NextChar();  
  2252.                         if (textPos == textLen)  
  2253.                             throw ParseError(textPos, Res.UnterminatedStringLiteral);  
  2254.                         NextChar();  
  2255.                     } while (ch == quote);  
  2256.                     t = TokenId.StringLiteral;  
  2257.                     break;  
  2258.                 default:  
  2259.                     if (Char.IsLetter(ch) || ch == '@' || ch == '_')  
  2260.                     {  
  2261.                         do  
  2262.                         {  
  2263.                             NextChar();  
  2264.                         } while (Char.IsLetterOrDigit(ch) || ch == '_');  
  2265.                         t = TokenId.Identifier;  
  2266.                         break;  
  2267.                     }  
  2268.                     if (Char.IsDigit(ch))  
  2269.                     {  
  2270.                         t = TokenId.IntegerLiteral;  
  2271.                         do  
  2272.                         {  
  2273.                             NextChar();  
  2274.                         } while (Char.IsDigit(ch));  
  2275.                         if (ch == '.')  
  2276.                         {  
  2277.                             t = TokenId.RealLiteral;  
  2278.                             NextChar();  
  2279.                             ValidateDigit();  
  2280.                             do  
  2281.                             {  
  2282.                                 NextChar();  
  2283.                             } while (Char.IsDigit(ch));  
  2284.                         }  
  2285.                         if (ch == 'E' || ch == 'e')  
  2286.                         {  
  2287.                             t = TokenId.RealLiteral;  
  2288.                             NextChar();  
  2289.                             if (ch == '+' || ch == '-') NextChar();  
  2290.                             ValidateDigit();  
  2291.                             do  
  2292.                             {  
  2293.                                 NextChar();  
  2294.                             } while (Char.IsDigit(ch));  
  2295.                         }  
  2296.                         if (ch == 'F' || ch == 'f') NextChar();  
  2297.                         break;  
  2298.                     }  
  2299.                     if (textPos == textLen)  
  2300.                     {  
  2301.                         t = TokenId.End;  
  2302.                         break;  
  2303.                     }  
  2304.                     throw ParseError(textPos, Res.InvalidCharacter, ch);  
  2305.             }  
  2306.             token.id = t;  
  2307.             token.text = text.Substring(tokenPos, textPos - tokenPos);  
  2308.             token.pos = tokenPos;  
  2309.         }  
  2310.   
  2311.         bool TokenIdentifierIs(string id)  
  2312.         {  
  2313.             return token.id == TokenId.Identifier && String.Equals(id, token.text, StringComparison.OrdinalIgnoreCase);  
  2314.         }  
  2315.   
  2316.         string GetIdentifier()  
  2317.         {  
  2318.             ValidateToken(TokenId.Identifier, Res.IdentifierExpected);  
  2319.             string id = token.text;  
  2320.             if (id.Length > 1 && id[0] == '@') id = id.Substring(1);  
  2321.             return id;  
  2322.         }  
  2323.   
  2324.         void ValidateDigit()  
  2325.         {  
  2326.             if (!Char.IsDigit(ch)) throw ParseError(textPos, Res.DigitExpected);  
  2327.         }  
  2328.   
  2329.         void ValidateToken(TokenId t, string errorMessage)  
  2330.         {  
  2331.             if (token.id != t) throw ParseError(errorMessage);  
  2332.         }  
  2333.   
  2334.         void ValidateToken(TokenId t)  
  2335.         {  
  2336.             if (token.id != t) throw ParseError(Res.SyntaxError);  
  2337.         }  
  2338.   
  2339.         Exception ParseError(string format, params object[] args)  
  2340.         {  
  2341.             return ParseError(token.pos, format, args);  
  2342.         }  
  2343.   
  2344.         Exception ParseError(int pos, string format, params object[] args)  
  2345.         {  
  2346.             return new ParseException(string.Format(System.Globalization.CultureInfo.CurrentCulture, format, args), pos);  
  2347.         }  
  2348.   
  2349.         static Dictionary<stringobject> CreateKeywords()  
  2350.         {  
  2351.             Dictionary<stringobject> d = new Dictionary<stringobject>(StringComparer.OrdinalIgnoreCase);  
  2352.             d.Add("true", trueLiteral);  
  2353.             d.Add("false", falseLiteral);  
  2354.             d.Add("null", nullLiteral);  
  2355.             d.Add(keywordIt, keywordIt);  
  2356.             d.Add(keywordIif, keywordIif);  
  2357.             d.Add(keywordNew, keywordNew);  
  2358.             foreach (Type type in predefinedTypes) d.Add(type.Name, type);  
  2359.             return d;  
  2360.         }  
  2361.     }  
  2362.   
  2363.     static class Res  
  2364.     {  
  2365.         public const string DuplicateIdentifier = "The identifier '{0}' was defined more than once";  
  2366.         public const string ExpressionTypeMismatch = "Expression of type '{0}' expected";  
  2367.         public const string ExpressionExpected = "Expression expected";  
  2368.         public const string InvalidCharacterLiteral = "Character literal must contain exactly one character";  
  2369.         public const string InvalidIntegerLiteral = "Invalid integer literal '{0}'";  
  2370.         public const string InvalidRealLiteral = "Invalid real literal '{0}'";  
  2371.         public const string UnknownIdentifier = "Unknown identifier '{0}'";  
  2372.         public const string NoItInScope = "No 'it' is in scope";  
  2373.         public const string IifRequiresThreeArgs = "The 'iif' function requires three arguments";  
  2374.         public const string FirstExprMustBeBool = "The first expression must be of type 'Boolean'";  
  2375.         public const string BothTypesConvertToOther = "Both of the types '{0}' and '{1}' convert to the other";  
  2376.         public const string NeitherTypeConvertsToOther = "Neither of the types '{0}' and '{1}' converts to the other";  
  2377.         public const string MissingAsClause = "Expression is missing an 'as' clause";  
  2378.         public const string ArgsIncompatibleWithLambda = "Argument list incompatible with lambda expression";  
  2379.         public const string TypeHasNoNullableForm = "Type '{0}' has no nullable form";  
  2380.         public const string NoMatchingConstructor = "No matching constructor in type '{0}'";  
  2381.         public const string AmbiguousConstructorInvocation = "Ambiguous invocation of '{0}' constructor";  
  2382.         public const string CannotConvertValue = "A value of type '{0}' cannot be converted to type '{1}'";  
  2383.         public const string NoApplicableMethod = "No applicable method '{0}' exists in type '{1}'";  
  2384.         public const string MethodsAreInaccessible = "Methods on type '{0}' are not accessible";  
  2385.         public const string MethodIsVoid = "Method '{0}' in type '{1}' does not return a value";  
  2386.         public const string AmbiguousMethodInvocation = "Ambiguous invocation of method '{0}' in type '{1}'";  
  2387.         public const string UnknownPropertyOrField = "No property or field '{0}' exists in type '{1}'";  
  2388.         public const string NoApplicableAggregate = "No applicable aggregate method '{0}' exists";  
  2389.         public const string CannotIndexMultiDimArray = "Indexing of multi-dimensional arrays is not supported";  
  2390.         public const string InvalidIndex = "Array index must be an integer expression";  
  2391.         public const string NoApplicableIndexer = "No applicable indexer exists in type '{0}'";  
  2392.         public const string AmbiguousIndexerInvocation = "Ambiguous invocation of indexer in type '{0}'";  
  2393.         public const string IncompatibleOperand = "Operator '{0}' incompatible with operand type '{1}'";  
  2394.         public const string IncompatibleOperands = "Operator '{0}' incompatible with operand types '{1}' and '{2}'";  
  2395.         public const string UnterminatedStringLiteral = "Unterminated string literal";  
  2396.         public const string InvalidCharacter = "Syntax error '{0}'";  
  2397.         public const string DigitExpected = "Digit expected";  
  2398.         public const string SyntaxError = "Syntax error";  
  2399.         public const string TokenExpected = "{0} expected";  
  2400.         public const string ParseExceptionFormat = "{0} (at index {1})";  
  2401.         public const string ColonExpected = "':' expected";  
  2402.         public const string OpenParenExpected = "'(' expected";  
  2403.         public const string CloseParenOrOperatorExpected = "')' or operator expected";  
  2404.         public const string CloseParenOrCommaExpected = "')' or ',' expected";  
  2405.         public const string DotOrOpenParenExpected = "'.' or '(' expected";  
  2406.         public const string OpenBracketExpected = "'[' expected";  
  2407.         public const string CloseBracketOrCommaExpected = "']' or ',' expected";  
  2408.         public const string IdentifierExpected = "Identifier expected";  
  2409.     }  
  2410. }  
原创粉丝点击