示例#1
0
        /// <summary>
        /// Translates infix expressions into postfix expressions
        /// </summary>
        /// <param name="query">Infix query that has been split into its tokens</param>
        /// <param name="attributes"></param>
        public SearchAlgorithm(ArrayList query, ArrayList attributes)
        {
            // define valid tokens
            operators = new ArrayList();
            operands  = attributes;
            // here we hardcode opernads and operators; this can be done in a more elegant manner.
            string[] t1 = { "AND", "OR", "(", ")" }; // operators and parentheses
            operators.AddRange(t1);
            // Create and instantiate a new empty Stack.
            Stack rpnStack = new Stack();

            // apply dijkstra algorithm using a stack to convert infix to postfix notation (=rpn)
            Infix.AddRange(query);
            foreach (string infixToken in Infix)
            {
                // Replace underscores with space for things like "Fiero 2M4"
                string token = infixToken;
                if (token.Contains("_"))
                {
                    token = token.Replace("_", " ");
                }

                if (operands.Contains(token))
                {   // move operands across to output
                    Postfix.Add(token);
                }
                else if (token.Equals("("))
                {   // push open parenthesis onto stack
                    rpnStack.Push(token);
                }
                else if (token.Equals(")"))
                {   // pop all operators off the stack until the mathcing open parenthesis is found
                    while ((rpnStack.Count > 0) && !((string)rpnStack.Peek()).Equals("("))
                    {
                        Postfix.Add(rpnStack.Pop());  // transfer operator to output
                        if (rpnStack.Count == 0)
                        {
                            throw new Exception("Unbalanced parenthesis. Make sure you close any parenthesis and don't have any extras!");
                        }
                    }
                    if (rpnStack.Count == 0)
                    {
                        throw new Exception("Unbalanced parenthesis. Make sure you close any parenthesis and don't have any extras!");
                    }
                    rpnStack.Pop(); // discard open parenthesis
                }
                else if (operators.Contains(token))
                {   // push operand to the rpn stack after moving to output all higher or equal priority operators
                    while (rpnStack.Count > 0 && ((string)rpnStack.Peek()).Equals("AND"))
                    {
                        Postfix.Add(rpnStack.Pop()); // pop and add to output
                    }
                    rpnStack.Push(token);            // now pus the operator onto the stack
                }
                else
                {
                    if (token.Length >= 8 && token.Substring(token.Length - Seat_Suffix_Length) == "-SEATER")
                    {
                        throw new Exception(string.Format("No matches found for a {0} vehicle! Try a different number of seats.", token));
                    }
                    throw new Exception(string.Format("Unrecognised token '{0}'. Ensure you only use 'AND', 'OR', '(' or ')', in addition to " +
                                                      "vehicle attributes only!", token));
                }
            }
            // now copy what's left on the rpnStack
            while (rpnStack.Count > 0)
            {   // move to the output all remaining operators
                if (((string)rpnStack.Peek()).Equals("("))
                {
                    throw new Exception("Unbalanced parenthesis. Make sure you close any parenthesis and don't have any extras!");
                }
                Postfix.Add(rpnStack.Pop());
            }
        }