Выбрать главу

}

};

void OrQuery::eval()

{

// вычислить левый и правый операнды

_lop-eval();

_rop-eval();

// подготовиться к объединению двух векторов позиций

vector location, allocator ::const_iterator

riter = _rop-locations()-begin(),

liter = _lop-locations()-begin(),

riter_end = _rop-locations()-end(),

liter_end = _lop-locations()-end();

merge( liter, liter_end, riter, riter_end,

inserter( _loc, _loc.begin() ),

less_than_pair() );

}

А вот трассировка выполнения запроса OrQuery, в которой мы выводим вектор позиций каждого из двух операндов и результат их объединения. (Напомним еще раз, что для пользователя строки нумеруются с 1, а внутри программы - с 0.)

== fiery || untamed

fiery ( 1 ) lines match

display_location vector:

first: 2 second: 2

first: 2 second: 8

untamed ( 1 ) lines match

display_location vector:

first: 3 second: 2

fiery || untamed ( 2 ) lines match

display_location vector:

first: 2 second: 2

first: 2 second: 8

first: 3 second: 2

Requested query: fiery || untamed

( 3 ) like a fiery bird in flight. A beautiful fiery bird, he tells her,

( 4 ) magical but untamed. "Daddy, shush, there is no such thing,"

При обработке запроса AndQuery мы обходим векторы позиций обоих операндов и ищем соседние слова. Каждая найденная пара вставляется в вектор _loc. Основная трудность связана с тем, что эти векторы нужно просматривать синхронно, чтобы можно было установить соседство слов.

void AndQuery::eval()

{

// вычислить левый и правый операнды

_lop-eval();

_rop-eval();

// установить итераторы

vector location, allocator ::const_iterator

riter = _rop-locations()-begin(),

liter = _lop-locations()-begin(),

riter_end = _rop-locations()-end(),

liter_end = _lop-locations()-end();

// продолжать цикл, пока есть что сравнивать

while ( liter != liter_end &&

riter != riter_end )

{

// пока номер строки в левом векторе больше, чем в правом

while ( (*liter).first (*riter).first )

{

++riter;

if ( riter == riter_end ) return;

}

// пока номер строки в левом векторе меньше, чем в правом

while ( (*liter).first (*riter).first )

{

// если соответствие найдено для последнего слова

// в одной строке и первого слова в следующей

// _max_col идентифицирует последнее слово в строке

if ( ((*liter).first == (*riter).first-1 ) &&

((*riter).second == 0 ) &&

((*liter).second == (*_max_col)[ (*liter).first ] ))

{

_loc.push_back( *liter );

_loc.push_back( *riter );

++riter;

if ( riter == riter_end ) return;

}

++liter;

if ( liter == liter_end ) return;

}

// пока оба в одной и той же строке

while ( (*liter).first == (*riter).first )

{

if ( (*liter).second+1 == ((*riter).second) )

{ // соседние слова

_loc.push_back( *liter ); ++liter;

_loc.push_back( *riter ); ++riter;

}

else

if ( (*liter).second = (*riter).second )

++liter;

else ++riter;

if ( liter == liter_end || riter == riter_end )

return;

}

}

}

А так выглядит трассировка выполнения запроса AndQuery, в которой мы выводим векторы позиций обоих операндов и результирующий вектор:

== fiery && bird

fiery ( 1 ) lines match

display_location vector:

first: 2 second: 2

first: 2 second: 8

bird ( 1 ) lines match

display_location vector:

first: 2 second: 3

first: 2 second: 9

fiery && bird ( 1 ) lines match

display_location vector:

first: 2 second: 2

first: 2 second: 3

first: 2 second: 8

first: 2 second: 9

Requested query: fiery && bird

( 3 ) like a fiery bird in flight. A beautiful fiery bird, he tells her,

Приведем трассировку выполнения составного запроса, включающего как И, так и ИЛИ. Показаны векторы позиций каждого операнда, а также результирующий вектор:

== fiery && ( bird || untamed )

fiery ( 1 ) lines match

display_location vector:

first: 2 second: 3

first: 2 second: 8

bird ( 1 ) lines match

display_location vector:

first: 2 second: 3

first: 2 second: 9

untamed ( 1 ) lines match

display_location vector:

first: 3 second: 2

( bird || untamed ) ( 2 ) lines match

display_location vector:

first: 2 second: 3

first: 2 second: 9

first: 3 second: 2

fiery && ( bird || untamed ) ( 1 ) lines match

display_location vector:

first: 2 second: 2

first: 2 second: 3

first: 2 second: 8