public Expr BuildExpressionTree(string text) { var tokenList = new List <TokenInfo>(); int tokenListNumber = 0; // 1. read all tokens and build initial tree by Parens using (TextReader sr = new StringReader(text)) { var t = new SqlTokenizer(sr, _resolver); var current = t.Token; var openParenStack = new List <int>(); while (current != Token.EOF) { tokenList.Add(t.Info); // read expression if (current == Token.OpenParens) { openParenStack.Add(tokenListNumber); } if (current == Token.CloseParens) { if (openParenStack.Count < 1) { throw new Exception($"Cannot find open parens for close parens ')'"); } var openParensIndex = openParenStack.Last(); openParenStack.RemoveAt(openParenStack.Count - 1); //var sb = new StringBuilder(); var expr = new List <TokenInfo>(); for (int i = openParensIndex + 1; i <= tokenListNumber; i++) { var ti = tokenList[i]; //sb.Append($"{ti.Field}{ti.Param}{ti.Operator}{ti.Number}{ti.StringLiteral}"); if (ti != null && ti.Token != Token.CloseParens) { expr.Add(ti); tokenList[i] = null; } //if(ti?.Token == Token.CloseParens) //{ // tokenList[i] = null; //} } tokenList[openParensIndex] = new TokenInfo { Token = Token.ParensExpression, Expression = expr }; tokenList[tokenListNumber] = null; } // next t.NextToken(); current = t.Token; tokenListNumber++; } tokenList = tokenList.Where(x => x != null && x.Token != Token.CloseParens).ToList(); } if (!tokenList.Any()) { return(new Expr { Type = ExprType.None }); } // 2. Apply logical operators in order : = AND OR var prioDict = _resolver.GetPriorityOperators(); var min = prioDict.Keys.Min(); var max = prioDict.Keys.Max(); for (int i = min; i <= max; i++) { ApplyOperators(tokenList, prioDict[i]); } var sb = new StringBuilder(); PrintExpressions(tokenList, sb); Console.WriteLine(sb.ToString()); var mainExpr = new Expr { Type = ExprType.Expr }; BuildTree(tokenList, mainExpr); return(mainExpr); }