Мониторинг обменных курсов валют
18c0693f

Управляющий класс UserQuery


Если имеется запрос такого типа:

fiery && ( bird || potato )

то в нашу задачу входит построение эквивалентной иерархии классов:

AndQuery

   NameQuery( "fiery" )

   OrQuery

      NameQuery( "bird" )

      NameQuery( "potato" )

Как лучше всего это сделать? Процедура вычисления ответа на запрос напоминает функционирование конечного автомата. Мы начинаем с пустого состояния и при обработке каждого элемента запроса переходим в новое состояние, пока весь запрос не будет разобран. В основе нашей реализации лежит одна инструкция switch внутри операции, которую мы назвали eval_query(). Слова запроса считываются одно за другим из вектора строк и сравниваются с каждым из возможных значений:

vector<string>::iterator

    it     = _query->begin(),

    end_it = _query->end();

for ( ; it != end_it; ++it )

            switch( evalQueryString( *it ))

            {

               case WORD:

                    evalWord( *it );

                     break;

               case AND:

                     evalAnd();

                     break;

               case OR:

                     evalOr();

                     break;

               case NOT:

                     evalNot();

                     break;

               case LPAREN:

                     ++_paren;

                     ++_lparenOn;

                     break;

               case RPAREN:

                     --_paren;

                     ++_rparenOn;

                     evalRParen();

                     break;

            }

Пять операций eval: evalWord(), evalAnd(), evalOr(), evalNot и evalRParen() – как раз и строят иерархию классов Query. Прежде чем обратиться к деталям их реализации, рассмотрим общую организацию программы.

Нам нужно определить каждую операцию в виде отдельной функции, как это было сделано в главе 6 при построении процедур обработки запроса. Пользовательский запрос и производные от Query классы представляют независимые данные, которыми оперируют эти функции. От такой модели программирования (она называется процедурной) мы предпочли отказаться.


В разделе 6. 14 мы ввели класс TextQuery, где инкапсулировали операции и данные, изучавшиеся в главе 6. Здесь нам потребуется класс UserQuery, решающий аналогичные задачи.

Одним из членов этого класса должен быть вектор строк, содержащий сам запрос пользователя. Другой член – это указатель типа Query* на иерархическое представление запроса, построенное в eval_query(). Еще три члена служат для обработки скобок: