示例#1
0
 // See http://en.wikipedia.org/wiki/Shunting-yard_algorithm
 private static ArrayList<QueryToken> PrepareQueryPlan(ArrayList<QueryToken> tokens, QueryOperatorPrecedence precedenceType)
 {
     ArrayList<QueryToken> output = new ArrayList<QueryToken>();
     Stack<QueryToken> stack = new Stack<QueryToken>();
     foreach (QueryToken token in tokens) // While there are tokens to be read:
     {
         switch (GetTokenType(token))
         {
             case TokenType.Term: // If the token is a number...
                 output.Add(token); // ...then add it to the output queue.
                 while (stack.Count > 0 && GetTokenType(stack.Peek()) == TokenType.Function) { output.Add(stack.Pop()); } // *** this fixes function scope when used without brackets
                 break;
             case TokenType.Function: // If the token is a function token... 
                 stack.Push(token); // ...then push it onto the stack.
                 break;
             case TokenType.Operator: // If the token is an operator, o1, then:
                 QueryToken o1 = token;
                 QueryToken o2;
                 // while there is an operator token, o2, at the top of the stack, and either o1 is left-associative and its precedence is equal to that of o2,
                 // or o1 has precedence less than that of o2...
                 while (stack.Count > 0 && GetTokenType(o2 = stack.Peek()) == TokenType.Operator && GetPrecedence(o1, precedenceType) <= GetPrecedence(o2, precedenceType))
                 {
                     output.Add(stack.Pop()); // ...pop o2 off the stack, onto the output queue.
                 }
                 stack.Push(o1); // Push o1 onto the stack.
                 break;
             case TokenType.LeftParenthesis: // If the token is a left parenthesis... 
                 stack.Push(token); // ...then push it onto the stack.
                 break;
             case TokenType.RightParenthesis: // If the token is a right parenthesis:
                 while (stack.Count > 0 && GetTokenType(stack.Peek()) != TokenType.LeftParenthesis) // Until the token at the top of the stack is a left parenthesis...
                 {
                     output.Add(stack.Pop()); // ...pop operators off the stack onto the output queue.
                 }
                 if (stack.Count == 0) { throw new Exception("Parenthesis mismatch."); } // If the stack runs out without finding a left parenthesis, then there are mismatched parentheses.
                 stack.Pop(); // Pop the left parenthesis from the stack, but not onto the output queue.
                 // If the token at the top of the stack is a function token, pop it onto the output queue.
                 if (stack.Count > 0 && GetTokenType(stack.Peek()) == TokenType.Function) { output.Add(stack.Pop()); }
                 break;
         }
     }
     // When there are no more tokens to read:
     while (stack.Count > 0) // While there are still operator tokens in the stack:
     {
         QueryToken o = stack.Pop();
         // If the operator token on the top of the stack is a parenthesis, then there are mismatched parentheses.
         if (GetTokenType(o) == TokenType.LeftParenthesis || GetTokenType(o) == TokenType.RightParenthesis) { throw new Exception("Parenthesis mismatch."); }
         output.Add(o); // Pop the operator onto the output queue.
     }
     return output;
 } 
示例#2
0
 public static ArrayList<QueryToken> PrepareQueryPlan(string query, string tokenRegex, QueryOperatorPrecedence precedenceType = QueryOperatorPrecedence.AndBeforeOr, bool caseSensitive = true)
 {
     ArrayList<QueryToken> tokens = TokenizeQuery(query, tokenRegex, caseSensitive);
     ArrayList<QueryToken> plan = PrepareQueryPlan(tokens, precedenceType);
     return plan;
 }
示例#3
0
 private static int GetPrecedence(string op, QueryOperatorPrecedence precedenceType)
 {
     int rev = precedenceType == QueryOperatorPrecedence.OrBeforeAnd ? 1 : 0;
     if (op == "AND") { return 1 - rev; }
     if (op == "OR") { return 0 + rev; }
     throw new ArgumentNotSupportedException("op");
 }