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