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

/Objective-PHP/tokenizer.php

http://github.com/stevegeek/moka
PHP | 284 lines | 207 code | 36 blank | 41 comment | 12 complexity | 370c087457ba515646aed5c35183a186 MD5 | raw file
Possible License(s): LGPL-3.0
  1. <?php
  2. /*
  3. * tokenizer.php
  4. *
  5. * This file is part of Objective-PHP <http://www.atimport.net/>.
  6. *
  7. * Copyright (c) 2009-2011, Stephen Paul Ierodiaconou
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * * Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * * Neither the name of Stephen Ierodiaconou nor the
  18. * names of its contributors may be used to endorse or promote products
  19. * derived from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  23. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  24. * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  25. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  26. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  27. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  28. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. namespace ObjPHP;
  33. // Tokens, includes possible future tokens which are currently not used
  34. const T_OBJPHP_IMPORT = 10000; // @import -- # is a php comment
  35. const T_OBJPHP_IMPLEMENTATION = 10001; // @implementation
  36. const T_OBJPHP_INTERFACE = 10002; // @interface
  37. const T_OBJPHP_END = 10003; // @end
  38. const T_OBJPHP_PUBLIC = 10004; // @public
  39. const T_OBJPHP_PRIVATE = 10005; // @private
  40. const T_OBJPHP_PROTECTED = 10006; // @protected
  41. const T_OBJPHP_TRY = 10007; // @try
  42. const T_OBJPHP_CATCH = 10008; // @catch
  43. const T_OBJPHP_THROW = 10009; // @implementation
  44. const T_OBJPHP_FINALLY = 10010; // @finally
  45. const T_OBJPHP_PROTOCOL = 10011; // @protocol
  46. const T_OBJPHP_SELECTOR = 10012; // @selector
  47. const T_OBJPHP_SYNTHESIZE = 10013; // @synthesize
  48. const T_OBJPHP_ACCESSORS = 10014; // @accessors
  49. const T_OBJPHP_SYNCHRONIZED = 10015; // @synchronized
  50. const T_OBJPHP_DEFS = 10016; // @defs
  51. const T_OBJPHP_ENCODE = 10017; // @encode
  52. const T_OBJPHP_PHP = 10018; // @php
  53. const T_OBJPHP_CMD = 10019; // $_cmd
  54. const T_OBJPHP_SUPER = 10020; // $super
  55. const T_OBJPHP_SELF = 10021; // $self: (Note: self (no $) is reserved)
  56. const T_OBJPHP_NIL = 10022; // nil
  57. const T_OBJPHP_OBJNIL = 10023; // Nil
  58. const T_OBJPHP_THIS = 10024; // $this: (In instance methods this is replaced by $_op_receiver)
  59. const T_OBJPHP_YES = 10025; // YES
  60. const T_OBJPHP_NO = 10026; // NO
  61. // Tokenizer
  62. class Tokenizer
  63. {
  64. protected $tokenChain;
  65. private $tokenIndex;
  66. function __construct($codeObjPHP = null)
  67. {
  68. $this->reset();
  69. if($codeObjPHP)
  70. {
  71. $this->addTokens($codeObjPHP);
  72. }
  73. }
  74. public function reset()
  75. {
  76. $this->tokenIndex = 0;
  77. $this->tokenChain = array();
  78. }
  79. public function addTokens($codeObjPHP)
  80. {
  81. return $this->tokenize($codeObjPHP);
  82. }
  83. public function addTokensAndReset($codeObjPHP)
  84. {
  85. $this->reset();
  86. return $this->addTokens($codeObjPHP);
  87. }
  88. public function peekToken()
  89. {
  90. if ( $this->tokenIndex < count($this->tokenChain) )
  91. return $this->tokenChain[$this->tokenIndex + 1];
  92. else
  93. return false;
  94. }
  95. public function current()
  96. {
  97. return $this->tokenChain[$this->tokenIndex];
  98. }
  99. public function moveNext()
  100. {
  101. $this->tokenIndex++;
  102. if ( $this->tokenIndex < count($this->tokenChain) )
  103. {
  104. return $this->tokenChain[$this->tokenIndex];
  105. }
  106. else
  107. return false;
  108. }
  109. public function previousToken()
  110. {
  111. return $this->previousTokenAt(0);
  112. }
  113. public function previousTokenAt($i)
  114. {
  115. return ($this->tokenIndex - $i - 1 >= 0)?($this->tokenChain[$this->tokenIndex - $i - 1]):(false);
  116. }
  117. private $tokenMap
  118. = array(
  119. "@accessors" => T_OBJPHP_ACCESSORS,
  120. "@catch" => T_OBJPHP_CATCH,
  121. "@end" => T_OBJPHP_END,
  122. "@finally" => T_OBJPHP_FINALLY,
  123. "@implementation" => T_OBJPHP_IMPLEMENTATION,
  124. "@import" => T_OBJPHP_IMPORT,
  125. "@php" => T_OBJPHP_PHP,
  126. "@private" => T_OBJPHP_PRIVATE,
  127. "@protected" => T_OBJPHP_PROTECTED,
  128. "@protocol" => T_OBJPHP_PROTOCOL,
  129. "@public" => T_OBJPHP_PUBLIC,
  130. "@selector" => T_OBJPHP_SELECTOR,
  131. "@throw" => T_OBJPHP_THROW,
  132. "@try" => T_OBJPHP_TRY,
  133. '$self' => T_OBJPHP_SELF,
  134. '$this' => T_OBJPHP_THIS,
  135. "_cmd" => T_OBJPHP_CMD,
  136. "nil" => T_OBJPHP_NIL,
  137. "Nil" => T_OBJPHP_OBJNIL,
  138. "NO" => T_OBJPHP_NO,
  139. "YES" => T_OBJPHP_YES
  140. );
  141. private $tokenNames
  142. = array(
  143. T_OBJPHP_ACCESSORS => "T_OBJPHP_ACCESSORS",
  144. T_OBJPHP_CATCH => "T_OBJPHP_CATCH",
  145. T_OBJPHP_END => "T_OBJPHP_END",
  146. T_OBJPHP_FINALLY => "T_OBJPHP_FINALLY",
  147. T_OBJPHP_IMPLEMENTATION => "T_OBJPHP_IMPLEMENTATION",
  148. T_OBJPHP_IMPORT => "T_OBJPHP_IMPORT",
  149. T_OBJPHP_PHP => "T_OBJPHP_PHP",
  150. T_OBJPHP_PRIVATE => "T_OBJPHP_PRIVATE",
  151. T_OBJPHP_PROTECTED => "T_OBJPHP_PROTECTED",
  152. T_OBJPHP_PROTOCOL => "T_OBJPHP_PROTOCOL",
  153. T_OBJPHP_PUBLIC => "T_OBJPHP_PUBLIC",
  154. T_OBJPHP_SELECTOR => "T_OBJPHP_SELECTOR",
  155. T_OBJPHP_THROW => "T_OBJPHP_THROW",
  156. T_OBJPHP_TRY => "T_OBJPHP_TRY",
  157. T_OBJPHP_SELF => "T_OBJPHP_SELF",
  158. T_OBJPHP_THIS => "T_OBJPHP_THIS",
  159. T_OBJPHP_CMD => "T_OBJPHP_CMD",
  160. T_OBJPHP_NIL => "T_OBJPHP_NIL",
  161. T_OBJPHP_OBJNIL => "T_OBJPHP_OBJNIL",
  162. T_OBJPHP_NO => "T_OBJPHP_NO",
  163. T_OBJPHP_YES => "T_OBJPHP_YES"
  164. );
  165. public function createToken($id, $text, $curline)
  166. {
  167. $name = (is_int($id))?(
  168. (($tname = token_name($id)) != "UNKNOWN")?($tname):(
  169. (($tname = $this->tokenName($id)) !== false)?($tname):($text)
  170. )
  171. ):($text);
  172. return array($id, $name, $text, $curline);
  173. }
  174. public function tokenName($id)
  175. {
  176. return (array_key_exists($id, $this->tokenNames))?($this->tokenNames[$id]):(false);
  177. }
  178. private function tokenize($src)
  179. {
  180. $this->startTimer();
  181. $tokenizedSource = token_get_all($src);
  182. $curline = -1; // keeps the current line counter for the string tokens
  183. $tokenCount = count($tokenizedSource);
  184. for ($i = 0; $i < $tokenCount; $i++)
  185. {
  186. $token = $tokenizedSource[$i];
  187. $prevToken = ($i > 0)?($tokenizedSource[$i-1]):(false);
  188. // Many single character tokens are simply retained as strings
  189. // Name, string and id are all simply the character string
  190. if (is_string($token))
  191. {
  192. $tokenizedSource[$i] = $this->createToken($token, $token, $curline);
  193. continue;
  194. }
  195. // PHP tokens are Array objects which contain the ID, the string of the token
  196. // and the location of the token (source code line).
  197. list($id, $text, $curline) = $token;
  198. // Create key into token map
  199. if($prevToken !== false && $prevToken[0] == '@')
  200. {
  201. $key = '@'.$text;
  202. $rmToken = true;
  203. }
  204. else
  205. $key = $text;
  206. // Check if this is an Objective PHP keyword
  207. if (array_key_exists($key, $this->tokenMap))
  208. {
  209. // Delete preceeding '@' from token stream
  210. if (isset($rmToken))
  211. {
  212. unset($tokenizedSource[$i - 1]);
  213. unset($rmToken);
  214. }
  215. $tokenizedSource[$i] = $this->createToken($this->tokenMap[$key], $text, $curline);
  216. }
  217. else
  218. {
  219. if (isset($rmToken))
  220. unset($rmToken);
  221. $tokenizedSource[$i] = $this->createToken($id, $text, $curline);
  222. }
  223. }
  224. // add new tokens
  225. array_splice($this->tokenChain, $this->tokenIndex, 0, $tokenizedSource);
  226. $this->stopTimer();
  227. return true;
  228. }
  229. // ITimeable
  230. private $startTime = 0.0;
  231. private $endTime = 0.0;
  232. private $totalTime = 0.0;
  233. private function startTimer()
  234. {
  235. $mtime = explode(" ", microtime());
  236. $this->startTime = $mtime[1] + $mtime[0];
  237. }
  238. private function stopTimer()
  239. {
  240. $mtime = explode(" ", microtime());
  241. $this->endTime = $mtime[1] + $mtime[0];
  242. $this->totalTime += ($this->endTime - $this->startTime);
  243. }
  244. public function getTime()
  245. {
  246. return $this->totalTime;
  247. }
  248. }