PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/symfony/2.0.0alpha1/src/vendor/symfony/tests/lib/vendor/lime/lexer/LimeLexer.php

http://github.com/pmjones/php-framework-benchmarks
PHP | 402 lines | 267 code | 29 blank | 106 comment | 16 complexity | 6fef31a9774a8c3ad0bafa465c96584e MD5 | raw file
Possible License(s): LGPL-3.0, Apache-2.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1
  1. <?php
  2. /*
  3. * This file is part of the Lime test framework.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. * (c) Bernhard Schussek <bernhard.schussek@symfony-project.com>
  7. *
  8. * This source file is subject to the MIT license that is bundled
  9. * with this source code in the file LICENSE.
  10. */
  11. /**
  12. * Analyzes PHP scripts syntactically.
  13. *
  14. * You can extend this class if you want to write your own lexer that parses
  15. * a PHP file for specific information.
  16. *
  17. * To create your own lexer, implement the methods process() and getResult()
  18. * in your class. process() is called for every token in the file. You can use
  19. * the methods of this class to retrieve more information about the context of
  20. * the token, f.i. whether the token is inside a class or function etc.
  21. *
  22. * The method getResult() must return the value that should be returned by
  23. * parse().
  24. *
  25. * A lexer is stateless. This means that you can analyze any number of PHP
  26. * scripts with the same lexer instance.
  27. *
  28. * @package Lime
  29. * @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
  30. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  31. * @version SVN: $Id: LimeLexer.php 25934 2009-12-27 20:44:07Z bschussek $
  32. */
  33. abstract class LimeLexer
  34. {
  35. private
  36. $continue,
  37. $currentClass,
  38. $inClassDeclaration,
  39. $currentFunction,
  40. $inFunctionDeclaration,
  41. $inAssignment,
  42. $endOfCurrentExpr,
  43. $currentLine;
  44. /**
  45. * Analyzes the given file or PHP code.
  46. *
  47. * @param string $content A file path or a string with PHP code.
  48. *
  49. * @return mixed The result from getResult()
  50. */
  51. public function parse($content)
  52. {
  53. if (is_readable($content))
  54. {
  55. $content = file_get_contents($content);
  56. }
  57. $this->continue = true;
  58. $this->currentClass = array();
  59. $this->inClassDeclaration = false;
  60. $this->currentFunction = array();
  61. $this->inFunctionDeclaration = false;
  62. $this->inAssignment = false;
  63. $this->endOfCurrentExpr = true;
  64. $this->currentLine = 1;
  65. $tokens = token_get_all($content);
  66. $openBraces = 0;
  67. foreach ($tokens as $token)
  68. {
  69. if (is_string($token))
  70. {
  71. switch ($token)
  72. {
  73. case '{':
  74. ++$openBraces;
  75. $this->inClassDeclaration = false;
  76. $this->inFunctionDeclaration = false;
  77. break;
  78. case ';':
  79. // abstract functions
  80. if ($this->inFunctionDeclaration)
  81. {
  82. $this->inFunctionDeclaration = false;
  83. unset($this->currentFunction[$openBraces]);
  84. }
  85. $this->endOfCurrentExpr = true;
  86. break;
  87. case '}':
  88. $this->endOfCurrentExpr = true;
  89. break;
  90. case '=':
  91. $this->endOfCurrentExpr = false;
  92. $this->inAssignment = true;
  93. break;
  94. }
  95. if ($this->endOfCurrentExpr)
  96. {
  97. $this->inAssignment = false;
  98. }
  99. $this->beforeProcess($token, null);
  100. $this->process($token, null);
  101. $this->afterProcess($token, null);
  102. switch ($token)
  103. {
  104. case '}':
  105. --$openBraces;
  106. if (array_key_exists($openBraces, $this->currentClass))
  107. {
  108. unset($this->currentClass[$openBraces]);
  109. }
  110. if (array_key_exists($openBraces, $this->currentFunction))
  111. {
  112. unset($this->currentFunction[$openBraces]);
  113. }
  114. break;
  115. }
  116. }
  117. else
  118. {
  119. list($id, $text) = $token;
  120. switch ($id)
  121. {
  122. case T_CURLY_OPEN:
  123. case T_DOLLAR_OPEN_CURLY_BRACES:
  124. ++$openBraces;
  125. break;
  126. case T_OPEN_TAG:
  127. case T_CLOSE_TAG:
  128. $this->endOfCurrentExpr = true;
  129. $this->currentLine += count(explode("\n", $text)) - 1;
  130. break;
  131. case T_WHITESPACE:
  132. case T_START_HEREDOC:
  133. case T_CONSTANT_ENCAPSED_STRING:
  134. case T_ENCAPSED_AND_WHITESPACE:
  135. case T_COMMENT:
  136. case T_DOC_COMMENT:
  137. $this->currentLine += count(explode("\n", $text)) - 1;
  138. break;
  139. case T_ABSTRACT:
  140. if ($this->inClass())
  141. {
  142. $this->currentFunction[$openBraces] = null;
  143. $this->inFunctionDeclaration = true;
  144. }
  145. else
  146. {
  147. $this->currentClass[$openBraces] = null;
  148. $this->inClassDeclaration = true;
  149. }
  150. break;
  151. case T_INTERFACE:
  152. case T_CLASS:
  153. $this->currentClass[$openBraces] = null;
  154. $this->inClassDeclaration = true;
  155. break;
  156. case T_FUNCTION:
  157. $this->currentFunction[$openBraces] = null;
  158. $this->inFunctionDeclaration = true;
  159. break;
  160. case T_STRING:
  161. if (array_key_exists($openBraces, $this->currentClass) && is_null($this->currentClass[$openBraces]))
  162. {
  163. $this->currentClass[$openBraces] = $text;
  164. }
  165. if (array_key_exists($openBraces, $this->currentFunction) && is_null($this->currentFunction[$openBraces]))
  166. {
  167. $this->currentFunction[$openBraces] = $text;
  168. }
  169. break;
  170. case T_AND_EQUAL:
  171. case T_BREAK:
  172. case T_CASE:
  173. case T_CATCH:
  174. case T_CLONE:
  175. case T_CONCAT_EQUAL:
  176. case T_CONTINUE:
  177. case T_DEC:
  178. case T_DECLARE:
  179. case T_DEFAULT:
  180. case T_DIV_EQUAL:
  181. case T_DO:
  182. case T_ECHO:
  183. case T_ELSEIF:
  184. case T_EMPTY:
  185. case T_ENDDECLARE:
  186. case T_ENDFOR:
  187. case T_ENDFOREACH:
  188. case T_ENDIF:
  189. case T_ENDSWITCH:
  190. case T_ENDWHILE:
  191. case T_END_HEREDOC:
  192. case T_EVAL:
  193. case T_EXIT:
  194. case T_FOR:
  195. case T_FOREACH:
  196. case T_GLOBAL:
  197. case T_IF:
  198. case T_INC:
  199. case T_INCLUDE:
  200. case T_INCLUDE_ONCE:
  201. case T_INSTANCEOF:
  202. case T_ISSET:
  203. case T_IS_EQUAL:
  204. case T_IS_GREATER_OR_EQUAL:
  205. case T_IS_IDENTICAL:
  206. case T_IS_NOT_EQUAL:
  207. case T_IS_NOT_IDENTICAL:
  208. case T_IS_SMALLER_OR_EQUAL:
  209. case T_LIST:
  210. case T_LOGICAL_AND:
  211. case T_LOGICAL_OR:
  212. case T_LOGICAL_XOR:
  213. case T_MINUS_EQUAL:
  214. case T_MOD_EQUAL:
  215. case T_MUL_EQUAL:
  216. case T_NEW:
  217. case T_OBJECT_OPERATOR:
  218. case T_OR_EQUAL:
  219. case T_PLUS_EQUAL:
  220. case T_PRINT:
  221. case T_REQUIRE:
  222. case T_REQUIRE_ONCE:
  223. case T_RETURN:
  224. case T_SL:
  225. case T_SL_EQUAL:
  226. case T_SR:
  227. case T_SR_EQUAL:
  228. case T_SWITCH:
  229. case T_THROW:
  230. case T_TRY:
  231. case T_UNSET:
  232. case T_UNSET_CAST:
  233. case T_USE:
  234. case T_WHILE:
  235. case T_XOR_EQUAL:
  236. $this->endOfCurrentExpr = false;
  237. break;
  238. }
  239. if ($this->endOfCurrentExpr)
  240. {
  241. $this->inAssignment = false;
  242. }
  243. $this->beforeProcess($text, $id);
  244. $this->process($text, $id);
  245. $this->afterProcess($text, $id);
  246. }
  247. if (!$this->continue)
  248. {
  249. break;
  250. }
  251. }
  252. return $this->getResult();
  253. }
  254. protected function beforeProcess($text, $id)
  255. {
  256. }
  257. protected function afterProcess($text, $id)
  258. {
  259. }
  260. /**
  261. * Processes a token in the PHP code.
  262. *
  263. * @param string $text The string representation of the token
  264. * @param integer $id The token identifier (f.i. T_VARIABLE) or NULL, if
  265. * the token does not have an identifier.
  266. */
  267. abstract protected function process($text, $id);
  268. /**
  269. * Returns the result of the lexing process.
  270. *
  271. * @return mixed
  272. */
  273. abstract protected function getResult();
  274. /**
  275. * Returns the line number at the current position of the lexer.
  276. *
  277. * @return integer
  278. */
  279. protected function getCurrentLine()
  280. {
  281. return $this->currentLine;
  282. }
  283. /**
  284. * Returns the class name at the current position of the lexer.
  285. *
  286. * @return string Returns NULL if the current position is not inside a class.
  287. */
  288. protected function getCurrentClass()
  289. {
  290. return $this->inClass() ? end($this->currentClass) : null;
  291. }
  292. /**
  293. * Returns the function name at the current position of the lexer.
  294. *
  295. * @return string Returns NULL if the current position is not inside a function.
  296. */
  297. protected function getCurrentFunction()
  298. {
  299. return $this->inFunction() ? end($this->currentFunction) : null;
  300. }
  301. /**
  302. * Returns whether the current position of the lexer is inside a class.
  303. *
  304. * @return boolean
  305. */
  306. protected function inClass()
  307. {
  308. return count($this->currentClass) > 0;
  309. }
  310. /**
  311. * Returns whether the current position of the lexer is inside a class
  312. * declaration (f.i. "abstract class ClassName extends BaseClass").
  313. *
  314. * @return boolean
  315. */
  316. protected function inClassDeclaration()
  317. {
  318. return $this->inClassDeclaration;
  319. }
  320. /**
  321. * Returns whether the current position of the lexer is inside a function.
  322. *
  323. * @return boolean
  324. */
  325. protected function inFunction()
  326. {
  327. return count($this->currentFunction) > 0;
  328. }
  329. /**
  330. * Returns whether the current position of the lexer is inside a function
  331. * declaration (f.i. "protected function myFunctionName()").
  332. *
  333. * @return boolean
  334. */
  335. protected function inFunctionDeclaration()
  336. {
  337. return $this->inFunctionDeclaration;
  338. }
  339. /**
  340. * Returns how many functions are currently nested inside each other.
  341. *
  342. * @return integer
  343. */
  344. protected function getFunctionNestingLevel()
  345. {
  346. return count($this->currentFunction);
  347. }
  348. /**
  349. * Returns whether the current token marks the end of the last expression.
  350. *
  351. * @return boolean
  352. */
  353. protected function isEndOfCurrentExpr()
  354. {
  355. return $this->endOfCurrentExpr;
  356. }
  357. /**
  358. * Returns whether the current token is inside an assignment operation.
  359. *
  360. * @return boolean
  361. */
  362. protected function inAssignment()
  363. {
  364. return $this->inAssignment;
  365. }
  366. /**
  367. * Tells the lexer to stop lexing.
  368. */
  369. protected function stop()
  370. {
  371. $this->continue = false;
  372. }
  373. }