/library/Zend/Search/Lucene/Search/BooleanExpressionRecognizer.php

https://bitbucket.org/hamidrezas/melobit · PHP · 278 lines · 100 code · 42 blank · 136 comment · 8 complexity · 09a255fb3441b1271728044206d50024 MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Search_Lucene
  17. * @subpackage Search
  18. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: BooleanExpressionRecognizer.php 24594 2012-01-05 21:27:01Z matthew $
  21. */
  22. /** Zend_Search_Lucene_FSM */
  23. require_once 'Zend/Search/Lucene/FSM.php';
  24. /**
  25. * @category Zend
  26. * @package Zend_Search_Lucene
  27. * @subpackage Search
  28. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. class Zend_Search_Lucene_Search_BooleanExpressionRecognizer extends Zend_Search_Lucene_FSM
  32. {
  33. /** State Machine states */
  34. const ST_START = 0;
  35. const ST_LITERAL = 1;
  36. const ST_NOT_OPERATOR = 2;
  37. const ST_AND_OPERATOR = 3;
  38. const ST_OR_OPERATOR = 4;
  39. /** Input symbols */
  40. const IN_LITERAL = 0;
  41. const IN_NOT_OPERATOR = 1;
  42. const IN_AND_OPERATOR = 2;
  43. const IN_OR_OPERATOR = 3;
  44. /**
  45. * NOT operator signal
  46. *
  47. * @var boolean
  48. */
  49. private $_negativeLiteral = false;
  50. /**
  51. * Current literal
  52. *
  53. * @var mixed
  54. */
  55. private $_literal;
  56. /**
  57. * Set of boolean query conjunctions
  58. *
  59. * Each conjunction is an array of conjunction elements
  60. * Each conjunction element is presented with two-elements array:
  61. * array(<literal>, <is_negative>)
  62. *
  63. * So, it has a structure:
  64. * array( array( array(<literal>, <is_negative>), // first literal of first conjuction
  65. * array(<literal>, <is_negative>), // second literal of first conjuction
  66. * ...
  67. * array(<literal>, <is_negative>)
  68. * ), // end of first conjuction
  69. * array( array(<literal>, <is_negative>), // first literal of second conjuction
  70. * array(<literal>, <is_negative>), // second literal of second conjuction
  71. * ...
  72. * array(<literal>, <is_negative>)
  73. * ), // end of second conjuction
  74. * ...
  75. * ) // end of structure
  76. *
  77. * @var array
  78. */
  79. private $_conjunctions = array();
  80. /**
  81. * Current conjuction
  82. *
  83. * @var array
  84. */
  85. private $_currentConjunction = array();
  86. /**
  87. * Object constructor
  88. */
  89. public function __construct()
  90. {
  91. parent::__construct( array(self::ST_START,
  92. self::ST_LITERAL,
  93. self::ST_NOT_OPERATOR,
  94. self::ST_AND_OPERATOR,
  95. self::ST_OR_OPERATOR),
  96. array(self::IN_LITERAL,
  97. self::IN_NOT_OPERATOR,
  98. self::IN_AND_OPERATOR,
  99. self::IN_OR_OPERATOR));
  100. $emptyOperatorAction = new Zend_Search_Lucene_FSMAction($this, 'emptyOperatorAction');
  101. $emptyNotOperatorAction = new Zend_Search_Lucene_FSMAction($this, 'emptyNotOperatorAction');
  102. $this->addRules(array( array(self::ST_START, self::IN_LITERAL, self::ST_LITERAL),
  103. array(self::ST_START, self::IN_NOT_OPERATOR, self::ST_NOT_OPERATOR),
  104. array(self::ST_LITERAL, self::IN_AND_OPERATOR, self::ST_AND_OPERATOR),
  105. array(self::ST_LITERAL, self::IN_OR_OPERATOR, self::ST_OR_OPERATOR),
  106. array(self::ST_LITERAL, self::IN_LITERAL, self::ST_LITERAL, $emptyOperatorAction),
  107. array(self::ST_LITERAL, self::IN_NOT_OPERATOR, self::ST_NOT_OPERATOR, $emptyNotOperatorAction),
  108. array(self::ST_NOT_OPERATOR, self::IN_LITERAL, self::ST_LITERAL),
  109. array(self::ST_AND_OPERATOR, self::IN_LITERAL, self::ST_LITERAL),
  110. array(self::ST_AND_OPERATOR, self::IN_NOT_OPERATOR, self::ST_NOT_OPERATOR),
  111. array(self::ST_OR_OPERATOR, self::IN_LITERAL, self::ST_LITERAL),
  112. array(self::ST_OR_OPERATOR, self::IN_NOT_OPERATOR, self::ST_NOT_OPERATOR),
  113. ));
  114. $notOperatorAction = new Zend_Search_Lucene_FSMAction($this, 'notOperatorAction');
  115. $orOperatorAction = new Zend_Search_Lucene_FSMAction($this, 'orOperatorAction');
  116. $literalAction = new Zend_Search_Lucene_FSMAction($this, 'literalAction');
  117. $this->addEntryAction(self::ST_NOT_OPERATOR, $notOperatorAction);
  118. $this->addEntryAction(self::ST_OR_OPERATOR, $orOperatorAction);
  119. $this->addEntryAction(self::ST_LITERAL, $literalAction);
  120. }
  121. /**
  122. * Process next operator.
  123. *
  124. * Operators are defined by class constants: IN_AND_OPERATOR, IN_OR_OPERATOR and IN_NOT_OPERATOR
  125. *
  126. * @param integer $operator
  127. */
  128. public function processOperator($operator)
  129. {
  130. $this->process($operator);
  131. }
  132. /**
  133. * Process expression literal.
  134. *
  135. * @param integer $operator
  136. */
  137. public function processLiteral($literal)
  138. {
  139. $this->_literal = $literal;
  140. $this->process(self::IN_LITERAL);
  141. }
  142. /**
  143. * Finish an expression and return result
  144. *
  145. * Result is a set of boolean query conjunctions
  146. *
  147. * Each conjunction is an array of conjunction elements
  148. * Each conjunction element is presented with two-elements array:
  149. * array(<literal>, <is_negative>)
  150. *
  151. * So, it has a structure:
  152. * array( array( array(<literal>, <is_negative>), // first literal of first conjuction
  153. * array(<literal>, <is_negative>), // second literal of first conjuction
  154. * ...
  155. * array(<literal>, <is_negative>)
  156. * ), // end of first conjuction
  157. * array( array(<literal>, <is_negative>), // first literal of second conjuction
  158. * array(<literal>, <is_negative>), // second literal of second conjuction
  159. * ...
  160. * array(<literal>, <is_negative>)
  161. * ), // end of second conjuction
  162. * ...
  163. * ) // end of structure
  164. *
  165. * @return array
  166. * @throws Zend_Search_Lucene_Exception
  167. */
  168. public function finishExpression()
  169. {
  170. if ($this->getState() != self::ST_LITERAL) {
  171. require_once 'Zend/Search/Lucene/Exception.php';
  172. throw new Zend_Search_Lucene_Exception('Literal expected.');
  173. }
  174. $this->_conjunctions[] = $this->_currentConjunction;
  175. return $this->_conjunctions;
  176. }
  177. /*********************************************************************
  178. * Actions implementation
  179. *********************************************************************/
  180. /**
  181. * default (omitted) operator processing
  182. */
  183. public function emptyOperatorAction()
  184. {
  185. /** Zend_Search_Lucene_Search_QueryParser */
  186. require_once 'Zend/Search/Lucene/Search/QueryParser.php';
  187. if (Zend_Search_Lucene_Search_QueryParser::getDefaultOperator() == Zend_Search_Lucene_Search_QueryParser::B_AND) {
  188. // Do nothing
  189. } else {
  190. $this->orOperatorAction();
  191. }
  192. // Process literal
  193. $this->literalAction();
  194. }
  195. /**
  196. * default (omitted) + NOT operator processing
  197. */
  198. public function emptyNotOperatorAction()
  199. {
  200. /** Zend_Search_Lucene_Search_QueryParser */
  201. require_once 'Zend/Search/Lucene/Search/QueryParser.php';
  202. if (Zend_Search_Lucene_Search_QueryParser::getDefaultOperator() == Zend_Search_Lucene_Search_QueryParser::B_AND) {
  203. // Do nothing
  204. } else {
  205. $this->orOperatorAction();
  206. }
  207. // Process NOT operator
  208. $this->notOperatorAction();
  209. }
  210. /**
  211. * NOT operator processing
  212. */
  213. public function notOperatorAction()
  214. {
  215. $this->_negativeLiteral = true;
  216. }
  217. /**
  218. * OR operator processing
  219. * Close current conjunction
  220. */
  221. public function orOperatorAction()
  222. {
  223. $this->_conjunctions[] = $this->_currentConjunction;
  224. $this->_currentConjunction = array();
  225. }
  226. /**
  227. * Literal processing
  228. */
  229. public function literalAction()
  230. {
  231. // Add literal to the current conjunction
  232. $this->_currentConjunction[] = array($this->_literal, !$this->_negativeLiteral);
  233. // Switch off negative signal
  234. $this->_negativeLiteral = false;
  235. }
  236. }