Pelzini

This is the code documentation for the Pelzini project

source of /processor/c_analyser.php

Contains the CAnalyser class
  1. <?php
  2. /*
  3. Copyright 2008 Josh Heidenreich
  4.  
  5. This file is part of Pelzini.
  6.  
  7. Pelzini is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation, either version 3 of the License, or
  10. (at your option) any later version.
  11.  
  12. Pelzini is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Pelzini. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20.  
  21.  
  22. /**
  23.  * Contains the {@link CAnalyser} class
  24.  *
  25.  * @package Parsers
  26.  * @author Josh
  27.  * @since 0.2
  28.  **/
  29.  
  30. /**
  31.  * Analyses the C tokens, and creates a set of ParserItem objects.
  32.  **/
  33. class CAnalyser extends Analyser {
  34. /**
  35.   * Resets any state variables used by this class back to their initial state
  36.   **/
  37. public function resetState()
  38. {
  39. parent::resetState();
  40. }
  41.  
  42.  
  43. /**
  44.   * Should create ParserItem objects that represent the provided tokens
  45.   * and apply those objects to the ParserFile specified.
  46.   * @return boolean True on success, false on failure
  47.   **/
  48. public function process($tokens, $parser_file)
  49. {
  50. $this->setTokens($tokens);
  51.  
  52. // File docblock
  53. $this->setPos(0);
  54. while ($token = $this->getToken()) {
  55. switch ($token->getType()) {
  56. case TOKEN_COMMENT:
  57. case TOKEN_C_PREPROCESSOR:
  58. break;
  59.  
  60. case TOKEN_DOCBLOCK:
  61. $parser_file->applyComment($token->getValue());
  62. break 2;
  63.  
  64. default:
  65. break 2;
  66. }
  67. $this->movePosForward();
  68. }
  69.  
  70. // Functions
  71. $this->setPos(0);
  72. while ($function_open_bracket = $this->findTokenForwards(TOKEN_OPEN_NORMAL_BRACKET)) {
  73. $open_bracket_pos = $this->getTokenPos();
  74. $this->setPos($open_bracket_pos);
  75.  
  76. $parser_function = new ParserFunction();
  77. $parser_file->functions[] = $parser_function;
  78.  
  79. // Find the name
  80. $name = $this->findTokenBackwards(TOKEN_IDENTIFIER, array(TOKEN_CLOSE_CURLY_BRACKET, TOKEN_SEMICOLON));
  81. if ($name == null) return false;
  82. $this->setPos($this->getTokenPos());
  83. $parser_function->name = $name->getValue();
  84.  
  85. // Find the return type
  86. $return_type = '';
  87. $return = $this->findTokenBackwards(array(TOKEN_IDENTIFIER, TOKEN_ASTERIX, TOKEN_CONST), array(TOKEN_CLOSE_CURLY_BRACKET, TOKEN_SEMICOLON));
  88. $this->setPos($this->getTokenPos());
  89. while ($return != null) {
  90. $return_type = $return->getValue() . ' ' . $return_type;
  91.  
  92. $return = $this->findTokenBackwards(array(TOKEN_IDENTIFIER, TOKEN_ASTERIX, TOKEN_CONST), array(TOKEN_CLOSE_CURLY_BRACKET, TOKEN_SEMICOLON));
  93. $this->setPos($this->getTokenPos());
  94. }
  95.  
  96. // Set the function return value to the value found
  97. if ($return_type == '') {
  98. $return_type = 'int';
  99. } else {
  100. $return_type = trim($return_type);
  101. $return_type = str_replace(' *', '*', $return_type);
  102. }
  103. $parser_function->returns[0] = new ParserReturn();
  104. $parser_function->returns[0]->type = $return_type;
  105.  
  106. // Find reserved words before the return type
  107. $reserved = $this->findTokenBackwards(array(TOKEN_RESERVED_WORD), array(TOKEN_CLOSE_CURLY_BRACKET, TOKEN_SEMICOLON));
  108.  
  109. $this->setPos($this->getTokenPos());
  110. while ($reserved != null) {
  111. switch ($reserved->getValue()) {
  112. case 'static':
  113. $parser_function->static = true;
  114. break;
  115. }
  116.  
  117. $reserved = $this->findTokenBackwards(array(TOKEN_RESERVED_WORD), array(TOKEN_CLOSE_CURLY_BRACKET, TOKEN_SEMICOLON));
  118. $this->setPos($this->getTokenPos());
  119. }
  120.  
  121.  
  122.  
  123. // Look for a docblock before the function
  124. $docblock = $this->findTokenBackwards(TOKEN_DOCBLOCK, array(TOKEN_CLOSE_CURLY_BRACKET, TOKEN_SEMICOLON));
  125. if ($docblock != null) {
  126. $parser_function->applyComment($docblock->getValue());
  127. }
  128.  
  129. // Find the end of the arguments by counting regular brackets
  130. $depth = 0;
  131. $find_types = array(
  132. TOKEN_OPEN_NORMAL_BRACKET,
  133. TOKEN_CLOSE_NORMAL_BRACKET,
  134. TOKEN_IDENTIFIER,
  135. TOKEN_COMMA,
  136. TOKEN_ASTERIX,
  137. TOKEN_CONST,
  138. );
  139. $token = $function_open_bracket;
  140. $this->setPos($open_bracket_pos);
  141. $arg_tokens = array();
  142. while ($token) {
  143. switch ($token->getType()) {
  144. case TOKEN_OPEN_NORMAL_BRACKET:
  145. $depth++;
  146. break;
  147.  
  148. case TOKEN_CLOSE_NORMAL_BRACKET:
  149. $depth--;
  150. break;
  151.  
  152. case TOKEN_IDENTIFIER:
  153. case TOKEN_ASTERIX:
  154. case TOKEN_CONST:
  155. $arg_tokens[] = $token->getValue();
  156. break;
  157.  
  158. case TOKEN_COMMA:
  159. $arg = new ParserArgument();
  160. $parser_function->args[] = $arg;
  161. $arg->name = array_pop($arg_tokens);
  162.  
  163. if (count($arg_tokens) == 0) {
  164. $arg->type = 'int';
  165. } else {
  166. $arg->type = trim(implode(' ', $arg_tokens));
  167. $arg->type = str_replace(' *', '*', $arg->type);
  168. }
  169.  
  170. $arg_tokens = array();
  171. break;
  172. }
  173.  
  174. if ($depth == 0) break;
  175.  
  176. $token = $this->findTokenForwards($find_types);
  177. $this->setPos($this->getTokenPos());
  178. }
  179.  
  180. // Adds the last (or only) argument
  181. if (count($arg_tokens) > 0) {
  182. $arg = new ParserArgument();
  183. $parser_function->args[] = $arg;
  184. $arg->name = array_pop($arg_tokens);
  185.  
  186. if (count($arg_tokens) == 0) {
  187. $arg->type = 'int';
  188. } else {
  189. $arg->type = trim(implode(' ', $arg_tokens));
  190. $arg->type = str_replace(' *', '*', $arg->type);
  191. }
  192. }
  193.  
  194. // Find the end of the function by counting curly brackets
  195. $depth = 0;
  196. $token = $this->findTokenForwards(array(TOKEN_OPEN_CURLY_BRACKET, TOKEN_SEMICOLON));
  197. $this->setPos($this->getTokenPos());
  198. while ($token) {
  199. if ($token->getType() == TOKEN_OPEN_CURLY_BRACKET) $depth++;
  200. if ($token->getType() == TOKEN_CLOSE_CURLY_BRACKET) $depth--;
  201.  
  202. if ($depth == 0) break;
  203.  
  204. $token = $this->findTokenForwards(array(TOKEN_OPEN_CURLY_BRACKET, TOKEN_CLOSE_CURLY_BRACKET));
  205. $this->setPos($this->getTokenPos());
  206. }
  207.  
  208. $parser_function->post_load();
  209. }
  210. }
  211.  
  212.  
  213. }
  214.