PageRenderTime 55ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/vendor/Zend/Search/Lucene/FSM.php

https://bitbucket.org/anycode/sfluceneplugin
PHP | 443 lines | 188 code | 48 blank | 207 comment | 32 complexity | a7402883ea92f1bc7b1f3a958f988d9d MD5 | raw file
Possible License(s): BSD-3-Clause
  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. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: FSM.php 20096 2010-01-06 02:05:09Z bkarwin $
  20. */
  21. /** Zend_Search_Lucene_FSMAction */
  22. require_once 'Zend/Search/Lucene/FSMAction.php';
  23. /**
  24. * Abstract Finite State Machine
  25. *
  26. * Take a look on Wikipedia state machine description: http://en.wikipedia.org/wiki/Finite_state_machine
  27. *
  28. * Any type of Transducers (Moore machine or Mealy machine) also may be implemented by using this abstract FSM.
  29. * process() methods invokes a specified actions which may construct FSM output.
  30. * Actions may be also used to signal, that we have reached Accept State
  31. *
  32. * @category Zend
  33. * @package Zend_Search_Lucene
  34. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  35. * @license http://framework.zend.com/license/new-bsd New BSD License
  36. */
  37. abstract class Zend_Search_Lucene_FSM
  38. {
  39. /**
  40. * Machine States alphabet
  41. *
  42. * @var array
  43. */
  44. private $_states = array();
  45. /**
  46. * Current state
  47. *
  48. * @var integer|string
  49. */
  50. private $_currentState = null;
  51. /**
  52. * Input alphabet
  53. *
  54. * @var array
  55. */
  56. private $_inputAphabet = array();
  57. /**
  58. * State transition table
  59. *
  60. * [sourceState][input] => targetState
  61. *
  62. * @var array
  63. */
  64. private $_rules = array();
  65. /**
  66. * List of entry actions
  67. * Each action executes when entering the state
  68. *
  69. * [state] => action
  70. *
  71. * @var array
  72. */
  73. private $_entryActions = array();
  74. /**
  75. * List of exit actions
  76. * Each action executes when exiting the state
  77. *
  78. * [state] => action
  79. *
  80. * @var array
  81. */
  82. private $_exitActions = array();
  83. /**
  84. * List of input actions
  85. * Each action executes when entering the state
  86. *
  87. * [state][input] => action
  88. *
  89. * @var array
  90. */
  91. private $_inputActions = array();
  92. /**
  93. * List of input actions
  94. * Each action executes when entering the state
  95. *
  96. * [state1][state2] => action
  97. *
  98. * @var array
  99. */
  100. private $_transitionActions = array();
  101. /**
  102. * Finite State machine constructor
  103. *
  104. * $states is an array of integers or strings with a list of possible machine states
  105. * constructor treats fist list element as a sturt state (assignes it to $_current state).
  106. * It may be reassigned by setState() call.
  107. * States list may be empty and can be extended later by addState() or addStates() calls.
  108. *
  109. * $inputAphabet is the same as $states, but represents input alphabet
  110. * it also may be extended later by addInputSymbols() or addInputSymbol() calls.
  111. *
  112. * $rules parameter describes FSM transitions and has a structure:
  113. * array( array(sourseState, input, targetState[, inputAction]),
  114. * array(sourseState, input, targetState[, inputAction]),
  115. * array(sourseState, input, targetState[, inputAction]),
  116. * ...
  117. * )
  118. * Rules also can be added later by addRules() and addRule() calls.
  119. *
  120. * FSM actions are very flexible and may be defined by addEntryAction(), addExitAction(),
  121. * addInputAction() and addTransitionAction() calls.
  122. *
  123. * @param array $states
  124. * @param array $inputAphabet
  125. * @param array $rules
  126. */
  127. public function __construct($states = array(), $inputAphabet = array(), $rules = array())
  128. {
  129. $this->addStates($states);
  130. $this->addInputSymbols($inputAphabet);
  131. $this->addRules($rules);
  132. }
  133. /**
  134. * Add states to the state machine
  135. *
  136. * @param array $states
  137. */
  138. public function addStates($states)
  139. {
  140. foreach ($states as $state) {
  141. $this->addState($state);
  142. }
  143. }
  144. /**
  145. * Add state to the state machine
  146. *
  147. * @param integer|string $state
  148. */
  149. public function addState($state)
  150. {
  151. $this->_states[$state] = $state;
  152. if ($this->_currentState === null) {
  153. $this->_currentState = $state;
  154. }
  155. }
  156. /**
  157. * Set FSM state.
  158. * No any action is invoked
  159. *
  160. * @param integer|string $state
  161. * @throws Zend_Search_Exception
  162. */
  163. public function setState($state)
  164. {
  165. if (!isset($this->_states[$state])) {
  166. require_once 'Zend/Search/Exception.php';
  167. throw new Zend_Search_Exception('State \'' . $state . '\' is not on of the possible FSM states.');
  168. }
  169. $this->_currentState = $state;
  170. }
  171. /**
  172. * Get FSM state.
  173. *
  174. * @return integer|string $state|null
  175. */
  176. public function getState()
  177. {
  178. return $this->_currentState;
  179. }
  180. /**
  181. * Add symbols to the input alphabet
  182. *
  183. * @param array $inputAphabet
  184. */
  185. public function addInputSymbols($inputAphabet)
  186. {
  187. foreach ($inputAphabet as $inputSymbol) {
  188. $this->addInputSymbol($inputSymbol);
  189. }
  190. }
  191. /**
  192. * Add symbol to the input alphabet
  193. *
  194. * @param integer|string $inputSymbol
  195. */
  196. public function addInputSymbol($inputSymbol)
  197. {
  198. $this->_inputAphabet[$inputSymbol] = $inputSymbol;
  199. }
  200. /**
  201. * Add transition rules
  202. *
  203. * array structure:
  204. * array( array(sourseState, input, targetState[, inputAction]),
  205. * array(sourseState, input, targetState[, inputAction]),
  206. * array(sourseState, input, targetState[, inputAction]),
  207. * ...
  208. * )
  209. *
  210. * @param array $rules
  211. */
  212. public function addRules($rules)
  213. {
  214. foreach ($rules as $rule) {
  215. $this->addrule($rule[0], $rule[1], $rule[2], isset($rule[3])?$rule[3]:null);
  216. }
  217. }
  218. /**
  219. * Add symbol to the input alphabet
  220. *
  221. * @param integer|string $sourceState
  222. * @param integer|string $input
  223. * @param integer|string $targetState
  224. * @param Zend_Search_Lucene_FSMAction|null $inputAction
  225. * @throws Zend_Search_Exception
  226. */
  227. public function addRule($sourceState, $input, $targetState, $inputAction = null)
  228. {
  229. if (!isset($this->_states[$sourceState])) {
  230. require_once 'Zend/Search/Exception.php';
  231. throw new Zend_Search_Exception('Undefined source state (' . $sourceState . ').');
  232. }
  233. if (!isset($this->_states[$targetState])) {
  234. require_once 'Zend/Search/Exception.php';
  235. throw new Zend_Search_Exception('Undefined target state (' . $targetState . ').');
  236. }
  237. if (!isset($this->_inputAphabet[$input])) {
  238. require_once 'Zend/Search/Exception.php';
  239. throw new Zend_Search_Exception('Undefined input symbol (' . $input . ').');
  240. }
  241. if (!isset($this->_rules[$sourceState])) {
  242. $this->_rules[$sourceState] = array();
  243. }
  244. if (isset($this->_rules[$sourceState][$input])) {
  245. require_once 'Zend/Search/Exception.php';
  246. throw new Zend_Search_Exception('Rule for {state,input} pair (' . $sourceState . ', '. $input . ') is already defined.');
  247. }
  248. $this->_rules[$sourceState][$input] = $targetState;
  249. if ($inputAction !== null) {
  250. $this->addInputAction($sourceState, $input, $inputAction);
  251. }
  252. }
  253. /**
  254. * Add state entry action.
  255. * Several entry actions are allowed.
  256. * Action execution order is defined by addEntryAction() calls
  257. *
  258. * @param integer|string $state
  259. * @param Zend_Search_Lucene_FSMAction $action
  260. */
  261. public function addEntryAction($state, Zend_Search_Lucene_FSMAction $action)
  262. {
  263. if (!isset($this->_states[$state])) {
  264. require_once 'Zend/Search/Exception.php';
  265. throw new Zend_Search_Exception('Undefined state (' . $state. ').');
  266. }
  267. if (!isset($this->_entryActions[$state])) {
  268. $this->_entryActions[$state] = array();
  269. }
  270. $this->_entryActions[$state][] = $action;
  271. }
  272. /**
  273. * Add state exit action.
  274. * Several exit actions are allowed.
  275. * Action execution order is defined by addEntryAction() calls
  276. *
  277. * @param integer|string $state
  278. * @param Zend_Search_Lucene_FSMAction $action
  279. */
  280. public function addExitAction($state, Zend_Search_Lucene_FSMAction $action)
  281. {
  282. if (!isset($this->_states[$state])) {
  283. require_once 'Zend/Search/Exception.php';
  284. throw new Zend_Search_Exception('Undefined state (' . $state. ').');
  285. }
  286. if (!isset($this->_exitActions[$state])) {
  287. $this->_exitActions[$state] = array();
  288. }
  289. $this->_exitActions[$state][] = $action;
  290. }
  291. /**
  292. * Add input action (defined by {state, input} pair).
  293. * Several input actions are allowed.
  294. * Action execution order is defined by addInputAction() calls
  295. *
  296. * @param integer|string $state
  297. * @param integer|string $input
  298. * @param Zend_Search_Lucene_FSMAction $action
  299. */
  300. public function addInputAction($state, $inputSymbol, Zend_Search_Lucene_FSMAction $action)
  301. {
  302. if (!isset($this->_states[$state])) {
  303. require_once 'Zend/Search/Exception.php';
  304. throw new Zend_Search_Exception('Undefined state (' . $state. ').');
  305. }
  306. if (!isset($this->_inputAphabet[$inputSymbol])) {
  307. require_once 'Zend/Search/Exception.php';
  308. throw new Zend_Search_Exception('Undefined input symbol (' . $inputSymbol. ').');
  309. }
  310. if (!isset($this->_inputActions[$state])) {
  311. $this->_inputActions[$state] = array();
  312. }
  313. if (!isset($this->_inputActions[$state][$inputSymbol])) {
  314. $this->_inputActions[$state][$inputSymbol] = array();
  315. }
  316. $this->_inputActions[$state][$inputSymbol][] = $action;
  317. }
  318. /**
  319. * Add transition action (defined by {state, input} pair).
  320. * Several transition actions are allowed.
  321. * Action execution order is defined by addTransitionAction() calls
  322. *
  323. * @param integer|string $sourceState
  324. * @param integer|string $targetState
  325. * @param Zend_Search_Lucene_FSMAction $action
  326. */
  327. public function addTransitionAction($sourceState, $targetState, Zend_Search_Lucene_FSMAction $action)
  328. {
  329. if (!isset($this->_states[$sourceState])) {
  330. require_once 'Zend/Search/Exception.php';
  331. throw new Zend_Search_Exception('Undefined source state (' . $sourceState. ').');
  332. }
  333. if (!isset($this->_states[$targetState])) {
  334. require_once 'Zend/Search/Exception.php';
  335. throw new Zend_Search_Exception('Undefined source state (' . $targetState. ').');
  336. }
  337. if (!isset($this->_transitionActions[$sourceState])) {
  338. $this->_transitionActions[$sourceState] = array();
  339. }
  340. if (!isset($this->_transitionActions[$sourceState][$targetState])) {
  341. $this->_transitionActions[$sourceState][$targetState] = array();
  342. }
  343. $this->_transitionActions[$sourceState][$targetState][] = $action;
  344. }
  345. /**
  346. * Process an input
  347. *
  348. * @param mixed $input
  349. * @throws Zend_Search_Exception
  350. */
  351. public function process($input)
  352. {
  353. if (!isset($this->_rules[$this->_currentState])) {
  354. require_once 'Zend/Search/Exception.php';
  355. throw new Zend_Search_Exception('There is no any rule for current state (' . $this->_currentState . ').');
  356. }
  357. if (!isset($this->_rules[$this->_currentState][$input])) {
  358. require_once 'Zend/Search/Exception.php';
  359. throw new Zend_Search_Exception('There is no any rule for {current state, input} pair (' . $this->_currentState . ', ' . $input . ').');
  360. }
  361. $sourceState = $this->_currentState;
  362. $targetState = $this->_rules[$this->_currentState][$input];
  363. if ($sourceState != $targetState && isset($this->_exitActions[$sourceState])) {
  364. foreach ($this->_exitActions[$sourceState] as $action) {
  365. $action->doAction();
  366. }
  367. }
  368. if (isset($this->_inputActions[$sourceState]) &&
  369. isset($this->_inputActions[$sourceState][$input])) {
  370. foreach ($this->_inputActions[$sourceState][$input] as $action) {
  371. $action->doAction();
  372. }
  373. }
  374. $this->_currentState = $targetState;
  375. if (isset($this->_transitionActions[$sourceState]) &&
  376. isset($this->_transitionActions[$sourceState][$targetState])) {
  377. foreach ($this->_transitionActions[$sourceState][$targetState] as $action) {
  378. $action->doAction();
  379. }
  380. }
  381. if ($sourceState != $targetState && isset($this->_entryActions[$targetState])) {
  382. foreach ($this->_entryActions[$targetState] as $action) {
  383. $action->doAction();
  384. }
  385. }
  386. }
  387. public function reset()
  388. {
  389. if (count($this->_states) == 0) {
  390. require_once 'Zend/Search/Exception.php';
  391. throw new Zend_Search_Exception('There is no any state defined for FSM.');
  392. }
  393. $this->_currentState = $this->_states[0];
  394. }
  395. }