/// <summary> /// Replaces ( and ) with open and close group tokens /// </summary> /// <param name="tokens">tokens input</param> /// <returns>tokens</returns> private static List <FilterExpressionToken> ReplaceGroupTokens(List <FilterExpressionToken> tokens) { List <SymbolToken> openClosed = tokens.Where(x => x is PrimitiveExpressionToken pet && (pet.Token.IsSymbolToken('(') || pet.Token.IsSymbolToken(')'))) .Cast <PrimitiveExpressionToken>() .Select(x => x.Token.CastToSymbolToken()) .ToList(); if (openClosed.Any()) { if (openClosed.First().IsSymbolToken(')')) { throw new UnexpectedTokenException(openClosed.First()); } if (openClosed.Last().IsSymbolToken('(')) { throw new UnexpectedTokenException(openClosed.Last()); } int openCount = openClosed.Count(x => x.IsSymbolToken('(')); int closedCount = openClosed.Count(x => x.IsSymbolToken(')')); if (openCount > closedCount) { throw new UnexpectedTokenException("Not all ( are closed with )"); } if (openCount < closedCount) { throw new UnexpectedTokenException("Not all ) have matching ("); } } else { return(tokens); } List <FilterExpressionToken> ret = tokens.ToList(); Stack <int> groupIds = new Stack <int>(); for (int i = 0; i < ret.Count; i++) { if (ret[i] is PrimitiveExpressionToken pet) { if (pet.Token.IsSymbolToken('(')) { groupIds.Push(i); ret[i] = new OpenGroupToken(pet.Token.CastToSymbolToken(), i, groupIds.Count); } else if (pet.Token.IsSymbolToken(')')) { ret[i] = new CloseGroupToken(pet.Token.CastToSymbolToken(), groupIds.Pop()); } } } return(ret); }
private static List <FilterExpressionToken> ReplaceMethodCallsOnProps(List <FilterExpressionToken> tokens) { List <PropertyExpressionToken> propTokens = tokens.Where(x => x is PropertyExpressionToken).Cast <PropertyExpressionToken>().ToList(); List <FilterExpressionToken> ret = tokens.ToList(); foreach (PropertyExpressionToken pt in propTokens) { int nextIndex = ret.IndexOf(pt) + 1; if (nextIndex < ret.Count && ret[nextIndex] is OpenGroupToken) { OpenGroupToken open = ret[nextIndex] as OpenGroupToken; CloseGroupToken close = ret.First(x => x is CloseGroupToken cgt && cgt.GroupId == open.GroupId) as CloseGroupToken; int openIndex = ret.IndexOf(open); int closeIndex = ret.IndexOf(close); List <FilterExpressionToken> args = new List <FilterExpressionToken>(); for (int i = openIndex + 1; i < closeIndex; i++) { args.Add(ret[i]); } args = FormatAndValidateMethodArgumentTokens(args); string methodName; PropertyExpressionToken allButLast = pt.AllButLast(out methodName); int ptIndex = ret.IndexOf(pt); ret[ptIndex] = new MethodCallExpressionToken(allButLast, methodName, args.ToArray()); List <FilterExpressionToken> toRemove = new List <FilterExpressionToken>(); for (int i = ptIndex + 1; i <= closeIndex; i++) { ret[i] = null; } } } return(ret.Where(x => x != null).ToList()); }