}
};
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