5cec4c1b9c251d253af062ee16df86532e072cc1
[atutor.git] / mods / phpdoc2 / PhpDocumentor / phpDocumentor / phpDocumentorTWordParser.inc
1 <?php\r
2 /**\r
3  * tokenizer extension-based lexer for PHP code\r
4  * \r
5  * phpDocumentor :: automatic documentation generator\r
6  * \r
7  * PHP versions 4 and 5\r
8  *\r
9  * Copyright (c) 2002-2006 Gregory Beaver\r
10  * \r
11  * LICENSE:\r
12  * \r
13  * This library is free software; you can redistribute it\r
14  * and/or modify it under the terms of the GNU Lesser General\r
15  * Public License as published by the Free Software Foundation;\r
16  * either version 2.1 of the License, or (at your option) any\r
17  * later version.\r
18  * \r
19  * This library is distributed in the hope that it will be useful,\r
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
22  * Lesser General Public License for more details.\r
23  * \r
24  * You should have received a copy of the GNU Lesser General Public\r
25  * License along with this library; if not, write to the Free Software\r
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
27  *\r
28  * @category   ToolsAndUtilities\r
29  * @package    phpDocumentor\r
30  * @subpackage Parsers\r
31  * @author     Gregory Beaver <cellog@php.net>\r
32  * @copyright  2002-2007 Gregory Beaver\r
33  * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL\r
34  * @version    CVS: $Id: phpDocumentorTWordParser.inc,v 1.8 2007/11/16 11:53:06 ashnazg Exp $\r
35  * @link       http://www.phpdoc.org\r
36  * @link       http://pear.php.net/PhpDocumentor\r
37  * @since      1.2\r
38  * @todo       CS cleanup - change package to PhpDocumentor\r
39  * @todo       CS cleanup - PHPCS needs to ignore CVS Id length\r
40  */\r
41 \r
42 /**\r
43  * Like WordParser, but expects an array of tokens from the tokenizer \r
44  * instead of a string.\r
45  *\r
46  * @category   ToolsAndUtilities\r
47  * @package    phpDocumentor\r
48  * @subpackage WordParsers\r
49  * @author     Gregory Beaver <cellog@php.net>\r
50  * @copyright  2002-2007 Gregory Beaver\r
51  * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL\r
52  * @version    Release: 1.4.1\r
53  * @link       http://www.phpdoc.org\r
54  * @link       http://pear.php.net/PhpDocumentor\r
55  * @since      1.2\r
56  * @todo       CS cleanup - change package to PhpDocumentor\r
57  * @todo       CS cleanup - change classname to PhpDocumentor_*\r
58  */\r
59 class phpDocumentorTWordParser extends WordParser\r
60 {\r
61     /**#@+\r
62      * @access private\r
63      */\r
64     /**\r
65      * tokenized array from {@link token_get_all()}\r
66      * @var array\r
67      */\r
68     var $_all;\r
69     /**\r
70      * List of tokens that can contain a newline\r
71      * @var array\r
72      */\r
73     var $_nl_check = array(\r
74         T_WHITESPACE,\r
75         T_ENCAPSED_AND_WHITESPACE,\r
76         T_CONSTANT_ENCAPSED_STRING,\r
77         T_COMMENT,\r
78         T_DOC_COMMENT,\r
79         T_OPEN_TAG,\r
80         T_CLOSE_TAG,\r
81         T_INLINE_HTML);\r
82     /**\r
83      * @var array\r
84      */\r
85     var $_global_search;\r
86     /**\r
87      * current source line number (relative)\r
88      * @var integer\r
89      */\r
90     var $_sourceline;\r
91     /**\r
92      * Source of the entire file, parsed into arrays of tokens on each line\r
93      * @var array\r
94      */\r
95     var $_file_source = array();\r
96     /**\r
97      * Line number the last comment was on\r
98      * @var integer\r
99      */\r
100     var $_docblock_linenum;\r
101     /**#@-*/\r
102     \r
103     /**\r
104      * Uses {@link token_get_all()} to tokenize the source code.\r
105      * {@internal\r
106      * Also, it divides the source tokens into separate lines for use by\r
107      * the @filesource tag.\r
108      *\r
109      * {@source}}}\r
110      *\r
111      * @param string &$input source code\r
112      *\r
113      * @return void\r
114      */\r
115     function setup(&$input)\r
116     {\r
117         $input      = rtrim(ltrim($input, "\r\n"));\r
118         $this->data = &$input;\r
119         // fix php warnings on invalid source code\r
120         $this->_all         = @token_get_all($input);\r
121         $this->_file_source = array();\r
122         $this->addFileSource($this->_all);\r
123         $this->_sourceline = 0;\r
124         $this->pos         = 0;\r
125         $this->linenum     = 0;\r
126     }\r
127     \r
128     /**\r
129      * loads up next set of source code\r
130      *\r
131      * @return array source code array\r
132      */\r
133     function getSource()\r
134     {\r
135         $source          = $this->source;\r
136         $this->source    = array();\r
137         $this->getsource = false;\r
138         return $source;\r
139     }\r
140     \r
141     /**\r
142      * gets the source code tokens\r
143      *\r
144      * @return array source code tokens split up by line number\r
145      */\r
146     function getFileSource()\r
147     {\r
148         return $this->_file_source;\r
149     }\r
150     \r
151     /**\r
152      * Begin retrieving source code\r
153      *\r
154      * @param string $word word to add the beginning of source code\r
155      *\r
156      * @return void\r
157      * @access private\r
158      * @todo   CS cleanup - rename to retrieveSource for camelCase rule\r
159      */\r
160     function retrievesource($word = '')\r
161     {\r
162         $this->source      = array(array($word));\r
163         $this->_sourceline = 0;\r
164         $this->getsource   = true;\r
165     }\r
166 \r
167     /**\r
168      * Utility function to determine whether two tokens from the tokenizer are equal\r
169      *\r
170      * @param mixed $a first token\r
171      * @param mixed $b second token\r
172      *\r
173      * @return bool whether or not the tokens are equal\r
174      * @static\r
175      */\r
176     function tokenEquals($a, $b)\r
177     {\r
178         if (is_array($a)) $a = $a[1];\r
179         if (is_array($b)) $b = $b[1];\r
180         return $a == $b;\r
181     }\r
182     \r
183     /**\r
184      * Utility function to convert a series of tokens into a string\r
185      *\r
186      * @param array $a array of tokens\r
187      *\r
188      * @return string the resulting string\r
189      * @static\r
190      */\r
191     function concatTokens($a)\r
192     {\r
193         $b = '';\r
194         foreach ($a as $c) {\r
195             if (is_array($c)) {\r
196                 $c = $c[1];\r
197             }\r
198             $b .= $c;\r
199         }\r
200         return $b;\r
201     }\r
202     \r
203     /**\r
204      * Retrieve a token for the phpDocumentorTParser\r
205      * {@internal\r
206      * This method adds source code to the array for a function to be returned\r
207      * to a {@}source} tag, and will return the token unless it is T_WHITESPACE\r
208      * and {@link $returnWhiteSpace} is false.\r
209      *\r
210      * The global variable search is more complicated than it is in the\r
211      * WordParser, as we have to compare an array of tokens to each other, and\r
212      * that is what this code does}}\r
213      *\r
214      * @return string|array token from tokenizer\r
215      */\r
216     function getWord()\r
217     {\r
218         if (!isset($this->_all[$this->pos])) {\r
219             return false;\r
220         }\r
221 \r
222         $oldlinenum = $this->linenum;\r
223         $word       = $this->_all[$this->pos++];\r
224 \r
225         // if we're looking for a global variable declaration, then this section\r
226         // will search the upcoming tokens to see if they match the tokens\r
227         // that define the global variable\r
228         if (isset($this->_global_search)) {\r
229             $pos   = $this->pos;\r
230             $gpos  = 0;\r
231             $found = false;\r
232             if ($this->tokenEquals($word, $this->_global_search[$gpos++])) {\r
233                 $found = true;\r
234                 for (;$gpos<count($this->_global_search);$gpos++, $pos++) {\r
235                     if (isset($this->_all[$pos]) &&\r
236                         !$this->tokenEquals($this->_global_search[$gpos], \r
237                             $this->_all[$pos])\r
238                     ) {\r
239                         $found = false;\r
240                     }\r
241                 }\r
242             }\r
243             if ($found) {\r
244                 $a          = $this->concatTokens($this->_global_search);\r
245                 $this->pos += count($this->_global_search) - 1;\r
246                 unset($this->_global_search);\r
247                 return $a;\r
248             }\r
249         }\r
250         if ($this->getsource) {\r
251             $this->addSource($word);\r
252         }\r
253         if (is_array($word)) {\r
254             if (in_array($word[0], $this->_nl_check)) {\r
255                 $this->linenum += substr_count($word[1], "\n");\r
256             }\r
257             if ($word[0] == T_WHITESPACE && !$this->returnWhiteSpace) {\r
258                 return $this->getWord();\r
259             }\r
260             // seeing if we can get line numbers out of the beast\r
261         }\r
262         if (is_array($word) && $word[0] == T_COMMENT) {\r
263             $this->_docblock_linenum = $oldlinenum;\r
264         }\r
265         return $word;\r
266     }\r
267     \r
268     /**\r
269      * Wrapper for {@link addSource()} used to retrieve the entire source code\r
270      * organized by line number in setup()\r
271      *\r
272      * @param array $word full file source code\r
273      *\r
274      * @return void\r
275      */\r
276     function addFileSource($word)\r
277     {\r
278         $this->_sourceline = 0;\r
279         foreach ($word as $token) {\r
280             $this->addSource($token, true);\r
281         }\r
282         // var_dump($this->_file_source);\r
283     }\r
284     \r
285     /**\r
286      * Generate source token arrays organized by line number\r
287      *\r
288      * This code will split up tokens that contain "\n" and add them to the\r
289      * source code as separate tokens on different lines.\r
290      *\r
291      * @param array|string $word token to add\r
292      * @param bool         $file true if this should be added \r
293      *                           to {@link $_file_source}\r
294      *\r
295      * @return void\r
296      * @uses _set_sars()\r
297      */\r
298     function addSource($word, $file = false)\r
299     {\r
300         if (is_array($word)) {\r
301             $lines = str_replace("\r", '', explode("\n", $word[1]));\r
302             foreach ($lines as $i => $line) {\r
303                 $this->_set_sars($file, array($word[0], $line));\r
304                 if ($i < count($lines) - 1) {\r
305                     // increment sourceline\r
306                     $this->_sourceline++;\r
307                 }\r
308             }\r
309         } else {\r
310             $this->_set_sars($file, $word);\r
311         }\r
312     }\r
313     \r
314     /**\r
315      * Add tokens to source code\r
316      *\r
317      * {@source}\r
318      *\r
319      * @param bool         $type true if this is file source,\r
320      *                           otherwise it is function source\r
321      * @param string|array $word token to add\r
322      *\r
323      * @return void\r
324      * @access private\r
325      * @todo CS cleanup - rename to _setSars for camelCasing rule\r
326      */\r
327     function _set_sars($type, $word)\r
328     {\r
329         if ($type) {\r
330             $this->_file_source[$this->_sourceline][] = $word;\r
331         } else {\r
332             $this->source[$this->_sourceline][] = $word;\r
333         }\r
334     }\r
335     \r
336     /**\r
337      * Tell the phpDocumentorTWordParser to return the entire global variable\r
338      * if it is found.\r
339      *\r
340      * @param array $tokens tokens that represent the global variable definition\r
341      *\r
342      * @return void\r
343      * @uses $_global_search\r
344      */\r
345     function findGlobal($tokens)\r
346     {\r
347         if (!$tokens) {\r
348             unset($this->_global_search);\r
349         } else {\r
350             $this->_global_search = $tokens;\r
351         }\r
352     }\r
353     \r
354     /**\r
355      * backs the parser up to the previous position\r
356      *\r
357      * @return int|void can return a word\r
358      */\r
359     function backupPos()\r
360     {\r
361         $this->pos--;\r
362         $word = $this->_all[$this->pos];\r
363         if ($this->getsource) {\r
364             unset($this->source[$this->_sourceline]\r
365                 [count($this->source[$this->_sourceline]) - 1]);\r
366             if (empty($this->source[$this->_sourceline])) {\r
367                 unset($this->source[$this->_sourceline]);\r
368             } else {\r
369                 $this->source[$this->_sourceline] \r
370                     = array_values($this->source[$this->_sourceline]);\r
371             }\r
372         }\r
373         if (is_array($word)) {\r
374             if ($word[0] == T_WHITESPACE && !$this->returnWhiteSpace) {\r
375                 return $this->getWord();\r
376             }\r
377             // seeing if we can get line numbers out of the beast\r
378             if (in_array($word[0], $this->_nl_check)) {\r
379                 $this->linenum -= substr_count($word[1], "\n");\r
380             }\r
381         }\r
382     }\r
383 }\r
384 ?>\r