bea9f728c60e509dca04dfd0c8d6d09ef6b298f8
[atutor.git] / mods / phpdoc2 / PhpDocumentor / phpDocumentor / ParserDescCleanup.inc
1 <?php\r
2 /**\r
3  * All of the functions to clean up and handle the long description\r
4  * of a DocBlock are in this file.\r
5  *\r
6  * The primary functionality is based on Parser and WordParser, and modified to recognize\r
7  * only the tokens defined in the PHPDOCUMENTOR_PDP_* constants\r
8  * \r
9  * phpDocumentor :: automatic documentation generator\r
10  * \r
11  * PHP versions 4 and 5\r
12  *\r
13  * Copyright (c) 2002-2006 Gregory Beaver\r
14  * \r
15  * LICENSE:\r
16  * \r
17  * This library is free software; you can redistribute it\r
18  * and/or modify it under the terms of the GNU Lesser General\r
19  * Public License as published by the Free Software Foundation;\r
20  * either version 2.1 of the License, or (at your option) any\r
21  * later version.\r
22  * \r
23  * This library is distributed in the hope that it will be useful,\r
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
26  * Lesser General Public License for more details.\r
27  * \r
28  * You should have received a copy of the GNU Lesser General Public\r
29  * License along with this library; if not, write to the Free Software\r
30  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
31  *\r
32  * @package    phpDocumentor\r
33  * @subpackage Parsers\r
34  * @author     Gregory Beaver <cellog@php.net>\r
35  * @copyright  2002-2006 Gregory Beaver\r
36  * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL\r
37  * @version    CVS: $Id: ParserDescCleanup.inc,v 1.13 2007/12/13 02:56:45 ashnazg Exp $\r
38  * @link       http://www.phpdoc.org\r
39  * @link       http://pear.php.net/PhpDocumentor\r
40  * @see        Parser, WordParser\r
41  * @since      1.2\r
42  */\r
43 \r
44 /**#@+\r
45  * {@link parserDescParser} token constants\r
46  */\r
47 /** when <<code>> is found in a desc */\r
48 define('PHPDOCUMENTOR_PDP_EVENT_CODE', 600);\r
49 /** when <<code>> is found in a desc */\r
50 define('PHPDOCUMENTOR_PDP_STATE_CODE', 700);\r
51 /** when <<p>> is found in a desc */\r
52 define('PHPDOCUMENTOR_PDP_EVENT_P', 601);\r
53 /** when <<p>> is found in a desc */\r
54 define('PHPDOCUMENTOR_PDP_STATE_P', 701);\r
55 /** when \n\n is found in a desc */\r
56 define('PHPDOCUMENTOR_PDP_EVENT_DOUBLECR', 602);\r
57 /** when \n\n is found in a desc */\r
58 define('PHPDOCUMENTOR_PDP_STATE_DOUBLECR', 702);\r
59 /** when <<pre>> is found in a desc */\r
60 define('PHPDOCUMENTOR_PDP_EVENT_PRE', 603);\r
61 /** when <<pre>> is found in a desc */\r
62 define('PHPDOCUMENTOR_PDP_STATE_PRE', 703);\r
63 /** when <<ul>>/<<ol>> is found in a desc */\r
64 define('PHPDOCUMENTOR_PDP_EVENT_LIST', 604);\r
65 /** when <<ul>>/<<ol>> is found in a desc */\r
66 define('PHPDOCUMENTOR_PDP_STATE_LIST', 704);\r
67 /** when <<b>> is found in a desc */\r
68 define('PHPDOCUMENTOR_PDP_EVENT_B', 605);\r
69 /** when <<b>> is found in a desc */\r
70 define('PHPDOCUMENTOR_PDP_STATE_B', 705);\r
71 /** when <<i>> is found in a desc */\r
72 define('PHPDOCUMENTOR_PDP_EVENT_I', 606);\r
73 /** when <<i>> is found in a desc */\r
74 define('PHPDOCUMENTOR_PDP_STATE_I', 706);\r
75 /** when <<br>> is found in a desc */\r
76 define('PHPDOCUMENTOR_PDP_EVENT_BR', 607);\r
77 /** when <<br>> is found in a desc */\r
78 define('PHPDOCUMENTOR_PDP_STATE_BR', 707);\r
79 /** when the << potential escape for tags is found in a desc */\r
80 define('PHPDOCUMENTOR_PDP_EVENT_ESCAPE',608);\r
81 /** when the << potential escape for tags is found in a desc */\r
82 define('PHPDOCUMENTOR_PDP_STATE_ESCAPE',708);\r
83 /** when << /pre>> is found in a <<pre>><</pre>> section */\r
84 define('PHPDOCUMENTOR_PDP_EVENT_ESCAPE_PRE',609);\r
85 /** when << /pre>> is found in a <<pre>><</pre>> section */\r
86 define('PHPDOCUMENTOR_PDP_STATE_ESCAPE_PRE',709);\r
87 /** when << /code>> is found in a <<code>><</code>> section  */\r
88 define('PHPDOCUMENTOR_PDP_EVENT_ESCAPE_CODE',610);\r
89 /** when << /code>> is found in a <<code>><</code>> section  */\r
90 define('PHPDOCUMENTOR_PDP_STATE_ESCAPE_CODE',710);\r
91 /** when <<var>> is found in a desc  */\r
92 define('PHPDOCUMENTOR_PDP_EVENT_VAR',611);\r
93 /** when <<var>> is found in a desc  */\r
94 define('PHPDOCUMENTOR_PDP_STATE_VAR',711);\r
95 /** when <<samp>> is found in a desc  */\r
96 define('PHPDOCUMENTOR_PDP_EVENT_SAMP',612);\r
97 /** when <<samp>> is found in a desc  */\r
98 define('PHPDOCUMENTOR_PDP_STATE_SAMP',712);\r
99 /** when <<kbd>> is found in a desc  */\r
100 define('PHPDOCUMENTOR_PDP_EVENT_KBD',613);\r
101 /** when <<kbd>> is found in a desc  */\r
102 define('PHPDOCUMENTOR_PDP_STATE_KBD',713);\r
103 /** when a simple list is found in a desc\r
104  *\r
105  * like\r
106  * <pre>\r
107  *  o item 1\r
108  *  o item 2\r
109  * </pre>\r
110  */\r
111 define('PHPDOCUMENTOR_PDP_EVENT_SIMLIST',614);\r
112 /** when a simple list is found in a desc\r
113  *\r
114  * like\r
115  * <pre>\r
116  *  o item 1\r
117  *  o item 2\r
118  * </pre>\r
119  */\r
120 define('PHPDOCUMENTOR_PDP_STATE_SIMLIST',714);\r
121 /**#@-*/\r
122 /**\r
123 * Like WordParser but designed to handle an array with strings and\r
124 * {@link parserInlineTag}s\r
125 * @package phpDocumentor\r
126 * @subpackage WordParsers\r
127 * @author Greg Beaver <cellog@php.net>\r
128 * @since 1.2\r
129 */\r
130 class ObjectWordParser extends WordParser\r
131 {\r
132     /**\r
133      * Determines whether text searching is case-sensitive or not\r
134      * @access private\r
135      */\r
136     var $_casesensitive = false;\r
137     \r
138     function ObjectWordParser($casesensitive = false)\r
139     {\r
140         $this->_casesensitive = $casesensitive;\r
141     }\r
142     \r
143     /**\r
144      * Set the word parser to go.\r
145      *\r
146      * @param array {@link parserStringWithInlineTags::$value} style-array, with\r
147      *              alternating text and inline tags\r
148      */\r
149     function setup(&$input)\r
150     {\r
151 //        if (is_string($input[0])) $input[0] = ltrim($input[0]);\r
152         $this->data = & $input;\r
153         $this->pos = 0;\r
154         $this->linenum = 0;\r
155         $this->linenumpos = 0;\r
156         $this->cache = array();\r
157         reset($this->data);\r
158         list($this->index,) = each($this->data);\r
159         if (!is_object($this->data[$this->index]))\r
160         $this->size = strlen($this->data[$this->index]);\r
161         else $this->size = 0;\r
162         //$this->run = 0;\r
163         //$this->word = WORD_PARSER_RET_WORD;\r
164     }\r
165     \r
166     function getWord()\r
167     {\r
168         if (!isset($this->data[$this->index])) return false;\r
169         // return any inline tags unchanged\r
170         if (is_object($this->data[$this->index]))\r
171         {\r
172             $index = $this->index;\r
173             list($this->index,) = each($this->data);\r
174             $this->pos = 0;\r
175             if ($this->index)\r
176             {\r
177                 if (!is_object($this->data[$this->index]))\r
178                 $this->size = strlen($this->data[$this->index]);\r
179                 else $this->size = 0;\r
180                 $this->cache = array();\r
181                 return $this->data[$index];\r
182             } else\r
183             {\r
184                 return false;\r
185             }\r
186         }\r
187         //$st = $this->mtime();\r
188         if ($this->size == $this->pos)\r
189         {\r
190             // cycle to next line in the array\r
191             list($this->index,) = each($this->data);\r
192             if (!$this->index) return false;\r
193             $this->pos = 0;\r
194             if (!is_object($this->data[$this->index]))\r
195             $this->size = strlen($this->data[$this->index]);\r
196             else $this->size = 0;\r
197             $this->cache = array();\r
198             return $this->getWord();\r
199         }\r
200 \r
201         $npos = $this->size;\r
202         if (is_array($this->wordseperators))\r
203         {\r
204             //$this->wordseperators = array();\r
205             foreach($this->wordseperators as $sep)\r
206             {\r
207                 if (isset($this->cache[$sep]))\r
208                 $tpos = $this->cache[$sep];\r
209                 else\r
210                 $tpos = false;\r
211                 if ($tpos < $this->pos || !is_int($tpos))\r
212                 {\r
213                     if ($this->_casesensitive)\r
214                         $tpos = strpos($this->data[$this->index],$sep,$this->pos);\r
215                     else\r
216                         $tpos = strpos(strtolower($this->data[$this->index]),$sep,$this->pos);\r
217                 }\r
218             \r
219                 if ( ($tpos < $npos) && !($tpos === false))\r
220                 {\r
221                     //echo trim($sep) . "=$tpos\n";\r
222                     $npos = $tpos;\r
223                     $seplen = strlen($sep);\r
224                 } \r
225                   else if (!($tpos === false))\r
226                 {\r
227                     $this->cache[$sep] = $tpos;\r
228                 }\r
229             }\r
230         } else {\r
231             // its time to cycle\r
232             return "";\r
233         }\r
234 \r
235         $len = $npos - $this->pos;\r
236         if ($len == 0)\r
237         {\r
238             $len = $seplen;\r
239         }\r
240 \r
241         //$st3 = $this->mtime();\r
242         $word = substr($this->data[$this->index],$this->pos,$len);\r
243         \r
244         // Change random other os newlines to the unix one\r
245         if ($word == "\r" || $word == "\r\n")\r
246         {\r
247             $word = "\n";\r
248         }\r
249         \r
250         if ($this->linenumpos <= $this->pos)\r
251         {\r
252             $this->linenumpos = $this->pos + $len;\r
253             $this->linenum += count(explode("\n",$word)) - 1;\r
254         }\r
255 \r
256         if ($this->getsource)\r
257         {\r
258             $this->source .= $word;\r
259         }\r
260         $this->pos = $this->pos + $len;\r
261         //$this->word = WORD_PARSER_RET_SEP;\r
262 \r
263         // Things like // commenats rely on the newline to find their end so im going to have to return them\r
264         // never return worthless white space /t ' '\r
265         if ($this->returnWhiteSpace == false)\r
266         {\r
267             if (strlen(trim($word)) == 0 && $word != "\n") \r
268             {\r
269                 $word = $this->getWord();\r
270             }\r
271         }\r
272         //$this->time3 = $this->time3 + ($this->mtime() - $st3);\r
273         //$this->time = $this->time + ($this->mtime() - $st);\r
274         return $word;\r
275     }\r
276     \r
277     /**\r
278      * Determine if the next word is an inline tag\r
279      * @return boolean\r
280      */\r
281     function nextIsObjectOrNonNL()\r
282     {\r
283         return (($this->size == $this->pos) && isset($this->data[$this->index + 1])\r
284             && is_object($this->data[$this->index + 1])) ||\r
285                (($this->size > $this->pos) && !in_array($this->data[$this->index]{$this->pos}, array("\n", "\r")));\r
286     }\r
287 }\r
288 \r
289 /**\r
290  * Parses a DocBlock description to retrieve abstract representations of\r
291  * <<pre>>,<<code>>,<<p>>,<<ul>>,<<ol>>,<<li>>,<<b>>,<<i>>\r
292  * @tutorial phpDocumentor.howto.pkg#basics.desc\r
293  * @package phpDocumentor\r
294  * @subpackage Parsers\r
295  * @author Greg Beaver <cellog@php.net>\r
296  * @since 1.2\r
297  */\r
298 class parserDescParser extends Parser\r
299 {\r
300     /**#@+\r
301      * @access private\r
302      */\r
303     /**\r
304      * @var array\r
305      */\r
306     var $eventHandlers = array(PHPDOCUMENTOR_PDP_EVENT_CODE => 'handleCode',\r
307                                PHPDOCUMENTOR_PDP_EVENT_PRE => 'handlePre',\r
308                                PHPDOCUMENTOR_PDP_EVENT_P => 'handleP',\r
309                                PHPDOCUMENTOR_PDP_EVENT_DOUBLECR => 'handleDoubleCR',\r
310                                PHPDOCUMENTOR_PDP_EVENT_LIST => 'handleList',\r
311                                PHPDOCUMENTOR_PDP_EVENT_B => 'handleB',\r
312                                PHPDOCUMENTOR_PDP_EVENT_I => 'handleI',\r
313                                PHPDOCUMENTOR_PDP_EVENT_VAR => 'handleVar',\r
314                                PHPDOCUMENTOR_PDP_EVENT_KBD => 'handleKbd',\r
315                                PHPDOCUMENTOR_PDP_EVENT_SAMP => 'handleSamp',\r
316                                PHPDOCUMENTOR_PDP_EVENT_BR => 'handleBr',\r
317                                PHPDOCUMENTOR_PDP_EVENT_ESCAPE => 'handleEscape',\r
318                                PHPDOCUMENTOR_PDP_EVENT_ESCAPE_CODE => 'handleEscapeCode',\r
319                                PHPDOCUMENTOR_PDP_EVENT_ESCAPE_PRE => 'handleEscapePre',\r
320                                PHPDOCUMENTOR_PDP_EVENT_SIMLIST => 'handleSimpleList',\r
321                                PARSER_EVENT_NOEVENTS => 'defaultHandler',\r
322                                );\r
323     \r
324     /**\r
325      * @var array\r
326      */\r
327     var $pars = array();\r
328     /**\r
329      * Determines whether parsing of &lt;p&gt; tags will occur, or double CR will\r
330      * be used\r
331      * @var boolean\r
332      */\r
333     var $parse_Ps;\r
334     /**\r
335      * Context stack.\r
336      *\r
337      * Values can be 'normal', or any tag container like 'my_i', 'my_b'.  This\r
338      * is used to determine which tag text or nested tags should be added to\r
339      * @var array\r
340      */\r
341     var $_context = array('normal');\r
342     /**#@-*/\r
343     \r
344     /**\r
345      * sets $wp to be a {@link ObjectWordParser}\r
346      * \r
347      * $wp is the word parser that retrieves tokens\r
348      */\r
349     function parserDescParser()\r
350     {\r
351         $this->wp = new ObjectWordParser;\r
352     }\r
353     \r
354     /**\r
355      * Parse a long or short description for tags\r
356      *\r
357      * @param array array of strings or {@link parserInlineTag}s\r
358      * @param boolean true if the description is a short description. (only 1 paragraph allowed in short desc)\r
359      * @param string name of the class to instantiate for each paragraph.  parserDesc for desc/sdesc,\r
360      *               parserStringWithInlineTags for tag data\r
361      * @staticvar integer used for recursion limiting if a handler for an event is not found\r
362      */\r
363     function parse (&$parse_data,$sdesc = false,$ind_type = 'parserDesc')\r
364     {\r
365         static $endrecur = 0;\r
366         global $_phpDocumentor_setting;\r
367         if (!is_array($parse_data) || count($parse_data) == 0)\r
368         {\r
369             return false;\r
370         }\r
371         $this->p_vars['indtype'] = $ind_type;\r
372         $this->setupStates($sdesc);\r
373         if (isset($_phpDocumentor_setting['javadocdesc']) && $_phpDocumentor_setting['javadocdesc'] == 'on')\r
374             $this->parse_Ps = true;\r
375 \r
376         // initialize variables so E_ALL error_reporting doesn't complain\r
377         $pevent = 0;\r
378         $word = 0;\r
379         $this->p_vars['curpar'] = 0;\r
380         $this->pars = array();\r
381         $this->p_vars['start'] = true;\r
382         $this->p_vars['event_stack'] = new EventStack;\r
383 \r
384         $this->wp->setup($parse_data,$sdesc);\r
385         $this->wp->setWhitespace(true);\r
386         $this->p_vars['list_count'] = 0;\r
387         if ($sdesc) $this->p_vars['start'] = false;\r
388 \r
389         // beware of infinite loops\r
390         $infiniteLoopCatcher = 0;\r
391         do\r
392         {\r
393             $infiniteLoopCatcher++;\r
394             if (!isset($this->pars[$this->p_vars['curpar']])) $this->pars[$this->p_vars['curpar']] = new $ind_type;\r
395             $lpevent = $pevent;\r
396             $pevent = $this->p_vars['event_stack']->getEvent();\r
397             if ($lpevent != $pevent)\r
398             {\r
399                 $this->p_vars['last_pevent'] = $lpevent;\r
400             }\r
401 \r
402             if ($this->p_vars['last_pevent'] != $pevent)\r
403             {\r
404                 // its a new event so the word parser needs to be reconfigured \r
405                 $this->configWordParser($pevent);\r
406             }\r
407 \r
408 \r
409             $this->p_vars['last_word'] = $word;\r
410             $word = $this->wp->getWord();\r
411 \r
412             if (PHPDOCUMENTOR_DEBUG == true)\r
413             {\r
414                 echo "----------------\n";\r
415                 echo "LAST: |" . htmlentities($this->p_vars['last_word']) . "|\n";\r
416 //                echo "INDEX: ".$this->p_vars['curpar']."\n";\r
417                 echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";\r
418                 echo "LASTPEVENT: " . $this->getParserEventName($this->p_vars['last_pevent']) . "\n";\r
419                 echo $this->wp->getPos() . " WORD: |".htmlentities($word)."|\n\n";\r
420                 var_dump($this->_context);\r
421             }\r
422             if (isset($this->eventHandlers[$pevent]))\r
423             {\r
424                 $handle = $this->eventHandlers[$pevent];\r
425                 if ($word !== false) $this->$handle($word, $pevent);\r
426                 else\r
427                 {\r
428                     if (!count($this->pars[$this->p_vars['curpar']]->value)) unset($this->pars[$this->p_vars['curpar']]);\r
429                 }\r
430             } else\r
431             {\r
432                 debug('WARNING: possible error, no ParserDescParser handler for event number '.$pevent);\r
433                 if ($endrecur++ == 25)\r
434                 {\r
435                     addErrorDie(PDERROR_LOOP_RECURSION_LIMIT_REACHED);\r
436                 }\r
437             }\r
438             if (is_object($word) || trim($word) != '')\r
439             {\r
440                 $this->p_vars['start'] = false;\r
441             }\r
442 \r
443             if ($infiniteLoopCatcher > 10000) {\r
444                 echo PHP_EOL . "FATAL ERROR:  Somehow we got into an infinite loop in parserDescCleanup->parse()'s do-while loop...";\r
445                 echo PHP_EOL . "    The line being parsed was:  " . $word . PHP_EOL . PHP_EOL;\r
446                 addErrorDie(PDERROR_LOOP_RECURSION_LIMIT_REACHED);\r
447             }\r
448         } while (is_object($word) || !($word === false) && $word != '');\r
449         $context = $this->getContext();\r
450         if ($context != 'normal')\r
451         {\r
452             if ($context == 'list' && $this->p_flags['simplelist'])\r
453             {\r
454                 $this->p_vars['lists'][0]->addItem($this->p_vars['list_item'][0]);\r
455                 unset($this->p_vars['list_item'][0]);\r
456                 $this->setContext('normal');\r
457                 $this->addText($this->p_vars['lists'][0]);\r
458             } else addError(PDERROR_UNCLOSED_TAG,str_replace('my_','',$context));\r
459         }\r
460         if ($this->p_vars['list_count'] > 0) addError(PDERROR_UNMATCHED_LIST_TAG);\r
461         if ($sdesc)\r
462         $this->publishEvent(2,$this->pars);\r
463         else\r
464         $this->publishEvent(1,$this->pars);\r
465     }\r
466     /**#@+ @access private */\r
467     /**\r
468      * basic handling\r
469      *\r
470      * This function checks to see if the first thing in\r
471      * a description is the <p> tag.  If so, it will switch\r
472      * into a mode of parsing out paragraphs by <p> instead\r
473      * of a double line-break\r
474      *\r
475      * It also removes extra whitespace\r
476      * @uses doSimpleList()\r
477      */\r
478     function defaultHandler($word, $pevent)\r
479     {\r
480         $context = $this->getContext();\r
481         if ($context != 'normal') $this->setContext('normal');\r
482         if ($this->p_vars['start'] && is_string($word) && strtolower($word) == '<p>')\r
483         {\r
484             $this->parse_Ps = true;\r
485         }\r
486         if (is_string($word) && $this->checkEventPush($word, $pevent)) return;\r
487 //        if (!isset($this->parse_Ps) || !$this->parse_Ps)\r
488         {\r
489             if (is_string($word) && is_string($this->p_vars['last_word']) &&\r
490                   ($word == ' ' && $this->p_vars['last_word'] == ' ')) return;\r
491             if ($pevent == PARSER_EVENT_NOEVENTS)\r
492             {\r
493                 if ($this->doSimpleList($word)) return;\r
494             }\r
495             $this->addText($word);\r
496         }\r
497     }\r
498     \r
499     /**\r
500      * Retrieve the current top-level tag to add text into\r
501      * @uses $_context\r
502      */\r
503     function getContext()\r
504     {\r
505         array_push($this->_context,$a = array_pop($this->_context));\r
506         return $a;\r
507     }\r
508     \r
509     /**\r
510      * Pop a context off of the context stack\r
511      * @uses $_context\r
512      */\r
513     function dropContext()\r
514     {\r
515         array_pop($this->_context);\r
516         if (count($this->_context) == 0)\r
517         $this->_context = array('normal');\r
518     }\r
519     \r
520     /**\r
521      * @uses $_context\r
522      * @param string context name\r
523      */\r
524     function setContext($context)\r
525     {\r
526         array_push($this->_context,$context);\r
527     }\r
528     \r
529     /**\r
530      * add input as text to the current paragraph or list\r
531      * @param string|parserInlineTag\r
532      */\r
533     function addText($text)\r
534     {\r
535         $context = $this->getContext();\r
536         if ($context == 'list')\r
537         {\r
538 //            debug('aded to '.$context);\r
539             if (!is_object($this->p_vars['list_item'][$this->p_vars['list_count']])) {\r
540                 addErrorDie(PDERROR_UL_IN_UL);\r
541             }\r
542             $this->p_vars['list_item'][$this->p_vars['list_count']]->add($text);\r
543         } elseif ($context != 'normal')\r
544         {\r
545 //            debug('added to '.$context);\r
546             $this->p_vars[$context]->add($text);\r
547         } else\r
548         {\r
549 //            debug('added to normal ');\r
550             $indtype = $this->p_vars['indtype'];\r
551             if (!isset($this->pars[$this->p_vars['curpar']]))\r
552                 $this->pars[$this->p_vars['curpar']] = new $indtype;\r
553             $this->pars[$this->p_vars['curpar']]->add($text);\r
554         }\r
555     }\r
556     \r
557     /**#@-*/\r
558     /**#@+\r
559      * @access private\r
560      * @param string|parserInlineTag token from the ObjectWordParser\r
561      * @param integer parser event from {@link ParserDescCleanup.inc}\r
562      */\r
563     /**\r
564      * Handles special case where a description needs the text "<tag>" and tag\r
565      * is one of code, b, i, pre, var, or any other valid in-DocBlock html tag.\r
566      *\r
567      * the text <<<code>>> in a DocBlock will parse out as <<code>>, instead\r
568      * of being parsed as markup.\r
569      */\r
570     function handleEscape($word, $pevent)\r
571     {\r
572         $this->p_vars['event_stack']->popEvent();\r
573         if (!in_array($word, $this->tokens[PHPDOCUMENTOR_PDP_STATE_ESCAPE]))\r
574         {\r
575             if ($word == '<')\r
576             {\r
577                 $this->addText($word);\r
578                 $this->wp->backupPos($word.$word);\r
579             } else\r
580             $this->wp->backupPos($word);\r
581             return;\r
582         }\r
583         $this->addText('<'.str_replace('>>','>',$word));\r
584     }\r
585     \r
586     /**\r
587      * Just like {@link handleEscape}, except the only valid escape is\r
588      * <<</pre>>>\r
589      */\r
590     function handleEscapePre($word, $pevent)\r
591     {\r
592         $this->p_vars['event_stack']->popEvent();\r
593         $this->addText('</pre>');\r
594     }\r
595     \r
596     /**\r
597      * Just like {@link handleEscape}, except the only valid escape is\r
598      * <<</code>>>\r
599      */\r
600     function handleEscapeCode($word, $pevent)\r
601     {\r
602         $this->p_vars['event_stack']->popEvent();\r
603         $this->addText('</code>');\r
604     }\r
605     \r
606     /**\r
607      * Handle "<<br>>"\r
608      * Add a new {@link parserBr}\r
609      * @uses addText()\r
610      */\r
611     function handleBr($word, $pevent)\r
612     {\r
613         if (is_string($word) && $this->checkEventPop($word, $pevent))\r
614         {\r
615             $this->addText(new parserBr);\r
616         }\r
617     }\r
618     \r
619     /**\r
620      * Handles simple lists\r
621      *\r
622      * phpEdit has an ingenious facility to handle simple lists used in a\r
623      * DocBlock like this:\r
624      *\r
625      * - item 1\r
626      * - item 2\r
627      * - item 3\r
628      *\r
629      * The DocBlock is:\r
630      * <pre>\r
631      * * - item 1\r
632      * * - item 2\r
633      * * - item 3\r
634      * </pre>\r
635      * This function converts these simple lists into the parserList class\r
636      * @param boolean true if this is the first list item in the list\r
637      */\r
638     function handleSimpleList($word, $pevent, $start = false)\r
639     {\r
640         if (is_object($word) && $this->p_flags['in_item'])\r
641         {\r
642             $this->p_vars['list_item'][0]->add($word);\r
643             return;\r
644         }\r
645         if (is_string($word) && $this->checkEventPush($word, $pevent))\r
646         {\r
647             $this->p_flags['in_event'] = true;\r
648             return;\r
649         }\r
650         $ltrimword = @substr($word, @strpos($word, ltrim($word)));\r
651         $is_valid = false;\r
652         if (strlen(trim($word)) == 0)\r
653         {\r
654             if ($this->wp->nextIsObjectOrNonNL())\r
655             {\r
656                 $is_valid = true;\r
657             }\r
658         }\r
659         if ($word == "\n" && is_string($this->p_vars['last_word'])\r
660             && $this->p_vars['last_word']{strlen($this->p_vars['last_word']) - 1}\r
661                 == "\n")\r
662         {\r
663             if ($this->p_flags['in_item'])\r
664             {\r
665                 $this->p_vars['lists'][0]->addItem($this->p_vars['list_item'][0]);\r
666                 unset($this->p_vars['list_item'][0]);\r
667                 $this->setContext('normal');\r
668                 $this->p_flags['simplelist'] = false;\r
669                 $this->addText($this->p_vars['lists'][0]);\r
670                 unset($this->p_vars['lists']);\r
671                 unset($this->p_vars['last_list']);\r
672                 $this->wp->backuppos($word);\r
673                 $this->p_vars['event_stack']->popEvent();\r
674                 $this->p_flags['in_item'] = false;\r
675 //                debug('end of list 3');\r
676                 return;\r
677             } else\r
678             {\r
679                 $this->wp->backuppos($word);\r
680                 $this->p_vars['event_stack']->popEvent();\r
681                 $this->p_flags['in_item'] = false;\r
682 //                debug('not a list 2');\r
683                 return;\r
684             }\r
685         }\r
686         $start_list = $this->getStartList($word);\r
687         if (substr($ltrimword,0,strlen($start_list)) != $start_list \r
688              || $this->p_flags['in_event'] || is_object($this->p_vars['last_word']))\r
689         {\r
690             if (((strlen($this->p_vars['whitespace']) + 1) < strlen(substr($word,0,strpos($word, $ltrimword))))\r
691                    || $word == "\n"\r
692                    || $is_valid\r
693                    || $this->p_flags['in_event']\r
694                    || (is_object($this->p_vars['last_word']) && $this->p_flags['in_item']))\r
695             {\r
696                 $this->p_vars['list_item'][0]->add($word);\r
697                 $this->resetStartList($start_list);\r
698                 $this->p_flags['in_event'] = false;\r
699 //                debug('middle of list');\r
700             } else\r
701             {\r
702                 if ($this->p_flags['in_item'])\r
703                 {\r
704                     $this->p_vars['lists'][0]->addItem($this->p_vars['list_item'][0]);\r
705                     unset($this->p_vars['list_item'][0]);\r
706                     $this->setContext('normal');\r
707                     $this->p_flags['simplelist'] = false;\r
708                     $this->addText($this->p_vars['lists'][0]);\r
709                     unset($this->p_vars['lists']);\r
710                     unset($this->p_vars['last_list']);\r
711                     $this->wp->backuppos($word);\r
712                     $this->p_vars['event_stack']->popEvent();\r
713                     $this->p_flags['in_item'] = false;\r
714 //                    debug('end of list 1');\r
715                     return;\r
716                 } else\r
717                 {\r
718                     $this->wp->backuppos($word);\r
719                     $this->p_vars['event_stack']->popEvent();\r
720                     $this->p_flags['in_item'] = false;\r
721 //                    debug('not a list');\r
722                     return;\r
723                 }\r
724             }\r
725         } else\r
726         {\r
727             if ($this->p_vars['whitespace'] != substr($word,0,strpos($word, $start_list)))\r
728             { // if the whitespace is greater than that preceding the list\r
729               // delimiter, it's a multi-line list item\r
730                 $this->setContext('normal');\r
731                 $this->p_flags['simplelist'] = false;\r
732                 $this->addText($this->p_vars['lists'][0]);\r
733                 unset($this->p_vars['lists']);\r
734                 $this->wp->backuppos($word);\r
735                 $this->p_vars['event_stack']->popEvent();\r
736                 unset($this->p_vars['last_list']);\r
737                 $this->p_flags['in_item'] = false;\r
738 //                debug('end of list 2');\r
739                 return;\r
740             } else\r
741             {\r
742                 if ($this->p_flags['in_item'])\r
743                 {\r
744                     // end of a list item, add it to the list\r
745                     $this->p_vars['lists'][0]->addItem($this->p_vars['list_item'][0]);\r
746                     unset($this->p_vars['list_item'][0]);\r
747                 }\r
748 //                debug('next list item');\r
749                 $this->p_vars['list_item'][0] = new parserStringWithInlineTags;\r
750                 $this->p_vars['list_item'][0]->add(ltrim(substr($ltrimword,strlen($start_list))));\r
751                 $this->p_flags['in_item'] = true;\r
752             }\r
753         }\r
754     }\r
755     /**#@-*/\r
756     /**\r
757      * Get the next list marker\r
758      *\r
759      * In unordered lists, this will be something like "o", "-"\r
760      *\r
761      * In ordered lists, this will be either the number "3", "5" or "3.", "5."\r
762      * @return string text of the next list marker to look for\r
763      * @param string current word from the parser\r
764      * @access private\r
765      */\r
766     function getStartList($word)\r
767     {\r
768         // unordered, return the first marker found\r
769         if (!$this->p_flags['orderedlist']) return $this->p_vars['start_list'];\r
770         if (isset($this->p_vars['last_list']))\r
771         {\r
772             $this->p_vars['save_list'] = $this->p_vars['last_list'];\r
773             $next = $this->p_vars['last_list'];\r
774             // increment to next list number, convert to string\r
775             if (substr($this->p_vars['start_list'], strlen($this->p_vars['start_list']) - 1) == '.')\r
776                 $next = (substr($next, 0, strpos($next,'.')) + 1) . '.';\r
777             else\r
778                 $next = ($next + 1) . '';\r
779 //                debug("next is '$next'");\r
780             if ($this->p_vars['whitespace'] == substr($word,0,strpos($word, $next)))\r
781                 return $this->p_vars['last_list'] = $next;\r
782             // the next number is not in this word, so return but don't save\r
783             return $next;\r
784         } else\r
785         {\r
786             $this->p_vars['last_list'] = $this->p_vars['start_list'];\r
787             return $this->p_vars['start_list'];\r
788         }\r
789     }\r
790     \r
791     /**\r
792      * Set the next list marker to the current list marker\r
793      *\r
794      * In ordered lists, this will ensure that the next number returned is the\r
795      * right number\r
796      * @param string token for next list marker\r
797      * @access private\r
798      */\r
799     function resetStartList($start)\r
800     {\r
801         if (!isset($this->p_vars['save_list'])) return false;\r
802         $this->p_vars['last_list'] = $this->p_vars['save_list'];\r
803     }\r
804     \r
805     /**#@+\r
806      * @access private\r
807      * @param string|parserInlineTag token from the ObjectWordParser\r
808      * @param integer parser event from {@link ParserDescCleanup.inc}\r
809      */\r
810     /**\r
811      * Handles <<ol>>,<<li>>,<<ul>>\r
812      *\r
813      * This allows parsing of lists nested to any level.  Using\r
814      * the lists and list_item temporary variables and using\r
815      * list_count to control nesting, the method creates a {@link parserList}\r
816      * for each <<ol>> or <<ul>> tag, and a\r
817      * standard {@link parserStringWithInlineTags} for all the text, adding\r
818      * in nested lists as if they were inline tags (the conversion interface\r
819      * is the same for both object types)\r
820      */\r
821     function handleList($word, $pevent)\r
822     {\r
823         if (is_string($word) && $this->checkEventPush($word, $pevent))\r
824         {\r
825             return;\r
826         }\r
827         $ordered = false;\r
828         if (!is_object($this->p_vars['last_word']) && strtolower($this->p_vars['last_word']) == '<ol>')\r
829         {\r
830             // ordered list\r
831             $ordered = true;\r
832         }\r
833         // start a new list\r
834         if (!is_object($this->p_vars['last_word']) && (strtolower($this->p_vars['last_word']) == '<ol>' || strtolower($this->p_vars['last_word']) == '<ul>'))\r
835         {\r
836             $this->p_flags['in_item'] = false;\r
837             $this->setContext('list');\r
838             $this->p_vars['lists'][++$this->p_vars['list_count']] = new parserList($ordered);\r
839         }\r
840         if (!is_object($word) && strtolower($word) == '<li>')\r
841         {\r
842             if ($this->p_flags['in_item'])\r
843             {\r
844                 // end of a list item (no end tag), add it to the list\r
845                 $this->p_vars['lists'][$this->p_vars['list_count']]->addItem($this->p_vars['list_item'][$this->p_vars['list_count']]);\r
846                 unset($this->p_vars['list_item'][$this->p_vars['list_count']]);\r
847             }\r
848             // start a new list item\r
849             $this->p_vars['list_item'][$this->p_vars['list_count']] = new parserStringWithInlineTags;\r
850             $this->p_flags['in_item'] = true;\r
851         } else\r
852         {\r
853             if (is_object($word) || (strtolower($word) != '</li>'))\r
854             {\r
855                 if (is_object($word) || (strtolower($word) != '</ul>' && strtolower($word) != '</ol>'))\r
856                 {\r
857                     // item text\r
858                     if (isset($this->p_vars['list_item'][$this->p_vars['list_count']]))\r
859                     {\r
860                         if (is_string($word) && $word == ' ' &&\r
861                               $this->p_vars['last_word'] == ' ') return;\r
862                         $this->p_vars['list_item'][$this->p_vars['list_count']]->add($word);\r
863                     }\r
864                 } else\r
865                 {\r
866                     if ($this->p_flags['in_item'])\r
867                     {\r
868                         // end the current list item before ending a list\r
869                         $this->p_vars['lists'][$this->p_vars['list_count']]->addItem($this->p_vars['list_item'][$this->p_vars['list_count']]);\r
870                         unset($this->p_vars['list_item'][$this->p_vars['list_count']]);\r
871                         $this->p_flags['in_item'] = false;\r
872                     }\r
873                     if (is_string($word) && $this->checkEventPop($word, $pevent))\r
874                     {\r
875                         if ($this->p_vars['list_count'] > 1)\r
876                         {\r
877                             // this is a sublist, add it to the list item of the parent list\r
878                             if (!isset($this->p_vars['list_item'][$this->p_vars['list_count'] - 1])) {\r
879                                 addErrorDie(PDERROR_UL_IN_UL);\r
880                             }\r
881                             $this->p_vars['list_item'][$this->p_vars['list_count'] - 1]->add($this->p_vars['lists'][$this->p_vars['list_count']]);\r
882                             // remove the sublist item and sublist, drop to parent list\r
883                             unset($this->p_vars['lists'][$this->p_vars['list_count']]);\r
884                             unset($this->p_vars['lists'][$this->p_vars['list_count']]);\r
885                             $this->p_vars['list_count']--;\r
886                             $this->p_flags['in_item'] = true;\r
887                         } else\r
888                         {\r
889                             // this is a primary list and it has concluded\r
890                             $this->pars[$this->p_vars['curpar']]->add($this->p_vars['lists'][$this->p_vars['list_count']]);\r
891                             unset($this->p_vars['lists']);\r
892                             unset($this->p_vars['list_item']);\r
893                             $this->p_vars['list_count'] = 0;\r
894                             $this->dropContext();\r
895                         }\r
896                     }\r
897                 }\r
898             } else\r
899             {\r
900                 // check to make sure our list item is not unclosed\r
901                 if (!$this->p_flags['in_item'])\r
902                 {\r
903                     addError(PDERROR_TEXT_OUTSIDE_LI);\r
904                 } else\r
905                 {\r
906                     // end of a list item, add it to the list\r
907                     $this->p_vars['lists'][$this->p_vars['list_count']]->addItem($this->p_vars['list_item'][$this->p_vars['list_count']]);\r
908                     unset($this->p_vars['list_item'][$this->p_vars['list_count']]);\r
909                     $this->p_flags['in_item'] = false;\r
910                 }\r
911             }\r
912         }\r
913     }\r
914 \r
915     /**\r
916      * Handles <<code>><</code>> blocks\r
917      */\r
918     function handleCode($word, $pevent)\r
919     {\r
920         if (!isset($this->p_vars['my_code']))\r
921         {\r
922             $this->setContext('my_code');\r
923             $this->p_vars['my_code'] = new parserCode;\r
924         }\r
925         if (is_string($word) && $this->checkEventPush($word, $pevent)) return;\r
926         if (is_object($word) || strtolower($word) != '</code>') $this->p_vars['my_code']->add($word);\r
927         if (is_string($word))\r
928         {\r
929             if ($this->checkEventPop($word,$pevent))\r
930             {\r
931                 $this->dropContext();\r
932                 $this->addText($this->p_vars['my_code']);\r
933                 unset($this->p_vars['my_code']);\r
934             }\r
935         }\r
936     }\r
937     \r
938     /**\r
939      * Handles <<pre>><</pre>> blocks\r
940      */\r
941     function handlePre($word, $pevent)\r
942     {\r
943         if (!isset($this->p_vars['my_pre']))\r
944         {\r
945             $this->setContext('my_pre');\r
946             $this->p_vars['my_pre'] = new parserPre;\r
947         }\r
948         if (is_string($word) && $this->checkEventPush($word, $pevent)) return;\r
949         if (is_object($word) || strtolower($word) != '</pre>') $this->p_vars['my_pre']->add($word);\r
950         if (is_string($word))\r
951         {\r
952             if ($this->checkEventPop($word,$pevent))\r
953             {\r
954                 $this->dropContext();\r
955                 $this->addText($this->p_vars['my_pre']);\r
956                 unset($this->p_vars['my_pre']);\r
957             }\r
958         }\r
959     }\r
960     \r
961     /**\r
962      * Handles <<b>><</b>> blocks\r
963      */\r
964     function handleB($word, $pevent)\r
965     {\r
966         if (!isset($this->p_vars['my_b']))\r
967         {\r
968             $this->setContext('my_b');\r
969             $this->p_vars['my_b'] = new parserB;\r
970         }\r
971         if (is_string($word))\r
972         {\r
973             if ($this->checkEventPop($word,$pevent))\r
974             {\r
975                 $this->dropContext();\r
976                 $this->addText($this->p_vars['my_b']);\r
977                 unset($this->p_vars['my_b']);\r
978             } else\r
979             {\r
980                 $this->p_vars['my_b']->add($word);\r
981             }\r
982         } else $this->p_vars['my_b']->add($word);\r
983     }\r
984     \r
985     /**\r
986      * Handles <<i>><</i>> blocks\r
987      */\r
988     function handleI($word, $pevent)\r
989     {\r
990         if (!isset($this->p_vars['my_i']))\r
991         {\r
992             $this->p_vars['my_i'] = new parserI;\r
993             $this->setContext('my_i');\r
994         }\r
995         if (is_string($word))\r
996         {\r
997             if ($this->checkEventPop($word,$pevent))\r
998             {\r
999                 $this->dropContext();\r
1000                 $this->addText($this->p_vars['my_i']);\r
1001                 unset($this->p_vars['my_i']);\r
1002             } else\r
1003             {\r
1004                 $this->p_vars['my_i']->add($word);\r
1005             }\r
1006         } else $this->p_vars['my_i']->add($word);\r
1007     }\r
1008     \r
1009     /**\r
1010      * Handles <<var>><</var>> blocks\r
1011      */\r
1012     function handleVar($word, $pevent)\r
1013     {\r
1014         if (!isset($this->p_vars['my_var']))\r
1015         {\r
1016             $this->setContext('my_var');\r
1017             $this->p_vars['my_var'] = new parserDescVar;\r
1018         }\r
1019         if (is_string($word))\r
1020         {\r
1021             if ($this->checkEventPop($word,$pevent))\r
1022             {\r
1023                 $this->dropContext();\r
1024                 $this->addText($this->p_vars['my_var']);\r
1025                 unset($this->p_vars['my_var']);\r
1026             } else\r
1027             {\r
1028                 $this->p_vars['my_var']->add($word);\r
1029             }\r
1030         } else $this->p_vars['my_var']->add($word);\r
1031     }\r
1032     \r
1033     /**\r
1034      * Handles <<samp>><</samp>> blocks\r
1035      */\r
1036     function handleSamp($word, $pevent)\r
1037     {\r
1038         if (!isset($this->p_vars['my_samp']))\r
1039         {\r
1040             $this->setContext('my_samp');\r
1041             $this->p_vars['my_samp'] = new parserSamp;\r
1042         }\r
1043         if (is_string($word))\r
1044         {\r
1045             if ($this->checkEventPop($word,$pevent))\r
1046             {\r
1047                 $this->dropContext();\r
1048                 $this->addText($this->p_vars['my_samp']);\r
1049                 unset($this->p_vars['my_samp']);\r
1050             } else\r
1051             {\r
1052                 $this->p_vars['my_samp']->add($word);\r
1053             }\r
1054         } else $this->p_vars['my_samp']->add($word);\r
1055     }\r
1056     \r
1057     /**\r
1058      * Handles <<kbd>><</kbd>> blocks\r
1059      */\r
1060     function handleKbd($word, $pevent)\r
1061     {\r
1062         if (!isset($this->p_vars['my_kbd']))\r
1063         {\r
1064             $this->setContext('my_kbd');\r
1065             $this->p_vars['my_kbd'] = new parserKbd;\r
1066         }\r
1067         if (is_string($word))\r
1068         {\r
1069             if ($this->checkEventPop($word,$pevent))\r
1070             {\r
1071                 $this->dropContext();\r
1072                 $this->addText($this->p_vars['my_kbd']);\r
1073                 unset($this->p_vars['my_kbd']);\r
1074             } else\r
1075             {\r
1076                 $this->p_vars['my_kbd']->add($word);\r
1077             }\r
1078         } else $this->p_vars['my_kbd']->add($word);\r
1079     }\r
1080     \r
1081     /**\r
1082      * Handles <<p>><</p>> blocks\r
1083      *\r
1084      * Note that the only time <<p>> will be interpreted as delimiting a\r
1085      * paragraph is if it is the first thing in the description.\r
1086      */\r
1087     function handleP($word, $pevent)\r
1088     {\r
1089         if (!isset($this->parse_Ps)) $this->parse_Ps = false;\r
1090         if (is_string($word))\r
1091         {\r
1092             if (is_string($word) && $this->checkEventPush($word, $pevent)) return;\r
1093         }\r
1094         if (!$this->parse_Ps)\r
1095         {\r
1096             $this->p_vars['event_stack']->popEvent();\r
1097             if (!is_object($word) && strtolower($this->p_vars['last_word']) == '<p>') $this->addText('<p>');\r
1098             $this->addText($word);\r
1099             return;\r
1100         }\r
1101         if (is_string($word) && $word == "\n") $word = " ";\r
1102         if (is_string($word))\r
1103         {\r
1104             if ($this->checkEventPop($word, $pevent))\r
1105             {\r
1106                 $this->p_vars['curpar']++;\r
1107                 return;\r
1108             }\r
1109             // if no closing tag, pretend there was one\r
1110             if (!is_object($word) && strtolower($word) == '<p>' && $this->parse_Ps)\r
1111             {\r
1112                 $this->p_vars['curpar']++;\r
1113                 return;\r
1114             }\r
1115         }\r
1116         if ($this->p_vars['start'])\r
1117         {\r
1118             $this->addText($word);\r
1119         } else\r
1120         {// if the <p> is not at the beginning of the desc, then it is not\r
1121          // possible to parse into paragraphs using this tag\r
1122             if ($word === ' ' && $this->p_vars['last_word'] === ' ') return;\r
1123             $this->addText($word);\r
1124         }\r
1125     }\r
1126     \r
1127     /**\r
1128      * Handles \n\n as a paragraph marker\r
1129      * @uses doSimpleList()\r
1130      */\r
1131     function handleDoubleCR($word, $pevent)\r
1132     {\r
1133         $this->p_vars['event_stack']->popEvent();\r
1134         if ($word == "\n")\r
1135         {\r
1136             // only use this if <p> isn't being used\r
1137             if ((!isset($this->parse_Ps) || !$this->parse_Ps))\r
1138             {\r
1139                 if ($this->p_vars['last_word'] == "\n")\r
1140                 {\r
1141                     $this->p_vars['curpar']++;\r
1142                     $this->parse_Ps = false;\r
1143                 } else\r
1144                 {\r
1145                     if (is_string($word) && !$this->checkEventPush($word, $pevent))\r
1146                     {\r
1147                         if ($word == ' ' && $this->p_vars['last_word'] == ' ') return;\r
1148                         $this->addText($word);\r
1149                     }\r
1150                 }\r
1151             } else\r
1152             {\r
1153                 if (is_string($word) && !$this->checkEventPush($word, $pevent))\r
1154                 {\r
1155                     if ($word == ' ' && $this->p_vars['last_word'] == ' ') return;\r
1156                     $this->addText($word);\r
1157                 }\r
1158             }\r
1159         } else\r
1160         {\r
1161             if ($this->p_vars['last_word'] == "\n")\r
1162             {\r
1163                 if ((!isset($this->parse_Ps) || !$this->parse_Ps))\r
1164                 {\r
1165                     $this->addText(' ');\r
1166                 }\r
1167             }\r
1168             if (is_string($word) && !($e = $this->checkEventPush($word, $pevent)))\r
1169             {\r
1170                 if ($word == ' ' && $this->p_vars['last_word'] == ' ') return;\r
1171                 if ($this->doSimpleList($word)) return;\r
1172                 $this->addText($word);\r
1173             }\r
1174         }\r
1175     }\r
1176     \r
1177     /**#@-*/\r
1178     /**\r
1179      * Return a simple list, if found\r
1180      *\r
1181      * This helper function extracts a simple list beginning with any of\r
1182      * 'o','-'.'#','+','0','1','0.','1.' and starts parsing it.\r
1183      * @param string line that may contain a simple list\r
1184      * @return boolean true if a list is found, false otherwise\r
1185      */\r
1186     function doSimpleList($word)\r
1187     {\r
1188         if ($this->p_flags['in_event']) return true;\r
1189         if (is_object($word)) return false;\r
1190         $ltrimword = ltrim($word);\r
1191         if ((strlen($ltrimword) != strlen($word))\r
1192              && strlen($ltrimword) > 1\r
1193              && ((in_array($ltrimword{0},array('o','-','1','0','#','+')) && $ltrimword{1} == ' '))\r
1194                  || ((strlen($ltrimword) >= 2) && (substr($ltrimword,0,2) === '1.' || substr($ltrimword,0,2) === '0.') && $ltrimword{2} == ' '))\r
1195         {\r
1196             // save the whitespace for comparison\r
1197             $this->p_vars['whitespace'] = substr($word,0,strlen($word) - strlen($ltrimword));\r
1198             $this->p_vars['start_list'] = $ltrimword{0};\r
1199             if ($this->p_vars['start_list'] != '1' && $this->p_vars['start_list'] != '1.' &&\r
1200                 $this->p_vars['start_list'] != '0' && $this->p_vars['start_list'] != '0.')\r
1201             {\r
1202                 $this->p_flags['orderedlist'] = false;\r
1203             } else\r
1204             {\r
1205                 if (substr($ltrimword,0,2) == '1.')\r
1206                 {\r
1207                     $this->p_vars['start_list'] = '1.';\r
1208                 }\r
1209                 $this->p_flags['orderedlist'] = true;\r
1210             }\r
1211             $this->p_vars['event_stack']->pushEvent(PHPDOCUMENTOR_PDP_EVENT_SIMLIST);\r
1212             $this->setContext('list');\r
1213             $this->p_flags['simplelist'] = true;\r
1214             $this->p_vars['lists'][0] = new parserList($this->p_flags['orderedlist']);\r
1215             $this->p_vars['list_count'] = 0;\r
1216             $this->handleSimpleList($word, PHPDOCUMENTOR_PDP_EVENT_SIMLIST, true);\r
1217             return true;\r
1218         }\r
1219         return false;\r
1220     }\r
1221     /**\r
1222     * setup the parser tokens, and the pushEvent/popEvent arrays\r
1223     * @see $tokens, $pushEvent, $popEvent\r
1224     * @param boolean determines whether to allow paragraph parsing\r
1225     * @global boolean used to determine whether to slow things down or not by\r
1226     * eliminating whitespace from comments\r
1227     */\r
1228     \r
1229     function setupStates($sdesc)\r
1230     {\r
1231         $this->p_flags['in_item'] = false;\r
1232         $this->p_flags['in_event'] = false;\r
1233         $this->p_flags['simplelist'] = false;\r
1234         $this->_context = array('normal');\r
1235         $this->tokens[STATE_NOEVENTS]            = array("\n", "<code>", "<pre>", "<ol>", "<ul>", \r
1236                                                          "<b>", "<i>", '<var>', '<kbd>', '<samp>', "<br", '<<');\r
1237         if (!$sdesc)\r
1238         {\r
1239             $this->tokens[STATE_NOEVENTS][] = "<p>";\r
1240             $this->tokens[STATE_NOEVENTS][] = "</p>";\r
1241         }\r
1242         if (PHPDOCUMENTOR_KILL_WHITESPACE) $this->tokens[STATE_NOEVENTS][] = ' ';\r
1243         $this->tokens[PHPDOCUMENTOR_PDP_STATE_P]        = array("</p>","<code>","<pre>","\n","<ol>","<ul>","<b>","<i>","<br","<p>", '<<',\r
1244                                                                 '<var>', '<kbd>', '<samp>');\r
1245         if (PHPDOCUMENTOR_KILL_WHITESPACE) $this->tokens[PHPDOCUMENTOR_PDP_STATE_P][] = ' ';\r
1246         $this->tokens[PHPDOCUMENTOR_PDP_STATE_CODE]        = array("</code>", '<</code>>');\r
1247         $this->tokens[PHPDOCUMENTOR_PDP_STATE_PRE]        = array("</pre>", '<</pre>>');\r
1248         $this->tokens[PHPDOCUMENTOR_PDP_STATE_LIST]        = array("<ul>","<ol>","</ul>","</ol>","<li>","</li>","<b>","<i>","<br", '<<',"<code>","<pre>","<br",\r
1249                                                                    '<var>', '<kbd>', '<samp>');\r
1250         $this->tokens[PHPDOCUMENTOR_PDP_STATE_DOUBLECR]        = array("\n","<ol>","<ul>","<code>","<pre>","<b>","<i>","<br","<p>","</p>",\r
1251                                                                        '<var>', '<kbd>', '<samp>', '<<');\r
1252         $this->tokens[PHPDOCUMENTOR_PDP_STATE_SIMLIST]      = array("\n",'<var>', '<kbd>', '<samp>','<b>','<i>', '<pre>', '<code>',\r
1253                                                                     '<br', '<<');\r
1254 \r
1255         $this->tokens[PHPDOCUMENTOR_PDP_STATE_B]    = array("<code>","\n","<pre>","<ol>","<ul>","</b>","<i>","<br", '<<',\r
1256                                                             '<var>', '<kbd>', '<samp>');\r
1257         $this->tokens[PHPDOCUMENTOR_PDP_STATE_KBD]    = array("<code>","\n","<pre>","<ol>","<ul>","<b>","<i>","<br", '<<',\r
1258                                                             '<var>', '</kbd>', '<samp>');\r
1259         $this->tokens[PHPDOCUMENTOR_PDP_STATE_VAR]    = array("<code>","\n","<pre>","<ol>","<ul>","<b>","<i>","<br", '<<',\r
1260                                                             '</var>', '<kbd>', '<samp>');\r
1261         $this->tokens[PHPDOCUMENTOR_PDP_STATE_SAMP]    = array("<code>","\n","<pre>","<ol>","<ul>","<b>","<i>","<br", '<<',\r
1262                                                             '<var>', '<kbd>', '</samp>');\r
1263         $this->tokens[PHPDOCUMENTOR_PDP_STATE_I]    = array("<code>","\n","<pre>","<ol>","<ul>","<b>","</i>","<br", '<<',\r
1264                                                             '<var>', '<kbd>', '<samp>');\r
1265         $this->tokens[PHPDOCUMENTOR_PDP_STATE_BR]    = array(">","/>");\r
1266         $this->tokens[PHPDOCUMENTOR_PDP_STATE_ESCAPE]    = array('code>>', '/code>>', 'pre>>', '/pre>>', 'b>>', '/b>>', \r
1267                                                                  'i>>', '/i>>', 'ol>>', '/ol>>', 'ul>>', '/ul>>', 'li>>', '/li>>', \r
1268                                                                  'br>>', 'br />>', 'p>>', '/p>>', 'samp>>', '/samp>>', \r
1269                                                                  'kbd>>', '/kbd>>', 'var>>', '/var>>'); \r
1270         if (PHPDOCUMENTOR_KILL_WHITESPACE) $this->tokens[PHPDOCUMENTOR_PDP_STATE_DOUBLECR][] = ' ';\r
1271 \r
1272         // For each event word to event mapings\r
1273         $this->pushEvent[PARSER_EVENT_NOEVENTS] = \r
1274             array(\r
1275                 "<code>"    => PHPDOCUMENTOR_PDP_EVENT_CODE,\r
1276                 "<pre>"    => PHPDOCUMENTOR_PDP_EVENT_PRE,\r
1277                 "<p>" => PHPDOCUMENTOR_PDP_EVENT_P,\r
1278                 "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,\r
1279                 "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,\r
1280                 "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,\r
1281                 "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1282                 "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1283                 "<b>" => PHPDOCUMENTOR_PDP_EVENT_B,\r
1284                 "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,\r
1285                 "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,\r
1286                 "\n" => PHPDOCUMENTOR_PDP_EVENT_DOUBLECR,\r
1287                 '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,\r
1288             );\r
1289 ##########################\r
1290         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_CODE] =\r
1291             array(\r
1292                 '<</code>>' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE_CODE,\r
1293             );\r
1294          \r
1295         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_CODE] = array("</code>");\r
1296 ##########################\r
1297         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_PRE] =\r
1298             array(\r
1299                 '<</pre>>' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE_PRE,\r
1300             );\r
1301          \r
1302         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_PRE] = array("</pre>");\r
1303 ##########################\r
1304          \r
1305         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_BR] = array(">","/>");\r
1306 ##########################\r
1307         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_P] =\r
1308             array(\r
1309                 "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,\r
1310                 "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1311                 "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1312                 "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,\r
1313                 "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,\r
1314                 "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,\r
1315                 "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,\r
1316                 "<b>" => PHPDOCUMENTOR_PDP_EVENT_B,\r
1317                 "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,\r
1318                 "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,\r
1319                 '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,\r
1320             );\r
1321          \r
1322         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_P] = array("</p>");\r
1323 ##########################\r
1324         \r
1325         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_LIST] =\r
1326             array(\r
1327                 "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1328                 "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1329                 "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,\r
1330                 "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,\r
1331                 "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,\r
1332                 "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,\r
1333                 "<b>" => PHPDOCUMENTOR_PDP_EVENT_B,\r
1334                 "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,\r
1335                 "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,\r
1336                 "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,\r
1337                 '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,\r
1338             );\r
1339         \r
1340         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_LIST] = array("</ul>","</ol>");\r
1341 ##########################\r
1342 \r
1343         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_SIMLIST] = \r
1344             array(\r
1345                 "<code>"    => PHPDOCUMENTOR_PDP_EVENT_CODE,\r
1346                 "<pre>"    => PHPDOCUMENTOR_PDP_EVENT_PRE,\r
1347                 "<p>" => PHPDOCUMENTOR_PDP_EVENT_P,\r
1348                 "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,\r
1349                 "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,\r
1350                 "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,\r
1351                 "<b>" => PHPDOCUMENTOR_PDP_EVENT_B,\r
1352                 "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,\r
1353                 "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,\r
1354                 '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,\r
1355             );\r
1356 ##########################\r
1357         \r
1358         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_DOUBLECR] =\r
1359             array(\r
1360                 "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,\r
1361                 "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1362                 "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1363                 "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,\r
1364                 "<b>" => PHPDOCUMENTOR_PDP_EVENT_B,\r
1365                 "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,\r
1366                 "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,\r
1367                 "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,\r
1368                 "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,\r
1369                 "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,\r
1370                 "<p>" => PHPDOCUMENTOR_PDP_EVENT_P,\r
1371                 '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,\r
1372             );\r
1373         \r
1374 ##########################\r
1375         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_B] =\r
1376             array(\r
1377                 "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,\r
1378                 "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1379                 "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1380                 "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,\r
1381                 "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,\r
1382                 "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,\r
1383                 "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,\r
1384                 "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,\r
1385                 '<i>' => PHPDOCUMENTOR_PDP_EVENT_I,\r
1386                 '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,\r
1387             );\r
1388          \r
1389         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_B] = array("</b>");\r
1390 \r
1391 ##########################\r
1392         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_I] =\r
1393             array(\r
1394                 "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,\r
1395                 "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1396                 "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1397                 "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,\r
1398                 "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,\r
1399                 "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,\r
1400                 "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,\r
1401                 "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,\r
1402                 '<b>' => PHPDOCUMENTOR_PDP_EVENT_B,\r
1403                 '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,\r
1404             );\r
1405          \r
1406         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_I] = array("</i>");\r
1407 \r
1408 ##########################\r
1409         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_VAR] =\r
1410             array(\r
1411                 "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,\r
1412                 "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1413                 "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1414                 "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,\r
1415                 "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,\r
1416                 "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,\r
1417                 "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,\r
1418                 "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,\r
1419                 '<b>' => PHPDOCUMENTOR_PDP_EVENT_B,\r
1420                 '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,\r
1421             );\r
1422          \r
1423         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_VAR] = array("</var>");\r
1424 \r
1425 ##########################\r
1426         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_SAMP] =\r
1427             array(\r
1428                 "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,\r
1429                 "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1430                 "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1431                 "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,\r
1432                 "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,\r
1433                 "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,\r
1434                 "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,\r
1435                 "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,\r
1436                 '<b>' => PHPDOCUMENTOR_PDP_EVENT_B,\r
1437                 '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,\r
1438             );\r
1439          \r
1440         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_SAMP] = array("</samp>");\r
1441 \r
1442 ##########################\r
1443         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_KBD] =\r
1444             array(\r
1445                 "<code" => PHPDOCUMENTOR_PDP_EVENT_CODE,\r
1446                 "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1447                 "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,\r
1448                 "<pre" => PHPDOCUMENTOR_PDP_EVENT_PRE,\r
1449                 "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,\r
1450                 "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,\r
1451                 "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,\r
1452                 "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,\r
1453                 '<b>' => PHPDOCUMENTOR_PDP_EVENT_B,\r
1454                 '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,\r
1455             );\r
1456          \r
1457         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_KBD] = array("</kbd>");\r
1458     }\r
1459     \r
1460     function getParserEventName ($value)\r
1461     {    \r
1462         $lookup = array(\r
1463             PARSER_EVENT_NOEVENTS         => "PARSER_EVENT_NOEVENTS",\r
1464             PHPDOCUMENTOR_PDP_EVENT_CODE        => "PHPDOCUMENTOR_PDP_EVENT_CODE",\r
1465             PHPDOCUMENTOR_PDP_EVENT_P        => "PHPDOCUMENTOR_PDP_EVENT_P",\r
1466             PHPDOCUMENTOR_PDP_EVENT_B        => "PHPDOCUMENTOR_PDP_EVENT_B",\r
1467             PHPDOCUMENTOR_PDP_EVENT_I        => "PHPDOCUMENTOR_PDP_EVENT_I",\r
1468             PHPDOCUMENTOR_PDP_EVENT_BR        => "PHPDOCUMENTOR_PDP_EVENT_BR",\r
1469             PHPDOCUMENTOR_PDP_EVENT_VAR        => "PHPDOCUMENTOR_PDP_EVENT_VAR",\r
1470             PHPDOCUMENTOR_PDP_EVENT_SAMP        => "PHPDOCUMENTOR_PDP_EVENT_SAMP",\r
1471             PHPDOCUMENTOR_PDP_EVENT_KBD        => "PHPDOCUMENTOR_PDP_EVENT_KBD",\r
1472             PHPDOCUMENTOR_PDP_EVENT_ESCAPE        => "PHPDOCUMENTOR_PDP_EVENT_ESCAPE",\r
1473             PHPDOCUMENTOR_PDP_EVENT_ESCAPE_CODE        => "PHPDOCUMENTOR_PDP_EVENT_ESCAPE_CODE",\r
1474             PHPDOCUMENTOR_PDP_EVENT_ESCAPE_PRE        => "PHPDOCUMENTOR_PDP_EVENT_ESCAPE_PRE",\r
1475             PHPDOCUMENTOR_PDP_EVENT_DOUBLECR        => "PHPDOCUMENTOR_PDP_EVENT_DOUBLECR",\r
1476             PHPDOCUMENTOR_PDP_EVENT_LIST    => "PHPDOCUMENTOR_PDP_EVENT_LIST",\r
1477             PHPDOCUMENTOR_PDP_EVENT_PRE => "PHPDOCUMENTOR_PDP_EVENT_PRE",\r
1478             PHPDOCUMENTOR_PDP_EVENT_SIMLIST => "PHPDOCUMENTOR_PDP_EVENT_SIMLIST",\r
1479         );\r
1480         if (isset($lookup[$value]))\r
1481         return $lookup[$value];\r
1482         else return $value;\r
1483     }\r
1484 }\r
1485 \r
1486 ?>\r