/// <summary>
        /// Final part of the shunting yard algorithm
        /// Pop and push elements to evaluate the search expression
        /// Shlomo 2020
        /// </summary>
        /// <param name="result">Array of vehicle registrations that match search</param>
        /// <param name="searchAlgorithm">Search algorithm instance to use</param>
        public void searchFleet(out string[] result, SearchAlgorithm searchAlgorithm)
        {
            // Create and instantiate a new empty Stack for result sets.
            Stack            setStack = new Stack();
            HashSet <string> hs1;
            HashSet <string> hs2;
            HashSet <string> hs;
            int idx;

            String[] temp = new string[] { };
            for (int i = 0; i < searchAlgorithm.Postfix.Count; i++)
            {
                if (searchAlgorithm.Postfix[i].Equals("AND"))
                {
                    // pop two sets off the stack and apply Intersect, push back result
                    hs1  = (HashSet <string>)setStack.Pop();
                    hs2  = (HashSet <string>)setStack.Pop();
                    temp = hs1.ToArray <string>();     // copy the elements of the set hs1
                    hs   = new HashSet <string>(temp); // make a deep copy of hs1
                    hs.IntersectWith(hs2);             // apply the Intersect to the new set
                    setStack.Push(hs);                 // push a reference to a new set
                }
                else if (searchAlgorithm.Postfix[i].Equals("OR"))
                {
                    // pop two sets off the stack and apply Union
                    hs1  = (HashSet <string>)setStack.Pop();
                    hs2  = (HashSet <string>)setStack.Pop();
                    temp = hs1.ToArray <string>();     // copy the elements of the set hs1
                    hs   = new HashSet <string>(temp); // make a deep copy of hs1
                    hs.UnionWith(hs2);                 // apply the Union to the new set
                    setStack.Push(hs);                 // push a reference to a new set
                }
                else
                {
                    // here if an operand
                    idx = attributeSets.IndexOfKey(searchAlgorithm.Postfix[i]); // identify attribute set
                    if (idx >= 0)
                    {
                        hs1 = (HashSet <string>)attributeSets.GetByIndex(idx);
                        setStack.Push(hs1); // note: pushing a reference, not the actual set
                    }
                    else
                    {
                        throw new FormatException(string.Format("Invalid attribute {0}. Use attributes that exist on a vehicle.",
                                                                searchAlgorithm.Postfix[i]));
                    }
                }
            }
            if (setStack.Count == 1)
            {
                //hs1 = (HashSet<string>)attributeSets.GetByIndex(1);
                hs1    = (HashSet <string>)setStack.Pop();
                result = hs1.ToList().ToArray();
            }
            else
            {
                throw new Exception("Invalid search query provided. Did you add an extra parenthesis?");
            }
        }
        /// <summary>
        /// Search using specified algorithm
        /// </summary>
        /// <param name="searchAlgorithm">Search algorithm instance to use</param>
        /// <returns></returns>
        private string[] search(SearchAlgorithm searchAlgorithm)
        {
            searchFleet(out string[] result, searchAlgorithm);

            if (result.Length == 0)
            {
                throw new Exception("No matches found for this search query. Perhaps make your query less specific.");
            }

            return(result);
        }