/Classes/Parser/AbstractStructureParser.php

https://github.com/RichardDownes/PHPCodeParser · PHP · 608 lines · 236 code · 132 blank · 240 comment · 36 complexity · be0e603de3b9ecc89a03b61c2f9c60f8 MD5 · raw file

  1. <?php
  2. namespace Parser;
  3. /*
  4. * Copyright 2011 Richard Downes
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. use Meta\AbstractPHPStructure;
  19. use Meta\DocBlock;
  20. /**
  21. * Contains Parser\AbstractStructureParser
  22. *
  23. * @author Richard Downes <richard@sculpt.ie>
  24. * @copyright Copyright (c) 2011, Richard Downes
  25. * @package Parser
  26. */
  27. /**
  28. * Responsible for parsing a php class
  29. *
  30. * @author Richard Downes <richard@sculpt.ie>
  31. */
  32. abstract class AbstractStructureParser extends AbstractParser
  33. {
  34. /**
  35. * Responsible for storing the information about the structure being parsed
  36. *
  37. * @var \Meta\AbstractPHPStructure $structure Stores meta information about the structure
  38. */
  39. protected $structure;
  40. /**
  41. * The currently detected access level.
  42. * This will be applied to the next function or variable discovered and then reset to public
  43. *
  44. * @var string $accessLevel The currently access level
  45. */
  46. protected $accessLevel;
  47. /**
  48. * Flag indicating that the current token belongs to a static member
  49. *
  50. * @var bool $staticMember If true then the current token belongs to a static member
  51. */
  52. protected $staticMember;
  53. /**
  54. * Flag indicating that the current token belongs to a abstract member
  55. *
  56. * @var bool $abstractMember If true then the current token belongs to a abstract member
  57. */
  58. protected $abstractMember;
  59. /**
  60. * An associative with the alias/class name as key and fully qualified class name as value
  61. *
  62. * @var array $usedClassNames A list of class names taken from a use statement
  63. */
  64. protected $usedClassNames;
  65. /**
  66. * The name of the current constant being parsed, if any
  67. *
  68. * @var string $currentConstName The name of the current constant being parsed
  69. */
  70. protected $currentConstName;
  71. /**
  72. * The value of the current constant being parsed, if any
  73. *
  74. * @var string $currentConstValue The value of the current constant being parsed
  75. */
  76. protected $currentConstValue;
  77. /**
  78. * Constructs a new instance of ClassParser
  79. *
  80. */
  81. public function __construct()
  82. {
  83. $this->structure = $this->createPHPStructure();
  84. $this->abstractMember = false;
  85. $this->staticMember = false;
  86. $this->accessLevel = "public";
  87. $this->currentConstName = null;
  88. $this->currentConstValue = null;
  89. // this parser is never passed the token that caused it to be invoked
  90. // so we never know if this is a T_INTERFACE or T_CLASS token
  91. $this->currentTokenType = $this->defaultTokenType();
  92. $this->usedClassNames = array();
  93. $this->docBlock = new DocBlock();
  94. }
  95. /**
  96. * Sets the list of used class names
  97. *
  98. * @param array $usedClassNames A list of used class names
  99. * @return void
  100. */
  101. public function setUsedClassNames($usedClassNames)
  102. {
  103. $this->usedClassNames = $usedClassNames;
  104. }
  105. /**
  106. * Factory method to create the PHP structure
  107. *
  108. * @return \Meta\AbstractPHPStructure
  109. */
  110. protected abstract function createPHPStructure();
  111. /**
  112. * Factory method to create the default token type
  113. *
  114. * @return int
  115. */
  116. protected abstract function defaultTokenType();
  117. /**
  118. * Responsible for handling any text tokens
  119. *
  120. * @param string $text The text token
  121. * @return void
  122. */
  123. protected function textHandler($text)
  124. {
  125. if ($this->currentTokenType == $this->defaultTokenType())
  126. {
  127. $this->parseStructureName($text);
  128. }
  129. else if ($text != "}")
  130. {
  131. $this->parseStructureInheritance($text);
  132. }
  133. else
  134. {
  135. $this->stopParsing();
  136. }
  137. }
  138. /**
  139. * Responsible for handling any T_EXTENDS tokens
  140. *
  141. * @param int $id The id of the token
  142. * @param string $text The text of the token
  143. * @return void
  144. */
  145. protected function extendsHandler($id, $text)
  146. {
  147. $text = null; // not needed
  148. $this->currentTokenType = $id;
  149. }
  150. /**
  151. * Responsible for handling any T_IMPLEMENTS tokens
  152. *
  153. * @param int $id The id of the token
  154. * @param string $text The text of the token
  155. * @return void
  156. */
  157. protected function implementsHandler($id, $text)
  158. {
  159. $text = null; // not needed
  160. $this->currentTokenType = $id;
  161. }
  162. /**
  163. * Responsible for handling any T_STATIC tokens
  164. *
  165. * @param int $id The id of the token
  166. * @param string $text The text of the token
  167. * @return void
  168. */
  169. protected function staticHandler($id, $text)
  170. {
  171. $id = null;
  172. $text = null; // not needed
  173. $this->staticMember = true;
  174. }
  175. /**
  176. * Responsible for handling any T_ABSTRACT tokens
  177. *
  178. * @param int $id The id of the token
  179. * @param string $text The text of the token
  180. * @return void
  181. */
  182. protected function abstractHandler($id, $text)
  183. {
  184. $text = null;
  185. $id = null;
  186. $this->abstractMember = true;
  187. }
  188. /**
  189. * Responsible for handling and T_PROTECTED tokens
  190. *
  191. * @param int $id The id of the token
  192. * @param string $text The text of the token
  193. * @return void
  194. */
  195. protected function protectedHandler($id, $text)
  196. {
  197. $text = null; // not needed
  198. $this->currentTokenType = $id;
  199. $this->accessLevel = "protected";
  200. }
  201. /**
  202. * Responsible for handling and T_PUBLIC tokens
  203. *
  204. * @param int $id The id of the token
  205. * @param string $text The text of the token
  206. * @return void
  207. */
  208. protected function publicHandler($id, $text)
  209. {
  210. $text = null; // not needed
  211. $this->currentTokenType = $id;
  212. $this->accessLevel = "public";
  213. }
  214. /**
  215. * Responsible for handling and T_PRIVATE tokens
  216. *
  217. * @param int $id The id of the token
  218. * @param string $text The text of the token
  219. * @return void
  220. */
  221. protected function privateHandler($id, $text)
  222. {
  223. $text = null; // not needed
  224. $this->currentTokenType = $id;
  225. $this->accessLevel = "private";
  226. }
  227. /**
  228. * Responsible for handing and T_FUNCTION tokens
  229. *
  230. * @param int $id The id of the token
  231. * @param string $text The text of the token
  232. * @return void
  233. */
  234. protected function functionHandler($id, $text)
  235. {
  236. $id = null;
  237. $text = null;
  238. $parser = $this->createFunctionParser();
  239. // set the default values for the parsers function object
  240. $parser->phpFunction()->setAccessLevel($this->accessLevel);
  241. $parser->phpFunction()->setStatic($this->staticMember);
  242. $parser->phpFunction()->setAbstract($this->abstractMember);
  243. $parser->phpFunction()->setDocBlock($this->docBlock);
  244. // parse the function
  245. $parser->parse($this->tokens);
  246. $this->structure->addMethod($parser->phpFunction());
  247. // reset
  248. $this->reset();
  249. }
  250. /**
  251. * Responsible for creating a function parser
  252. *
  253. * @return FunctionParser
  254. */
  255. protected abstract function createFunctionParser();
  256. /**
  257. * Responsible for creating a variable parser
  258. *
  259. * @return VariableParser
  260. */
  261. protected abstract function createVariableParser();
  262. /**
  263. * Responsible for handing and T_VARIABLE tokens
  264. *
  265. */
  266. protected function variableHandler($id, $text)
  267. {
  268. $parser = $this->createVariableParser();
  269. $parser->variable()->setName(str_replace("\$", "", $text));
  270. $parser->variable()->setStatic($this->staticMember);
  271. $parser->variable()->setDocBlock($this->docBlock);
  272. $parser->variable()->setAccessLevel($this->accessLevel);
  273. $parser->parse($this->tokens);
  274. $this->structure->addVariable($parser->variable());
  275. $this->currentTokenType = $id;
  276. $this->reset();
  277. }
  278. /**
  279. * Responsible for handling and T_CONST tokens
  280. *
  281. */
  282. protected function constHandler($id, $text)
  283. {
  284. $this->currentTokenType = $id;
  285. $text = null;
  286. }
  287. /**
  288. * Responsible for handling any T_CONSTANT_ENCAPSED_STRING tokens
  289. *
  290. */
  291. protected function constantEncapsedStringHandler($id, $text)
  292. {
  293. $id = null;
  294. if ($this->currentTokenType == T_CONST)
  295. {
  296. $this->currentConstValue = $text;
  297. }
  298. }
  299. /**
  300. * Responsible for handling any T_LNUMBER tokens (integers)
  301. *
  302. */
  303. protected function lnumberHandler($id, $text)
  304. {
  305. $id = null;
  306. if ($this->currentTokenType == T_CONST)
  307. {
  308. $this->currentConstValue = $text;
  309. }
  310. }
  311. /**
  312. * Responsible for handling any T_DNUMBER tokens (decimals)
  313. *
  314. */
  315. protected function dnumberHandler($id, $text)
  316. {
  317. $id = null;
  318. if ($this->currentTokenType == T_CONST)
  319. {
  320. $this->currentConstValue = $text;
  321. }
  322. }
  323. /**
  324. * Gets a reference to the PHP class
  325. *
  326. * @return \Meta\AbstractPHPStructure
  327. */
  328. public function &structure()
  329. {
  330. return $this->structure;
  331. }
  332. /**
  333. * Sets the PHP structure
  334. *
  335. * @param \Meta\AbstractPHPStructure $structure The new structure
  336. * @return void
  337. */
  338. public function setStructure(AbstractPHPStructure $structure)
  339. {
  340. $this->structure = $structure;
  341. }
  342. /**
  343. * Gets the PHP structure
  344. *
  345. * @return \Meta\AbstractPHPStructure
  346. */
  347. public function getStructure()
  348. {
  349. return $this->structure;
  350. }
  351. /**
  352. * Responsible for parsing the structures name
  353. *
  354. * @param string $text The text to parse the name frmo
  355. * @return void
  356. */
  357. protected function parseStructureName($text)
  358. {
  359. if ($text == "{")
  360. {
  361. $this->currentTokenType = -1;
  362. }
  363. else
  364. {
  365. $this->structure->setName($text);
  366. }
  367. }
  368. /**
  369. * Responsible for parsing the inheritance of a structure
  370. *
  371. * @param string $text The text to parse
  372. * @return void
  373. */
  374. protected function parseStructureInheritance($text)
  375. {
  376. if ($this->currentTokenType == T_EXTENDS)
  377. {
  378. $this->parseExtends($text);
  379. }
  380. else if ($this->currentTokenType == T_IMPLEMENTS)
  381. {
  382. $this->parseInterfaces($text);
  383. }
  384. else if ($this->currentTokenType == T_CONST)
  385. {
  386. $this->parseConstant($text);
  387. }
  388. }
  389. /**
  390. * Responsible for parsing the parent of a structure
  391. *
  392. * @var string $text The text to parse
  393. * @return void
  394. */
  395. protected function parseExtends($text)
  396. {
  397. if ($text != "{")
  398. {
  399. $parent = $this->resolveClassName($text);
  400. $this->structure->setParent($parent);
  401. }
  402. }
  403. /**
  404. * Parses a token from the class interface list
  405. *
  406. * @param string $text The text to parse
  407. * @return void
  408. */
  409. protected function parseInterfaces($text)
  410. {
  411. if ($text == "{")
  412. {
  413. $this->parsingInterfaces = false;
  414. }
  415. else if ($text != ",")
  416. {
  417. $interfaceName = $this->resolveClassName($text);
  418. $this->structure->addInterface($interfaceName);
  419. }
  420. }
  421. /**
  422. * Responsible for resetting the stored member properties
  423. *
  424. * @return void
  425. */
  426. protected function reset()
  427. {
  428. $this->docBlock = new DocBlock;
  429. $this->abstractMember = false;
  430. $this->accessLevel = "";
  431. $this->staticMember = false;
  432. }
  433. /**
  434. * Given a class name it will resolve it to a fully qualified on
  435. *
  436. * @param string $className The name of the class
  437. * @return string
  438. */
  439. protected function resolveClassName($className)
  440. {
  441. // if the class name exists in the list of used classes then
  442. // its from a separate namespace, otherwise prefix it with the
  443. // current namespace
  444. if (array_key_exists($className, $this->usedClassNames))
  445. {
  446. $className = $this->usedClassNames[$className];
  447. }
  448. else if (substr($className, 0, 1) != "\\")
  449. {
  450. $className = "{$this->structure()->getNamespace()}\\{$className}";
  451. }
  452. return $className;
  453. }
  454. /**
  455. * Responsible for parsing a class constant
  456. *
  457. * @param string $text The text to parse
  458. * @return void
  459. */
  460. protected function parseConstant($text)
  461. {
  462. if ($text == ";")
  463. {
  464. $this->currentConstName = null;
  465. $this->currentConstValue = null;
  466. $this->currentTokenType = -1;
  467. }
  468. else
  469. {
  470. if ($text != "=")
  471. {
  472. $this->currentConstName = $text;
  473. }
  474. }
  475. }
  476. }