// using System;
// using System.Collections.Generic;
// using System.Linq;
// using System.Linq.Expressions;
// using System.Text;
// using System.Reflection;
// using System.ComponentModel;
// using System.Globalization;
//
//
// namespace ExpressionsParser {
// 	
// 	/// <summary>
// 	/// Runtime parser for string expressions (formulas, method calls etc) into LINQ expression tree or lambda delegate.
// 	/// </summary>
// 	public class LambdaParser {
//
// 		static readonly char[] delimiters = new char[] {
// 			'(', ')', '[', ']', '?', ':', '.', ',', '=', '<', '>', '!', '&', '|', '*', '/', '%', '+','-', '{', '}'};
// 		static readonly char[] specialNameChars = new char[] {
// 			'_' };
// 		const char charQuote = '"';
// 		static readonly string[] mulOps = new[] {"*", "/", "%" };
// 		static readonly string[] addOps = new[] { "+", "-" };
// 		static readonly string[] eqOps = new[] { "==", "!=", "<", ">", "<=", ">=" };
//
// 		readonly IDictionary<string, CompiledExpression> CachedExpressions = new Dictionary<string, CompiledExpression>();
// 		readonly object _lock = new object();
//
// 		/// <summary>
// 		/// Gets or sets whether LambdaParser should use the cache for parsed expressions.
// 		/// </summary>
// 		public bool UseCache { get; set; }
//
// 		/// <summary>
// 		/// Allows usage of "=" for equality comparison (in addition to "=="). False by default.
// 		/// </summary>
// 		public bool AllowSingleEqualSign { get; set; }
//
// 		/// <summary>
// 		/// Gets value comparer used by the parser for comparison operators.
// 		/// </summary>
// 		public IValueComparer Comparer { get; private set; }
//
// 		public LambdaParser() {
// 			UseCache = true;
// 			AllowSingleEqualSign = false;
// 			Comparer = ValueComparer.Instance;
// 		}
//
// 		public LambdaParser(IValueComparer valueComparer) : this() {
// 			Comparer = valueComparer;
// 		}
//
// 		internal class ExtractParamsVisitor : ExpressionVisitor {
// 			internal List<ParameterExpression> ParamsList;
// 			public ExtractParamsVisitor() {
// 				ParamsList = new List<ParameterExpression>();
// 			}
//
// 			public override Expression Visit(Expression node) {
// 				if (node!=null && node.NodeType == ExpressionType.Parameter)
// 					ParamsList.Add( (ParameterExpression)node);
// 				return base.Visit(node);
// 			}
// 		}
//
// 		public static ParameterExpression[] GetExpressionParameters(Expression expr) {
// 			var paramsVisitor = new ExtractParamsVisitor();
// 			paramsVisitor.Visit(expr);
// 			return paramsVisitor.ParamsList.ToArray();
// 		}
//
// 		public object Eval(string expr, IDictionary<string, object> vars) {
// 			return Eval(expr, (varName) => {
// 				object val = null;
// 				vars.TryGetValue(varName, out val);
// 				return val;
// 			});
// 		}
//
//         public LambdaExpression CurrentExpression { get; private set; }
//         public Delegate CurrentCompileDelegate { get; private set; }
//
//         public object Eval(string expr, Func<string,object> getVarValue) {
// 			CompiledExpression compiledExpr = null;
// 			if (UseCache) {
// 				lock (_lock) {
// 					CachedExpressions.TryGetValue(expr, out compiledExpr);
// 				}
// 			}
//
// 			if (compiledExpr == null) {
// 				var linqExpr = Parse(expr);
// 				compiledExpr = new CompiledExpression() {
// 					Parameters = GetExpressionParameters(linqExpr)
// 				};
//                 CurrentExpression = Expression.Lambda(linqExpr, compiledExpr.Parameters);
//                 CurrentCompileDelegate = compiledExpr.Lambda = CurrentExpression.Compile();
//
//                 if (UseCache)
// 					lock (_lock) {
// 						CachedExpressions[expr] = compiledExpr;
// 					}
// 			}
//
// 			var valuesList = new List<object>();
// 			foreach (var paramExpr in compiledExpr.Parameters) {
// 				valuesList.Add( new LambdaParameterWrapper( getVarValue(paramExpr.Name), Comparer) );
// 			}
//
// 			var lambdaRes = compiledExpr.Lambda.DynamicInvoke(valuesList.ToArray());
// 			if (lambdaRes is LambdaParameterWrapper)
// 				lambdaRes = ((LambdaParameterWrapper)lambdaRes).Value;
// 			return lambdaRes;
// 		}
//
//
// 		public Expression Parse(string expr) {
// 			var parseResult = ParseConditional(expr, 0);
// 			var lastLexem = ReadLexem(expr, parseResult.End);
// 			if (lastLexem.Type != LexemType.Stop)
// 				throw new LambdaParserException(expr, parseResult.End, "Invalid expression");
// 			return parseResult.Expr;
// 		}
//
// 		protected Lexem ReadLexem(string s, int startIdx) {
// 			var lexem = new Lexem();
// 			lexem.Type = LexemType.Unknown;
// 			lexem.Expr = s;
// 			lexem.Start = startIdx;
// 			lexem.End = startIdx;
// 			while (lexem.End < s.Length) {
// 				if (Array.IndexOf(delimiters, s[lexem.End]) >= 0) {
// 					if (lexem.Type == LexemType.Unknown) {
// 						lexem.End++;
// 						lexem.Type = LexemType.Delimiter;
// 						return lexem;
// 					}
// 					if (lexem.Type != LexemType.StringConstant && (lexem.Type != LexemType.NumberConstant || s[lexem.End] != '.'))
// 						return lexem; // stop
// 				} else if (char.IsSeparator(s[lexem.End])) {
// 					if (lexem.Type != LexemType.StringConstant && lexem.Type != LexemType.Unknown)
// 						return lexem; // stop
// 				} else if (char.IsLetter(s[lexem.End])) {
// 					if (lexem.Type == LexemType.Unknown)
// 						lexem.Type = LexemType.Name;
// 				} else if (char.IsDigit(s[lexem.End])) {
// 					if (lexem.Type == LexemType.Unknown)
// 						lexem.Type = LexemType.NumberConstant;
// 				} else if (Array.IndexOf(specialNameChars, s[lexem.End]) >= 0) {
// 					if (lexem.Type == LexemType.Unknown || lexem.Type==LexemType.Name) {
// 						lexem.Type = LexemType.Name;
// 					} else if (lexem.Type!=LexemType.StringConstant)
// 						return lexem;
// 				} else if (s[lexem.End] == charQuote) {
// 					if (lexem.Type == LexemType.Unknown)
// 						lexem.Type = LexemType.StringConstant;
// 					else {
// 						if (lexem.Type == LexemType.StringConstant) {
// 							// check for "" combination
// 							if (((lexem.End + 1) >= s.Length || s[lexem.End + 1] != charQuote)) {
// 								lexem.End++;
// 								return lexem;
// 							} else
// 								if ((lexem.End + 1) < s.Length)
// 									lexem.End++; // skip next quote
// 						} else {
// 							return lexem;
// 						}
// 					}
// 				} else if (char.IsControl(s[lexem.End]) && lexem.Type != LexemType.Unknown && lexem.Type != LexemType.StringConstant)
// 					return lexem;
//
// 				// goto next char
// 				lexem.End++;
// 			}
//
// 			if (lexem.Type == LexemType.Unknown) {
// 				lexem.Type = LexemType.Stop;
// 				return lexem;
// 			}
// 			if (lexem.Type == LexemType.StringConstant)
// 				throw new LambdaParserException(s, startIdx, "Unterminated string constant");
// 			return lexem;
// 		}
//
//
// 		static readonly ConstructorInfo LambdaParameterWrapperConstructor = 
// 			#if NET40
// 			typeof(LambdaParameterWrapper).GetConstructor(new[] { typeof(object) });
// 			#else
// 			typeof(LambdaParameterWrapper).GetTypeInfo().DeclaredConstructors.First();
// 			#endif
//
// 		protected ParseResult ParseConditional(string expr, int start) {
// 			var testExpr = ParseOr(expr, start);
//  			var ifLexem = ReadLexem(expr, testExpr.End);
// 			if (ifLexem.Type == LexemType.Delimiter && ifLexem.GetValue() == "?") {
// 				// read positive expr
// 				var positiveOp = ParseOr(expr, ifLexem.End);
// 				var positiveOpExpr = Expression.New(LambdaParameterWrapperConstructor, 
// 						Expression.Convert(positiveOp.Expr,typeof(object)),
// 						Expression.Constant(Comparer));
//
// 				var elseLexem = ReadLexem(expr, positiveOp.End);
// 				if (elseLexem.Type == LexemType.Delimiter && elseLexem.GetValue() == ":") {
// 					var negativeOp = ParseOr(expr, elseLexem.End);
// 					var negativeOpExpr = Expression.New(LambdaParameterWrapperConstructor, 
// 							Expression.Convert( negativeOp.Expr, typeof(object)),
// 							Expression.Constant(Comparer));
// 					return new ParseResult() {
// 						End = negativeOp.End,
// 						Expr = Expression.Condition( Expression.IsTrue( testExpr.Expr ), positiveOpExpr, negativeOpExpr)
// 					};
//
// 				} else {
// 					throw new LambdaParserException(expr, positiveOp.End, "Expected ':'");
// 				}
// 			}
// 			return testExpr;
// 		}
//
// 		Expression WrapLambdaParameterIsTrueIfNeeded(Expression expr) {
// 			if (expr.Type == typeof(LambdaParameterWrapper))
// 				return Expression.Property(expr, "IsTrue");
// 			return expr;
// 		}
//
// 		protected ParseResult ParseOr(string expr, int start) {
// 			var firstOp = ParseAnd(expr, start);
// 			do {
// 				var opLexem = ReadLexem(expr, firstOp.End);
// 				var isOr = false;
// 				if (opLexem.Type == LexemType.Name && opLexem.GetValue() == "or") {
// 					isOr = true;
// 				} else if (opLexem.Type == LexemType.Delimiter && opLexem.GetValue() == "|") {
// 					opLexem = ReadLexem(expr, opLexem.End);
// 					if (opLexem.Type == LexemType.Delimiter && opLexem.GetValue() == "|")
// 						isOr = true;
// 				}
//
// 				if (isOr) {
// 					var secondOp = ParseOr(expr, opLexem.End);
// 					firstOp = new ParseResult() {
// 						End = secondOp.End,
// 						Expr = Expression.OrElse( 
// 							WrapLambdaParameterIsTrueIfNeeded(firstOp.Expr), 
// 							WrapLambdaParameterIsTrueIfNeeded(secondOp.Expr) )
// 					};
// 				} else
// 					break;
// 			} while (true);
// 			return firstOp;
// 		}
//
// 		protected ParseResult ParseAnd(string expr, int start) {
// 			var firstOp = ParseEq(expr, start);
// 			do {
// 				var opLexem = ReadLexem(expr, firstOp.End);
// 				var isAnd = false;
// 				if (opLexem.Type == LexemType.Name && opLexem.GetValue() == "and") {
// 					isAnd = true;
// 				} else if (opLexem.Type == LexemType.Delimiter && opLexem.GetValue() == "&") {
// 					opLexem = ReadLexem(expr, opLexem.End);
// 					if (opLexem.Type == LexemType.Delimiter && opLexem.GetValue() == "&")
// 						isAnd = true;
// 				}
//
// 				if (isAnd) {
// 					var secondOp = ParseAnd(expr, opLexem.End);
// 					firstOp = new ParseResult() {
// 						End = secondOp.End,
// 						Expr = Expression.AndAlso(
// 									WrapLambdaParameterIsTrueIfNeeded(firstOp.Expr),
// 									WrapLambdaParameterIsTrueIfNeeded(secondOp.Expr))
// 					};
// 				} else
// 					break;
// 			} while (true);
// 			return firstOp;
// 		}
//
// 		protected ParseResult ParseEq(string expr, int start) {
// 			var firstOp = ParseAdditive(expr, start);
// 			do {
// 				var opLexem = ReadLexem(expr, firstOp.End);
// 				if (opLexem.Type == LexemType.Delimiter) {
// 					var nextOpLexem = ReadLexem(expr, opLexem.End);
// 					if (nextOpLexem.Type == LexemType.Delimiter) {
// 						var opVal = opLexem.GetValue() + nextOpLexem.GetValue();
// 						if (eqOps.Contains(opVal)) {
// 							var secondOp = ParseAdditive(expr, nextOpLexem.End);
//
// 							switch (opVal) {
// 								case "==":
// 									firstOp = new ParseResult() {
// 										End = secondOp.End,
// 										Expr = Expression.Equal(firstOp.Expr, secondOp.Expr)
// 									};
// 									continue;
// 								case "<>":
// 								case "!=":
// 									firstOp = new ParseResult() {
// 										End = secondOp.End,
// 										Expr = Expression.NotEqual(firstOp.Expr, secondOp.Expr)
// 									};
// 									continue;
// 								case ">=":
// 									firstOp = new ParseResult() {
// 										End = secondOp.End,
// 										Expr = Expression.GreaterThanOrEqual(firstOp.Expr, secondOp.Expr)
// 									};
// 									continue;
// 								case "<=":
// 									firstOp = new ParseResult() {
// 										End = secondOp.End,
// 										Expr = Expression.LessThanOrEqual(firstOp.Expr, secondOp.Expr)
// 									};
// 									continue;
//
// 							}
// 						}
//
// 					}
//
// 					if (opLexem.GetValue() == ">" || opLexem.GetValue() == "<" 
// 						|| (AllowSingleEqualSign && opLexem.GetValue() == "=") ) {
// 						var secondOp = ParseAdditive(expr, opLexem.End);
// 						switch (opLexem.GetValue()) {
// 							case ">":
// 								firstOp = new ParseResult() {
// 									End = secondOp.End,
// 									Expr = Expression.GreaterThan(firstOp.Expr, secondOp.Expr)
// 								};
// 								continue;
// 							case "<":
// 								firstOp = new ParseResult() {
// 									End = secondOp.End,
// 									Expr = Expression.LessThan(firstOp.Expr, secondOp.Expr)
// 								};
// 								continue;
// 							case "=":
// 								firstOp = new ParseResult() {
// 									End = secondOp.End,
// 									Expr = Expression.Equal(firstOp.Expr, secondOp.Expr)
// 								};
// 								continue;
// 						}
// 					}
//
// 				}
// 				break;
// 			} while (true);
// 			return firstOp;
// 		}
//
//
// 		protected ParseResult ParseAdditive(string expr, int start) {
// 			var firstOp = ParseMultiplicative(expr, start);
// 			do {
// 				var opLexem = ReadLexem(expr, firstOp.End);
// 				if (opLexem.Type == LexemType.Delimiter && addOps.Contains(opLexem.GetValue())) {
// 					var secondOp = ParseMultiplicative(expr, opLexem.End);
// 					var res = new ParseResult() { End = secondOp.End };
// 					switch (opLexem.GetValue()) {
// 						case "+":
// 							res.Expr = Expression.Add(firstOp.Expr, secondOp.Expr);
// 							break;
// 						case "-":
// 							res.Expr = Expression.Subtract(firstOp.Expr, secondOp.Expr);
// 							break;
// 					}
// 					firstOp = res;
// 					continue;
// 				}
// 				break;
// 			} while (true);
// 			return firstOp;
// 		}
//
// 		protected ParseResult ParseMultiplicative(string expr, int start) {
// 			var firstOp = ParseUnary(expr, start);
// 			do {
// 				var opLexem = ReadLexem(expr, firstOp.End);
// 				if (opLexem.Type == LexemType.Delimiter && mulOps.Contains(opLexem.GetValue())) {
// 					var secondOp = ParseUnary(expr, opLexem.End);
// 					var res = new ParseResult() { End = secondOp.End };
// 					switch (opLexem.GetValue()) {
// 						case "*":
// 							res.Expr = Expression.Multiply(firstOp.Expr, secondOp.Expr);
// 							break;
// 						case "/":
// 							res.Expr = Expression.Divide(firstOp.Expr, secondOp.Expr);
// 							break;
// 						case "%":
// 							res.Expr = Expression.Modulo(firstOp.Expr, secondOp.Expr);
// 							break;
// 					}
// 					firstOp = res;
// 					continue;
// 				}
// 				break;
// 			} while (true);
// 			return firstOp;
// 		}
//
// 		protected ParseResult ParseUnary(string expr, int start) {
// 			var opLexem = ReadLexem(expr, start);
// 			if (opLexem.Type == LexemType.Delimiter) {
// 				switch (opLexem.GetValue()) {
// 					case "-": {
// 						var operand = ParsePrimary(expr, opLexem.End);
// 						operand.Expr = Expression.Negate(operand.Expr);
// 						return operand;
// 					}
// 					case "!": {
// 						var operand = ParsePrimary(expr, opLexem.End);
// 						operand.Expr = Expression.Not(operand.Expr);
// 						return operand;
// 					}
// 				}
// 			}
// 			return ParsePrimary(expr, start);
// 		}
//
// 		private static MethodInfo GetLambdaParameterWrapperMethod(string methodName) {
// 			#if NET40
// 			return typeof(LambdaParameterWrapper).GetMethod(methodName,	BindingFlags.Instance | BindingFlags.Public);
// 			#else
// 			return typeof(LambdaParameterWrapper).GetTypeInfo().DeclaredMethods.Where(m=>m.Name==methodName).First();
// 			#endif
// 		}
//
// 		static readonly MethodInfo InvokeMethodMI = GetLambdaParameterWrapperMethod("InvokeMethod");
//
// 		static readonly MethodInfo InvokeDelegateMI = GetLambdaParameterWrapperMethod("InvokeDelegate");
//
// 		static readonly MethodInfo InvokePropertyOrFieldMI = GetLambdaParameterWrapperMethod("InvokePropertyOrField");
//
// 		static readonly MethodInfo InvokeIndexerMI = GetLambdaParameterWrapperMethod("InvokeIndexer");
//
// 		static readonly MethodInfo CreateDictionaryMI = GetLambdaParameterWrapperMethod("CreateDictionary");
//
// 		protected ParseResult ParsePrimary(string expr, int start) {
// 			var val = ParseValue(expr, start);
// 			do {
// 				var lexem = ReadLexem(expr, val.End);
// 				if (lexem.Type==LexemType.Delimiter) {
// 					if (lexem.GetValue() == ".") { // member or method
// 						var memberLexem = ReadLexem(expr, lexem.End);
// 						if (memberLexem.Type == LexemType.Name) {
// 							var openCallLexem = ReadLexem(expr, memberLexem.End);
// 							if (openCallLexem.Type == LexemType.Delimiter && openCallLexem.GetValue() == "(") {
// 								var methodParams = new List<Expression>();
// 								var paramsEnd = ReadCallArguments(expr, openCallLexem.End, ")", methodParams);
// 								var paramsExpr = Expression.NewArrayInit(typeof(object), methodParams);
// 								val = new ParseResult() {
// 									End = paramsEnd,
// 									Expr = Expression.Call(
// 										Expression.Constant(new LambdaParameterWrapper(null,Comparer)),
// 										InvokeMethodMI, 
// 										val.Expr, 
// 										Expression.Constant(memberLexem.GetValue()),
// 										paramsExpr)
// 								};
// 								continue;
// 							} else {
// 								// member
// 								val = new ParseResult() {
// 									End = memberLexem.End,
// 									Expr = Expression.Call(
// 										Expression.Constant(new LambdaParameterWrapper(null, Comparer)),
// 										InvokePropertyOrFieldMI,
// 										val.Expr, Expression.Constant(memberLexem.GetValue()))
// 								};
// 								continue;
// 							}
// 						}
// 					} else if (lexem.GetValue()=="[") {
// 						var indexerParams = new List<Expression>();
// 						var paramsEnd = ReadCallArguments(expr, lexem.End, "]", indexerParams);
// 						val = new ParseResult() {
// 							End = paramsEnd,
// 							Expr = Expression.Call(
// 								Expression.Constant(new LambdaParameterWrapper(null, Comparer)),
// 								InvokeIndexerMI, val.Expr, 
// 								Expression.NewArrayInit(typeof(object), indexerParams)
// 							)
// 						};
// 						continue;
// 					} else if (lexem.GetValue()=="(") {
// 						var methodParams = new List<Expression>();
// 						var paramsEnd = ReadCallArguments(expr, lexem.End, ")", methodParams);
// 						var paramsExpr = Expression.NewArrayInit(typeof(object), methodParams);
// 						val = new ParseResult() {
// 							End = paramsEnd,
// 							Expr = Expression.Call(
// 								Expression.Constant(new LambdaParameterWrapper(null, Comparer)),
// 								InvokeDelegateMI, 
// 								val.Expr, paramsExpr)
// 						};
// 						continue;
// 					}
// 				}
// 				break;
// 			} while (true);
// 			return val;
// 		}
//
// 		protected int ReadCallArguments(string expr, int start, string endLexem, List<Expression> args) {
// 			var end = start;
// 			do {
// 				var lexem = ReadLexem(expr, end);
// 				if (lexem.Type == LexemType.Delimiter) {
// 					if (lexem.GetValue() == endLexem) {
// 						return lexem.End;
// 					} else if (lexem.GetValue() == ",") {
// 						if (args.Count == 0) {
// 							throw new LambdaParserException(expr, lexem.Start, "Expected method call parameter");
// 						}
// 						end = lexem.End;
// 					}
// 				}
// 				// read parameter
// 				var paramExpr = ParseConditional(expr, end);
// 				args.Add(paramExpr.Expr);
// 				end = paramExpr.End;
// 			} while (true);
// 		}
//
// 		protected ParseResult ParseValue(string expr, int start) {
// 			var lexem = ReadLexem(expr, start);
//
// 			if (lexem.Type == LexemType.Delimiter && lexem.GetValue() == "(") {
// 				var groupRes = ParseConditional(expr, lexem.End);
// 				var endLexem = ReadLexem(expr, groupRes.End);
// 				if (endLexem.Type != LexemType.Delimiter || endLexem.GetValue() != ")")
// 					throw new LambdaParserException(expr, endLexem.Start, "Expected ')'");
// 				groupRes.End = endLexem.End;
// 				return groupRes;
// 			} else if (lexem.Type == LexemType.NumberConstant) {
// 				decimal numConst;
// 				if (!Decimal.TryParse(lexem.GetValue(), NumberStyles.Any, CultureInfo.InvariantCulture, out numConst)) {
// 					throw new Exception(String.Format("Invalid number: {0}", lexem.GetValue())); 
// 				}
// 				return new ParseResult() { 
// 					End = lexem.End, 
// 					Expr = Expression.Constant(new LambdaParameterWrapper( numConst, Comparer) ) };
// 			} else if (lexem.Type == LexemType.StringConstant) {
// 				return new ParseResult() { 
// 					End = lexem.End, 
// 					Expr = Expression.Constant( new LambdaParameterWrapper( lexem.GetValue(), Comparer) ) };
// 			} else if (lexem.Type == LexemType.Name) {
// 				// check for predefined constants
// 				var val = lexem.GetValue();
// 				switch (val) {
// 					case "true":
// 						return new ParseResult() { End = lexem.End, Expr = Expression.Constant(new LambdaParameterWrapper(true, Comparer) ) };
// 					case "false":
// 						return new ParseResult() { End = lexem.End, Expr = Expression.Constant(new LambdaParameterWrapper(false, Comparer) ) };
// 					case "null":
// 						return new ParseResult() { End = lexem.End, Expr = Expression.Constant(new LambdaParameterWrapper(null, Comparer)) };
// 					case "new":
// 						return ReadNewInstance(expr, lexem.End);
// 				}
//
// 				// todo 
//
// 				return new ParseResult() { End = lexem.End, Expr = Expression.Parameter(typeof(LambdaParameterWrapper), val) };
// 			}
// 			throw new LambdaParserException(expr, start, "Expected value");
// 		}
//
// 		protected ParseResult ReadNewInstance(string expr, int start) {
// 			var nextLexem = ReadLexem(expr, start);
// 			if (nextLexem.Type == LexemType.Delimiter && nextLexem.GetValue() == "[") {
// 				nextLexem = ReadLexem(expr, nextLexem.End);
// 				if (!(nextLexem.Type == LexemType.Delimiter && nextLexem.GetValue() == "]"))
// 					throw new LambdaParserException(expr, nextLexem.Start, "Expected ']'");
//
// 				nextLexem = ReadLexem(expr, nextLexem.End);
// 				if (!(nextLexem.Type == LexemType.Delimiter && nextLexem.GetValue() == "{"))
// 					throw new LambdaParserException(expr, nextLexem.Start, "Expected '{'");
//
// 				var arrayArgs = new List<Expression>();
// 				var end = ReadCallArguments(expr, nextLexem.End, "}", arrayArgs);
// 				var newArrExpr = Expression.NewArrayInit(typeof(object), arrayArgs );
// 				return new ParseResult() { 
// 					End = end,
// 					Expr = Expression.New(LambdaParameterWrapperConstructor, 
// 						Expression.Convert(newArrExpr, typeof(object)),
// 						Expression.Constant(Comparer)) 
// 				};
// 			}
// 			if (nextLexem.Type == LexemType.Name && nextLexem.GetValue().ToLower() == "dictionary") {
// 				nextLexem = ReadLexem(expr, nextLexem.End);
// 				if (!(nextLexem.Type == LexemType.Delimiter && nextLexem.GetValue() == "{"))
// 					throw new LambdaParserException(expr, nextLexem.Start, "Expected '{'");
//
// 				var dictionaryKeys = new List<Expression>();
// 				var dictionaryValues = new List<Expression>();
// 				do {
// 					nextLexem = ReadLexem(expr, nextLexem.End);
// 					if (!(nextLexem.Type == LexemType.Delimiter && nextLexem.GetValue() == "{"))
// 						throw new LambdaParserException(expr, nextLexem.Start, "Expected '{'");
// 					var entryArgs = new List<Expression>();
// 					var end = ReadCallArguments(expr, nextLexem.End, "}", entryArgs);
// 					if (entryArgs.Count!=2)
// 						throw new LambdaParserException(expr, nextLexem.Start, "Dictionary entry should have exactly 2 arguments");
// 					
// 					dictionaryKeys.Add( entryArgs[0] );
// 					dictionaryValues.Add( entryArgs[1] );
// 					
// 					nextLexem = ReadLexem(expr, end);
// 				} while (nextLexem.Type == LexemType.Delimiter && nextLexem.GetValue() == ",");
//
// 				if (!(nextLexem.Type == LexemType.Delimiter && nextLexem.GetValue() == "}"))
// 					throw new LambdaParserException(expr, nextLexem.Start, "Expected '}'");
//
// 				var newKeysArrExpr = Expression.NewArrayInit(typeof(object), dictionaryKeys );
// 				var newValuesArrExpr = Expression.NewArrayInit(typeof(object), dictionaryValues );
//
// 				return new ParseResult() {
// 					End = nextLexem.End,
// 					Expr = Expression.Call(
// 						Expression.Constant(new LambdaParameterWrapper(null, Comparer)),
// 						CreateDictionaryMI,
// 						newKeysArrExpr, newValuesArrExpr)
// 				};
// 			}
// 			throw new LambdaParserException(expr, start, "Unknown new instance initializer");
// 		}
//
// 		protected enum LexemType {
// 			Unknown,
// 			Name,
// 			Delimiter,
// 			StringConstant,
// 			NumberConstant,
// 			Stop
// 		}
//
// 		protected struct Lexem {
// 			public LexemType Type;
// 			public int Start;
// 			public int End;
// 			public string Expr;
//
// 			string rawValue;
//
// 			public string GetValue() {
// 				if (rawValue==null) {
// 					rawValue = Expr.Substring(Start, End-Start).Trim();
// 					if (Type==LexemType.StringConstant) {
// 						rawValue = rawValue.Substring(1, rawValue.Length-2).Replace( "\"\"", "\"" ); 
// 					}
// 				}
// 				return rawValue;
// 			}
// 		}
//
// 		protected struct ParseResult {
// 			public Expression Expr;
// 			public int End;
// 		}
//
// 		public class CompiledExpression {
// 			public Delegate Lambda;
// 			public ParameterExpression[] Parameters;
// 		}
//
//
// 	}
// }
