phplibrary/src/Search/search.php

96 lines
2.8 KiB
PHP

<?php
require_once __DIR__ '/../functions.php';
/**
* Поиск в индексе
*/
class Search
{
private $lexer;
private $index;
function __construct ($index)
{
$this->lexer = new Lexer();
$this->index = $index;
$this->op = array ($this, 'Op');
$this->binary = array ($this, 'binaryOp');
$this->union = array ($this, 'union');
$this->intersection = lcurry($this->op, 'array_uintersect', $this->union);
$this->notQuery = lcurry ($this->binary, Lexer::TOKEN_NOT,
lcurry($this->op, 'array_udiff', 'array_udiff'), array ($this, 'easyQuery'));
$this->orQuery = lcurry ($this->binary, Lexer::TOKEN_OR,
lcurry($this->op, $this->union, $this->union), $this->notQuery);
$this->andQuery = lcurry ($this->binary, Lexer::TOKEN_AND, $this->intersection, $this->orQuery);
}
function union ($a, $b, $callback)
{
return array_merge($a, $b);
}
function Eq ($a, $b)
{
return $a == $b;
}
function Op ($files, $words, $a, $b) {
return array (
'words' => call_user_func ($words, $a['words'], $b['words'], array ($this, 'eq')),
'files' => call_user_func ($files, $a['files'], $b['files'], array ($this, 'eq'))
);
}
public function getQuery ($source)
{
$this->lexer->setSource ($source);
$this->lexer->nextToken();
return $this->topQuery();
}
function topQuery ()
{
$result = call_user_func ($this->andQuery);
while ($this->lexer->token[0] == Lexer::TOKEN_LPAREN) {
$result = call_user_func ($this->intersection, $result, call_user_func ($this->andQuery));
}
return $result;
}
function easyQuery ()
{
$result = null;
if ($this->lexer->token[0] == Lexer::TOKEN_LPAREN) {
$this->lexer->nextToken ();
$result = $this->topQuery ();
if ($this->lexer->token[0] == Lexer::TOKEN_RPAREN) {
$this->lexer->nextToken ();
}
return $result;
} else {
$result = call_user_func ($this->index, $this->lexer->token[1]);
$this->lexer->nextToken ();
return $result;
}
}
/**
* @param int $type Тип лексемы
* @param function $op Функция при совпадении типа лексемы при запросе
* @param function $next Следующий обработчик запроса
*/
function binaryOp ($type, $op, $next)
{
$result = call_user_func($next);
while ($this->lexer->token[0] == $type) {
$this->lexer->nextToken();
$result = call_user_func($op, $result, call_user_func ($next));
}
return $result;
}
}