Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * tokenizer extension-based parser for PHP code
4
 *
5
 * phpDocumentor :: automatic documentation generator
6
 *
7
 * PHP versions 4 and 5
8
 *
9
 * Copyright (c) 2002-2008 Gregory Beaver
10
 *
11
 * LICENSE:
12
 *
13
 * This library is free software; you can redistribute it
14
 * and/or modify it under the terms of the GNU Lesser General
15
 * Public License as published by the Free Software Foundation;
16
 * either version 2.1 of the License, or (at your option) any
17
 * later version.
18
 *
19
 * This library is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22
 * Lesser General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Lesser General Public
25
 * License along with this library; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
 *
28
 * @category   ToolsAndUtilities
29
 * @package    phpDocumentor
30
 * @subpackage Parsers
31
 * @author     Gregory Beaver <cellog@php.net>
32
 * @copyright  2002-2008 Gregory Beaver
33
 * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL
34
 * @version    CVS: $Id: phpDocumentorTParser.inc 286921 2009-08-08 05:01:24Z ashnazg $
35
 * @link       http://www.phpdoc.org
36
 * @link       http://pear.php.net/PhpDocumentor
37
 * @since      1.2
38
 * @todo       CS cleanup - change package to PhpDocumentor
39
 */
40
 
41
/**
42
 * Tokenizer-based parser for PHP source code
43
 *
44
 * @category   ToolsAndUtilities
45
 * @package    phpDocumentor
46
 * @subpackage Parsers
47
 * @author     Gregory Beaver <cellog@php.net>
48
 * @copyright  2002-2008 Gregory Beaver
49
 * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL
50
 * @version    Release: 1.4.3
51
 * @link       http://www.phpdoc.org
52
 * @link       http://pear.php.net/PhpDocumentor
53
 * @todo       CS cleanup - change package to PhpDocumentor
54
 * @todo       CS cleanup - change classname to PhpDocumentor_*
55
 */
56
class phpDocumentorTParser extends Parser
57
{
58
    /**#@+
59
     * @access private
60
     */
61
    /**
62
     * @var EventStack
63
     */
64
    var $_event_stack;
65
    /**
66
     * last event triggered before the current event
67
     * @var integer
68
     */
69
    var $_last_pevent;
70
    /**
71
     * last word parsed
72
     * @var integer
73
     */
74
    var $_last_word;
75
    /**
76
     * full path of the currently parsed file
77
     * @var string
78
     */
79
    var $_path;
80
    /**#@-*/
81
 
82
    /**#@+
83
     * Parser Variables
84
     * @access private
85
     */
86
    var $_pv_class;
87
    var $_pv_cur_class;
88
    var $_pv_define;
89
    var $_pv_define_name;
90
    var $_pv_define_value;
91
    var $_pv_define_params_data;
92
    var $_pv_dtype;
93
    var $_pv_docblock;
94
    var $_pv_dtemplate;
95
    var $_pv_func;
96
    var $_pv_func_param;
97
    var $_pv_findglobal;
98
    var $_pv_global_name;
99
    var $_pv_global_val;
100
    var $_pv_globals;
101
    var $_pv_global_count;
102
    var $_pv_include_params_data;
103
    var $_pv_include_name;
104
    var $_pv_include_value;
105
    var $_pv_linenum;
106
    var $_pv_periodline;
107
    var $_pv_paren_count = 0;
108
    var $_pv_statics;
109
    var $_pv_static_count;
110
    var $_pv_static_val;
111
    var $_pv_quote_data;
112
    var $_pv_function_data;
113
    var $_pv_var;
114
    var $_pv_varname;
115
    var $_pv_var_value;
116
    /**#@-*/
117
 
118
    /**#@+
119
     * Parser Flags
120
     * @access private
121
     */
122
    var $_pf_definename_isset = false;
123
    var $_pf_includename_isset = false;
124
    var $_pf_get_source = false;
125
    var $_pf_getting_source = false;
126
    var $_pf_internal = false;
127
    var $_pf_in_class = false;
128
    var $_pf_in_define = false;
129
    var $_pf_in_global = false;
130
    var $_pf_in_include = false;
131
    var $_pf_in_include_value = false;
132
    var $_pf_in_var = false;
133
    var $_pf_interface = false;
134
    var $_pf_funcparam_val = false;
135
    var $_pf_quote_active = false;
136
    var $_pf_reset_quote_data = true;
137
    var $_pf_useperiod = false;
138
    var $_pf_set_var_value = false;
139
    var $_pf_var_equals = false;
140
    /**#@-*/
141
 
142
    /**
143
     * relative path of the parsed file from the base parse directory
144
     * @var string
145
     */
146
    var $source_location;
147
    var $eventHandlers = array(
148
        PARSER_EVENT_ARRAY                      => 'handleArray',
149
        PARSER_EVENT_VAR_ARRAY                  => 'handleArray',
150
        PARSER_EVENT_VAR_ARRAY_COMMENT          => 'handleVarArrayComment',
151
        PARSER_EVENT_CLASS                      => 'handleClass',
152
        PARSER_EVENT_COMMENT                    => 'handleComment',
153
        PARSER_EVENT_DOCBLOCK_TEMPLATE          => 'handleDocBlockTemplate',
154
        PARSER_EVENT_END_DOCBLOCK_TEMPLATE      => 'handleEndDocBlockTemplate',
155
        PARSER_EVENT_LOGICBLOCK                 => 'handleLogicBlock',
156
        PARSER_EVENT_NOEVENTS                   => 'defaultHandler',
157
        PARSER_EVENT_OUTPHP                     => 'defaultHandler',
158
        PARSER_EVENT_DEFINE                     => 'handleDefine',
159
        PARSER_EVENT_DEFINE_PARAMS              => 'handleDefineParams',
160
        PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS  => 'handleDefineParamsParenthesis',
161
        PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS => 'handleIncludeParamsParenthesis',
162
        PARSER_EVENT_DOCBLOCK                   => 'handleDocBlock',
163
        PARSER_EVENT_TAGS                       => 'handleTags',
164
        PARSER_EVENT_DESC                       => 'handleDesc',
165
        PARSER_EVENT_DOCKEYWORD                 => 'handleTag',
166
        PARSER_EVENT_DOCKEYWORD_EMAIL           => 'handleDockeywordEmail',
167
        PARSER_EVENT_EOFQUOTE                   => 'handleHereDoc',
168
        PARSER_EVENT_FUNCTION                   => 'handleFunction',
169
        PARSER_EVENT_FUNCTION_PARAMS            => 'handleFunctionParams',
170
        PARSER_EVENT_FUNCTION_PARAM_VAR         => 'handleFunctionParams',
171
        PARSER_EVENT_FUNC_GLOBAL                => 'handleFuncGlobal',
172
        PARSER_EVENT_DEFINE_GLOBAL              => 'handleGlobal',
173
        PARSER_EVENT_GLOBAL_VALUE               => 'handleGlobalValue',
174
        PARSER_EVENT_INLINE_DOCKEYWORD          => 'handleInlineDockeyword',
175
        PARSER_EVENT_INCLUDE                    => 'handleInclude',
176
        PARSER_EVENT_INCLUDE_PARAMS             => 'handleIncludeParams',
177
        PARSER_EVENT_QUOTE                      => 'handleQuote',
178
        PARSER_EVENT_PHPCODE                    => 'handlePhpCode',
179
        PARSER_EVENT_SINGLEQUOTE                => 'handleSingleQuote',
180
        PARSER_EVENT_STATIC_VAR                 => 'handleStaticVar',
181
        PARSER_EVENT_STATIC_VAR_VALUE           => 'handleStaticValue',
182
        PARSER_EVENT_VAR                        => 'handleVar',
183
        PARSER_EVENT_ACCESS_MODIFIER            => 'handleAccessModifier',
184
        PARSER_EVENT_IMPLEMENTS                 => 'handleImplements',
185
        PARSER_EVENT_CLASS_CONSTANT             => 'handleClassConstant',
186
    );
187
 
188
    var $inlineTagHandlers = array(
189
        '*'    => 'handleDefaultInlineTag',
190
        'link' => 'handleLinkInlineTag',
191
    );
192
 
193
    /**
194
     * Constructor
195
     *
196
     */
197
    function phpDocumentorTParser()
198
    {
199
        $this->allowableTags
200
            = $GLOBALS['_phpDocumentor_tags_allowed'];
201
        $this->allowableInlineTags
202
            = $GLOBALS['_phpDocumentor_inline_doc_tags_allowed'];
203
        $this->subscribe(PHPDOCUMENTOR_EVENT_NEWLINENUM,
204
            $GLOBALS['phpDocumentor_errors']);
205
        $this->subscribe(PHPDOCUMENTOR_EVENT_NEWFILE,
206
            $GLOBALS['phpDocumentor_errors']);
207
        $this->tagHandlers['author']     = 'authorTagHandler';
208
        $this->tagHandlers['filesource'] = 'filesourceTagHandler';
209
        $this->setupEventStates();
210
    }
211
 
212
    /**
213
     * Parse a new file
214
     *
215
     * @param string &$parse_data the parse data
216
     * @param string $path        the path
217
     * @param int    $base        number of directories to drop off the bottom
218
     *                            when creating names using path
219
     * @param bool   $packages    ???
220
     *
221
     * @staticvar int used for recursion limiting
222
     *                if a handler for an event is not found
223
     * @return bool
224
     */
225
    function parse (&$parse_data, $path, $base = 0, $packages = false)
226
    {
227
        global $_phpDocumentor_options;
228
        static $endrecur = 0;
229
 
230
        $this->setupStates();
231
        if (strlen($parse_data) == 0) {
232
            return false;
233
        }
234
 
235
        $this->configWordParser($parse_data);
236
        // initialize variables so E_ALL error_reporting doesn't complain
237
        $pevent = 0;
238
        $word   = 0;
239
 
240
        $page = new ParserPage;
241
        $page->setSource($this->_wp->getFileSource());
242
        $page->setPath($path);
243
        $this->_path = $path;
244
        $page->setPackageOutput($packages);
245
        $page->setFile(basename($path));
246
        $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWFILE, basename($path));
247
        //$name = str_replace("/","_",dirname($path)) . "_"
248
        //    . array_shift(explode(".",$page->getFile()));
249
        // fc@fc.clever-soft.com 11/29/2001
250
        $name = str_replace(':', '', dirname($path)
251
            . PATH_DELIMITER . $page->getFile());
252
        $tmp  = explode(PATH_DELIMITER, $name);
253
        $name = implode("---", array_slice($tmp, $base));
254
        // if base is '', drive letter is present in windows
255
 
256
        $page->setName($name);
257
        $temploc = $_phpDocumentor_options['Program_Root']
258
            . PATH_DELIMITER . implode(PATH_DELIMITER,
259
            array_slice(explode(PATH_DELIMITER, $path), $base));
260
 
261
        if ($temploc == $_phpDocumentor_options['Program_Root'] . PATH_DELIMITER) {
262
            $temploc .= $path;
263
        }
264
 
265
        $this->source_location = $source_location = $temploc;
266
        $page->setSourceLocation($source_location);
267
 
268
        $this->publishEvent(PHPDOCUMENTOR_EVENT_PAGE, $page);
269
        unset($page);
270
        do {
271
            $lpevent = $pevent;
272
            $pevent  = $this->_event_stack->getEvent();
273
            if ($lpevent != $pevent) {
274
                $this->_last_pevent = $lpevent;
275
            }
276
 
277
            $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE, ($pevent + 100));
278
 
279
            $this->_pv_last_word = $word;
280
 
281
            $word = $this->_wp->getWord();
282
            if (isset($this->_pv_findglobal) && $word == $this->_pv_findglobal) {
283
                $this->_last_pevent = $pevent;
284
 
285
                $this->_event_stack->pushEvent($pevent = PARSER_EVENT_DEFINE_GLOBAL);
286
            }
287
            // in wordparser, have to keep track of lines
288
            $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWLINENUM, $this->_wp->linenum);
289
            if ($this->_pf_get_source) {
290
                if ($word[0] == T_FUNCTION) {
291
                    $this->_wp->retrievesource($word);
292
                    $this->_pf_get_source     = false;
293
                    $this->_pf_getting_source = true;
294
                }
295
            }
296
 
297
            if (PHPDOCUMENTOR_DEBUG == true) {
298
                echo "LAST: ";
299
                if (is_array($this->_pv_last_word)) {
300
                    echo token_name($this->_pv_last_word[0]) . ' => |'
301
                        . htmlspecialchars($this->_pv_last_word[1]);
302
                } else {
303
                    echo "|" . $this->_pv_last_word;
304
                }
305
                echo "|\n";
306
                echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";
307
                echo "LASTPEVENT: "
308
                    . $this->getParserEventName($this->_last_pevent) . "\n";
309
                echo $this->_wp->getPos() . ": ";
310
                if (is_array($word)) {
311
                    echo token_name($word[0]) . ' => |'
312
                        . htmlspecialchars($word[1]);
313
                } else {
314
                    echo '|' . htmlspecialchars($word);
315
                }
316
                echo "|\n-------------------\n\n\n";
317
            }
318
 
319
            // $this->_pf_getting_source &&
320
            // ($pevent == PARSER_EVENT_DOCBLOCK) ||
321
            // ($pevent == PARSER_EVENT_NOEVENTS))
322
            if (0) {
323
                addError(PDERROR_SOURCE_TAG_FUNCTION_NOT_FOUND);
324
                // throw away source
325
                $this->_wp->getSource();
326
            }
327
            if (isset($this->eventHandlers[$pevent])) {
328
                $handle = $this->eventHandlers[$pevent];
329
                $this->$handle($word, $pevent);
330
            } else {
331
                debug('WARNING: possible error, no handler for event number '
332
                    . $pevent);
333
                if ($endrecur++ == 25) {
334
                    die("FATAL ERROR, recursion limit reached");
335
                }
336
            }
337
        } while (!($word === false));
338
        $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,
339
            PHPDOCUMENTOR_EVENT_END_PAGE);
340
    }
341
 
342
    /**#@+
343
     * @param string $word   the string word
344
     * @param int    $pevent the token constant
345
     * @access private
346
     * @return void
347
     */
348
 
349
    /**
350
     * handler for COMMENT
351
     */
352
    function handleComment($word, $pevent)
353
    {
354
        $this->_wp->backupPos();
355
        $this->_event_stack->popEvent();
356
    }
357
 
358
    /**
359
     * handler for PHPCODE.
360
     *
361
     * this handler recognizes the <code><?</code> php processor directive,
362
     * and begins parsing php code
363
     */
364
    function handlePhpCode($word, $pevent)
365
    {
366
        $e = $this->checkEventPush($word, $pevent);
367
        if (isset($this->_pv_findglobal) && $e) {
368
            if ($e != PARSER_EVENT_DEFINE_GLOBAL
369
                && $e != PARSER_EVENT_ARRAY
370
                && $e != PARSER_EVENT_QUOTE
371
                && $e != PARSER_EVENT_SINGLEQUOTE
372
                && $e != PARSER_EVENT_COMMENT
373
                && $e != PARSER_EVENT_COMMENTBLOCK
374
            ) {
375
                addError(PDERROR_GLOBAL_NOT_FOUND, $this->_pv_findglobal);
376
                $this->_wp->findGlobal(false);
377
                unset($this->_pv_findglobal);
378
            }
379
        }
380
    }
381
 
382
    /**
383
     * handler for FUNC_GLOBAL.
384
     *
385
     * this handler recognizes "global $var1, $var2" declarations in a function,
386
     * and parses them
387
     */
388
    function handleFuncGlobal($word, $pevent)
389
    {
390
        if ($this->checkEventPop($word, $pevent)) {
391
            return;
392
        }
393
        if (!$this->checkEventPush($word, $pevent)) {
394
            if ($word == ',') {
395
                // another variable
396
                $this->_pv_global_count++;
397
            } else {
398
                if (!isset($this->_pv_globals[$this->_pv_global_count])) {
399
                    $this->_pv_globals[$this->_pv_global_count] = '';
400
                }
401
 
402
                // if (!empty($this->_pv_globals[$this->_pv_global_count])) {
403
                //     $this->_pv_global_count++;
404
                // }
405
 
406
                if (is_array($word)) {
407
                    $word = $word[1];
408
                }
409
                $this->_pv_globals[$this->_pv_global_count] .= $word;
410
            }
411
        }
412
    }
413
 
414
    /**
415
     * handler for DEFINE_GLOBAL
416
     */
417
    function handleGlobal($word, $pevent)
418
    {
419
        if (isset($this->_pv_findglobal)) {
420
            $this->_pv_global_name = $this->_pv_findglobal;
421
            unset($this->_pv_findglobal);
422
        }
423
        if (!$this->_pf_in_global) {
424
            $this->_pv_linenum = $this->_wp->linenum + 1;
425
        }
426
        $this->_pf_in_global = true;
427
        if ($this->checkEventPush($word, $pevent)) {
428
            $this->_wp->setWhitespace(true);
429
        }
430
        if ($this->checkEventPop($word, $pevent)) {
431
            $this->_pf_in_global = false;
432
            $a                   = new parserGlobal;
433
            $a->setDataType($this->_pv_global_type);
434
            $this->_pv_global_type = '';
435
            $a->setLineNumber($this->_pv_linenum);
436
            $a->setName($this->_pv_global_name);
437
            if (isset($this->_pv_global_val)) {
438
                $a->setValue(trim($this->_pv_global_val));
439
            }
440
            $this->publishEvent(PHPDOCUMENTOR_EVENT_GLOBAL, $a);
441
            unset($this->_pv_global_val);
442
            unset($this->_pv_global_type);
443
        }
444
    }
445
 
446
    /**
447
     * handler for GLOBAL_VALUE
448
     */
449
    function handleGlobalValue($word, $pevent)
450
    {
451
        if ($this->checkEventPush($word, $pevent)) {
452
            return;
453
        }
454
        $this->_wp->setWhitespace(true);
455
        if (!isset($this->_pv_global_val)) {
456
            $this->_pv_global_val = '';
457
        }
458
        if ($this->_last_pevent == PARSER_EVENT_ARRAY) {
459
            $this->_pv_global_val   .= $this->_pv_function_data;
460
            $this->_pv_function_data = '';
461
        }
462
        if ($this->_last_pevent == PARSER_EVENT_QUOTE ||
463
            $this->_last_pevent == PARSER_EVENT_EOFQUOTE
464
        ) {
465
            $this->_pv_global_val .= $this->_pv_quote_data;
466
            unset($this->_pv_quote_data);
467
        }
468
        if ($this->checkEventPop($word, $pevent)) {
469
            $this->_wp->setWhitespace(false);
470
            $this->_wp->backupPos();
471
            return;
472
        }
473
        if (is_array($word)) {
474
            $word = $word[1];
475
        }
476
        $this->_pv_global_val .= $word;
477
    }
478
 
479
    /**
480
     * handler for STATIC_VAR.
481
     *
482
     * this handler recognizes "static $var1,
483
     * $var2 = 6" declarations in a function,
484
     * and parses them
485
     */
486
    function handleStaticVar($word, $pevent)
487
    {
488
        if ($this->checkEventPop($word, $pevent)) {
489
            $this->_pv_static_count++;
490
            return;
491
        }
492
        if (!$this->checkEventPush($word, $pevent)) {
493
            if ($word == ',') {
494
                $this->_pv_static_count++;
495
                return;
496
            }
497
            if (!isset($this->_pv_statics[$this->_pv_static_count])) {
498
                $this->_pv_statics[$this->_pv_static_count] = '';
499
            }
500
            if (!empty($this->_pv_statics[$this->_pv_static_count])) {
501
                $this->_pv_static_count++;
502
            }
503
            if (is_array($word)) {
504
                $word = $word[1];
505
            }
506
            $this->_pv_statics[$this->_pv_static_count] = $word;
507
        }
508
    }
509
 
510
    /**
511
     * handler for STATIC_VAR_VALUE.
512
     *
513
     * this handler parses the 6 in "static $var1, $var2 = 6"
514
     */
515
    function handleStaticValue($word, $pevent)
516
    {
517
        if ($this->checkEventPush($word, $pevent)) {
518
            return;
519
        }
520
        if (!isset($this->_pv_static_val[$this->_pv_static_count])) {
521
            $this->_pv_static_val[$this->_pv_static_count] = '';
522
        }
523
        if ($this->_last_pevent == PARSER_EVENT_QUOTE) {
524
            $this->_pv_static_val[$this->_pv_static_count]
525
                .= $this->_pv_quote_data;
526
            unset($this->_pv_quote_data);
527
        }
528
        if ($this->_last_pevent == PARSER_EVENT_ARRAY) {
529
            $this->_pv_static_val[$this->_pv_static_count]
530
                .= $this->_pv_function_data;
531
            $this->_pv_function_data = '';
532
        }
533
        if ($this->checkEventPop($word, $pevent)) {
534
            $this->_pv_static_val[$this->_pv_static_count]
535
                = trim($this->_pv_static_val[$this->_pv_static_count]);
536
            $this->_wp->backupPos($word);
537
            return;
538
        } else {
539
            if (is_array($word)) $word = $word[1];
540
            $this->_pv_static_val[$this->_pv_static_count] .= $word;
541
        }
542
    }
543
 
544
    /**
545
     * handler for LOGICBLOCK
546
     *
547
     * Logic Blocks are the stuff between { and } in a function/method.  A
548
     * logic block can clearly contain other logic blocks, as in:
549
     *
550
     * <code>
551
     * function test($a)
552
     * {
553
     *    if (testcondition)
554
     *    { // nested logic block
555
     *    }
556
     * }
557
     * </code>
558
     *
559
     * So, the exit portion of the logic block handler must check to see if the
560
     * logic block being exited is the top-level, and it does this by retrieving
561
     * the last event from the stack.  If it is a function (and not a logic block)
562
     * then it backs up the word parser so that the function will exit properly.
563
     *
564
     * {@source 11}
565
     */
566
    function handleLogicBlock($word, $pevent)
567
    {
568
        $a = $this->checkEventPush($word, $pevent);
569
        if ($this->checkEventPop($word, $pevent)) {
570
            $e = $this->_event_stack->popEvent();
571
            $this->_event_stack->pushEvent($e);
572
            if ($e == PARSER_EVENT_FUNCTION) {
573
                $this->_wp->backupPos();
574
            }
575
        }
576
    }
577
 
578
    /**
579
     * handler for FUNCTION.
580
     *
581
     * this handler recognizes function declarations, and parses them.  The body
582
     * of the function is parsed by handleLogicBlock()
583
     *
584
     * @see handleLogicBlock()
585
     */
586
    function handleFunction($word, $pevent)
587
    {
588
        if ($e = $this->checkEventPush($word, $pevent)) {
589
            $this->_pv_function_data = '';
590
            if ($e == PARSER_EVENT_FUNCTION_PARAMS && !is_object($this->_pv_func)
591
            ) {
592
                addErrorDie(PDERROR_FUNCTION_HAS_NONAME);
593
            }
594
            if ($e == PARSER_EVENT_COMMENT || $e == PARSER_EVENT_COMMENTBLOCK ||
595
                $e == PARSER_EVENT_FUNCTION_PARAMS || $e == PARSER_EVENT_LOGICBLOCK
596
            ) {
597
                return;
598
            }
599
        }
600
 
601
        if (!isset($this->_pv_func)) {
602
            $this->_pv_func = false;
603
        }
604
        if (! is_object($this->_pv_func)) {
605
            $this->_pv_globals      = array();
606
            $this->_pv_global_count = $this->_pv_static_count = 0;
607
            if ($this->_pf_in_class) {
608
                $this->_pv_func = new parserMethod($this->_pv_cur_class);
609
            } else {
610
                $this->_pv_func = new parserFunction;
611
                unset($this->_accessModifiers);
612
            }
613
            if (isset($this->_accessModifiers)) {
614
                $this->_pv_func->setModifiers($this->_accessModifiers);
615
                unset($this->_accessModifiers);
616
            }
617
            $this->_pv_func->setLineNumber($this->_wp->linenum + 1);
618
            if (is_string($word) && $word == '&') {
619
                $this->_pv_func->setReturnsReference();
620
            }
621
            if (is_array($word) && $word[0] == T_STRING) {
622
                $this->_pv_func->setName($word[1]);
623
            }
624
        } else {
625
            if ($this->_pv_func->getReturnsReference()) {
626
                if (is_array($word) && $word[0] == T_STRING) {
627
                    $this->_pv_func->setName($word[1]);
628
                }
629
            }
630
        }
631
        if ($this->checkEventPop($word, $pevent)) {
632
            $this->_pv_func->setEndLineNumber($this->_wp->linenum + 1);
633
            $this->_pv_func->addGlobals($this->_pv_globals);
634
            $this->_pv_func->addStatics($this->_pv_statics, $this->_pv_static_val);
635
            $this->_pv_globals      = array();
636
            $this->_pv_global_count = 0;
637
            if ($this->_pf_getting_source) {
638
                $x = $this->_wp->getSource();
639
                $this->_pv_func->addSource($x);
640
                $this->_pf_get_source     = false;
641
                $this->_pf_getting_source = false;
642
            }
643
            $this->publishEvent(PHPDOCUMENTOR_EVENT_FUNCTION, $this->_pv_func);
644
            $this->_pv_func = false;
645
 
646
            // subtle bug fixed by this, sometimes string from function body
647
            unset($this->_pv_quote_data); // was picked up by the next function
648
                                          // as a default value for a parameter!
649
        }
650
    }
651
 
652
    /**
653
     * handler for FUNCTION_PARAMS.
654
     *
655
     * this handler recognizes the parameters of a function within parentheses
656
     * like function(param, param = default_value) and parses them
657
     *
658
     * @see endFunctionParam()
659
     */
660
    function handleFunctionParams($word, $pevent)
661
    {
662
        //echo $this->_wp->getPos() . ": word=|$word|\t\t\tlastword=|"
663
        //    . $this->_pv_last_word."|\n";
664
        //echo "function_param = '".$this->_pv_function_param."'\n";
665
        //echo "function_data = '".$this->_pv_function_data."'\n";
666
        $e1 = $this->checkEventPush($word, $pevent);
667
 
668
        if (!$e1) {
669
            if (($pop = $this->checkEventPop($word, $pevent)) &&
670
                $pevent == PARSER_EVENT_FUNCTION_PARAM_VAR
671
            ) {
672
                // end of [typehint ]$param[= defaultval]
673
                if (is_string($word) && $word == ')') {
674
                    $this->_wp->backupPos();
675
                }
676
                $this->endFunctionParam($word);
677
            } elseif ($word == '=') {
678
                // about to parse the default value
679
                $this->_pf_funcparam_val = true;
680
            } else {
681
                if ($this->_pf_funcparam_val) {
682
                    // parsing default value
683
                    if (isset($this->_pv_quote_data)) {
684
                        $this->_pv_function_data .= $this->_pv_quote_data;
685
                        unset($this->_pv_quote_data);
686
                    }
687
                    if (is_array($word)) {
688
                        $word = $word[1];
689
                    }
690
                    $this->_pv_function_data .= $word;
691
                } else {
692
                    // pre-param
693
                    if ($pop) {
694
                        return;
695
                    }
696
                    if (!isset($this->_pv_function_param)) {
697
                        $this->_pv_function_param = '';
698
                    }
699
                    if (is_array($word) && $pevent == PARSER_EVENT_FUNCTION_PARAMS
700
                    ) {
701
                        if ($word[0] == T_STRING || $word[0] == T_ARRAY) {
702
                            // object or array type hint
703
                            $this->_pv_function_param_type = $word[1];
704
                            return;
705
                        }
706
                        $word = $word[1];
707
                    }
708
                    $this->_pv_function_param .= $word;
709
                }
710
            }
711
        } elseif ($e1 == PARSER_EVENT_ARRAY) {
712
            $this->_wp->setWhiteSpace(true);
713
        } elseif ($e1 == PARSER_EVENT_FUNCTION_PARAM_VAR) {
714
            if (!isset($this->_pv_function_param)) {
715
                $this->_pv_function_param = '';
716
            }
717
            // we just got the $var part of the param
718
            $this->_pv_function_param .= $word[1];
719
        }
720
    }
721
 
722
    /**
723
     * handler for ARRAY.
724
     *
725
     * this event handler parses arrays in default values of function
726
     * and var definitions
727
     */
728
    function handleArray($word, $pevent)
729
    {
730
        $e = $this->checkEventPush($word, $pevent);
731
        if ($e) {
732
            return;
733
        }
734
 
735
        if (!isset($this->_pv_function_data) ||
736
            (isset($this->_pv_function_data) && empty($this->_pv_function_data))
737
        ) {
738
            $this->_pv_function_data = "array";
739
        }
740
 
741
        if ($word == '(' && $this->_pv_paren_count++) {
742
            // need extra parentheses help
743
            $this->_event_stack->pushEvent($pevent);
744
        }
745
        if (is_array($word)) {
746
            $this->_pv_function_data .= $word[1];
747
        } else {
748
            $this->_pv_function_data .= $word;
749
        }
750
        //echo "function_data = |$this->_pv_function_data|\n";
751
 
752
        if ($this->checkEventPop($word, $pevent)) {
753
            $this->_pv_paren_count--;
754
            $this->_wp->setWhiteSpace(false);
755
        }
756
    }
757
 
758
    /**
759
     * handler for HEREDOC in a function logic block.
760
     *
761
     * this handler recognizes function declarations, and parses them.  The body
762
     * of the function is parsed by handleLogicBlock()
763
     *
764
     * @see handleLogicBlock()
765
     */
766
    function handleHereDoc($word, $pevent)
767
    {
768
        if (is_array($this->_pv_last_word) &&
769
            $this->_pv_last_word[0] == T_START_HEREDOC
770
        ) {
771
            $save = $word;
772
            if (is_array($word)) {
773
                $word = $word[1];
774
            }
775
            $this->_pv_quote_data   = $this->_pv_last_word[1] . $word;
776
            $this->_pf_quote_active = true;
777
        } elseif (!$this->_pf_quote_active) {
778
            $this->_pv_quote_data = $this->_pv_last_word[1];
779
            $this->_event_stack->popEvent();
780
            $this->_wp->backupPos();
781
            return;
782
        }
783
        $save = $word;
784
        if (is_array($word)) {
785
            $word = $word[1];
786
        }
787
        $this->_pv_quote_data .= $word;
788
        if ($this->checkEventPop($save, $pevent)) {
789
            $this->_pf_quote_active = false;
790
        }
791
    }
792
 
793
    /**
794
     * handler for QUOTE.
795
     *
796
     * this handler recognizes strings defined with double quotation marks (")
797
     * and single quotation marks and handles them correctly
798
     * in any place that they legally appear in php code
799
     */
800
    function handleQuote($word, $pevent)
801
    {
802
        if ($this->_pv_last_word == '"' || $this->_pv_last_word == "'" &&
803
            $this->_last_pevent != PARSER_EVENT_QUOTE
804
        ) {
805
            $save = $word;
806
            if (is_array($word)) {
807
                $word = $word[1];
808
            }
809
            $this->_pv_quote_data   = $this->_pv_last_word . $word;
810
            $this->_pf_quote_active = true;
811
            $this->checkEventPop($save, $pevent);
812
        } elseif (!$this->_pf_quote_active) {
813
            $this->_pv_quote_data = $this->_pv_last_word[1];
814
            $this->_event_stack->popEvent();
815
            $this->_wp->backupPos();
816
            return;
817
        }
818
        $save = $word;
819
        if (is_array($word)) {
820
            $word = $word[1];
821
        }
822
        $this->_pv_quote_data .= $word;
823
        if ($this->checkEventPop($save, $pevent)) {
824
            $this->_pf_quote_active = false;
825
        }
826
    }
827
 
828
    /**
829
     * handler for INCLUDE.
830
     *
831
     * this handler recognizes include/require/include_once/include_once statements,
832
     * and publishes the data to Render
833
     */
834
    function handleInclude($word, $pevent)
835
    {
836
        if (!$this->_pf_in_include) {
837
            $this->_pv_linenum = $this->_wp->linenum;
838
        }
839
        $this->_pf_in_include = true;
840
 
841
        $a = $this->checkEventPush($word, $pevent);
842
        if (!$this->_pf_includename_isset) {
843
            $this->_pf_includename_isset = true;
844
 
845
            $w = $this->_pv_last_word;
846
            if (is_array($w)) {
847
                $w = $w[1];
848
            }
849
            $this->_pv_include_name = $w;
850
            if ($a) {
851
                $this->_pv_include_value = '';
852
            } else {
853
                if (is_array($word)) {
854
                    $word = $word[1];
855
                }
856
                $this->_pv_include_value = $word;
857
            }
858
            unset($this->_pv_quote_data);
859
        } else {
860
            if (!$a) {
861
                if (empty($this->_pv_include_params_data)) {
862
                    if ($word != ';') {
863
                        if (is_array($word)) $word = $word[1];
864
                        $this->_pv_include_value .= $word;
865
                    }
866
                }
867
            } else {
868
                if ($this->_pf_in_include_value && $a == PARSER_EVENT_INCLUDE_PARAMS
869
                ) {
870
                    /* we're already inside the include value,
871
                     * so an open paren does NOT mean the beginning
872
                     * of "include parameters"...
873
                     * it's just a part of the include's value string...
874
                     * but we've already pushed PARSER_EVENT_INCLUDE_PARAMS
875
                     * onto the stack...
876
                     * we need to pop it off
877
                     * before handleIncludeParams gets called...
878
                     */
879
                    $this->_event_stack->popEvent();
880
                    // also need to keep that open parens...
881
                    $this->_pv_include_value .= $word;
882
                }
883
                $this->_pv_include_params_data = '';
884
            }
885
        }
886
 
887
        if (!empty($this->_pv_include_value)) {
888
            $this->_pf_in_include_value = true;
889
        }
890
 
891
        if ($this->checkEventPop($word, $pevent)) {
892
            $this->_pv_include = new parserInclude;
893
            $this->_pv_include->setLineNumber($this->_pv_linenum + 1);
894
            $this->_pf_in_include = false;
895
            $this->_pv_include->setName($this->_pv_include_name);
896
            $this->_pv_include->setValue($this->_pv_include_value);
897
            $this->publishEvent(PHPDOCUMENTOR_EVENT_INCLUDE, $this->_pv_include);
898
            $this->_pf_includename_isset = false;
899
            $this->_pf_in_include_value  = false;
900
            unset($this->_pv_include);
901
            unset($this->_pv_include_name);
902
            unset($this->_pv_include_value);
903
            unset($this->_pv_include_params_data);
904
        } elseif ($this->_last_pevent == PARSER_EVENT_INCLUDE_PARAMS) {
905
            // include is part of a larger statement
906
            // force ending of include
907
            $this->_event_stack->popEvent();
908
            $this->_pv_include = new parserInclude;
909
            $this->_pv_include->setLineNumber($this->_pv_linenum + 1);
910
            $this->_pf_in_include = false;
911
            $this->_pv_include->setName($this->_pv_include_name);
912
            $this->_pv_include->setValue($this->_pv_include_value);
913
            $this->publishEvent(PHPDOCUMENTOR_EVENT_INCLUDE, $this->_pv_include);
914
            $this->_pf_includename_isset = false;
915
            $this->_pf_in_include_value  = false;
916
            unset($this->_pv_include);
917
            unset($this->_pv_include_name);
918
            unset($this->_pv_include_value);
919
            unset($this->_pv_include_params_data);
920
        }
921
    }
922
 
923
    /**
924
     * handler for INCLUDE_PARAMS.
925
     *
926
     * this handler parses the contents of ( )
927
     * in include/require/include_once/include_once statements
928
     */
929
    function handleIncludeParams($word, $pevent)
930
    {
931
        $e = $this->checkEventPush($word, $pevent);
932
        if ($e == PARSER_EVENT_COMMENT) {
933
            return;
934
        }
935
 
936
        if (!isset($this->_pv_include_params_data)) {
937
            $this->_pv_include_params_data = '';
938
        }
939
 
940
        if ($this->checkEventPop($word, $pevent)) {
941
            if (!empty($this->_pv_include_params_data)) {
942
                $this->_pv_include_value = $this->_pv_include_params_data;
943
            } else {
944
                $w = $this->_pv_last_word;
945
                if (is_array($w)) {
946
                    $w = $w[1];
947
                }
948
                $this->_pv_include_value = $w;
949
            }
950
        }
951
        if (is_array($word)) {
952
            $word = $word[1];
953
        }
954
        $this->_pv_include_params_data .= $word;
955
    }
956
 
957
    /**
958
     * handler for INCLUDE_PARAMS_PARENTHESIS.
959
     *
960
     * this handler takes all parenthetical statements within file in:
961
     * include statement include(file), and handles them properly
962
     */
963
    function handleIncludeParamsParenthesis($word, $pevent)
964
    {
965
        $this->checkEventPush($word, $pevent);
966
        $this->checkEventPop($word, $pevent);
967
        if (is_array($word)) {
968
            $word = $word[1];
969
        }
970
        $this->_pv_include_params_data .= $word;
971
    }
972
 
973
    /**
974
     * handler for DEFINE.
975
     *
976
     * handles define(constant, value); statements
977
     */
978
    function handleDefine($word, $pevent)
979
    {
980
        if (!$this->_pf_in_define) {
981
            $this->_pv_linenum = $this->_wp->linenum + 1;
982
        }
983
        $this->_pf_in_define = true;
984
        $this->checkEventPush($word, $pevent);
985
 
986
        $this->_pf_definename_isset   = false;
987
        $this->_pv_define_params_data = '';
988
        unset($this->_pv_quote_data);
989
        if ($this->checkEventPop($word, $pevent)) {
990
            $this->_pf_in_define = false;
991
            $this->_pv_define    = new parserDefine;
992
            $this->_pv_define->setLineNumber($this->_pv_linenum);
993
            $this->_pv_define->setName($this->_pv_define_name);
994
            $this->_pv_define->setValue($this->_pv_define_value);
995
            $this->publishEvent(PHPDOCUMENTOR_EVENT_DEFINE, $this->_pv_define);
996
            $this->_pf_definename_isset = false;
997
            unset($this->_pv_define);
998
            unset($this->_pv_define_name);
999
            unset($this->_pv_define_value);
1000
            $this->_pf_in_define          = false;
1001
            $this->_pv_define_params_data = '';
1002
        }
1003
    }
1004
 
1005
    /**
1006
     * handler for DEFINE_PARAMS.
1007
     *
1008
     * handles the parsing of constant and value in define(constant, value);
1009
     */
1010
    function handleDefineParams($word, $pevent)
1011
    {
1012
        $e = $this->checkEventPush($word, $pevent);
1013
        if ($e && $e != PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS) {
1014
            return;
1015
        }
1016
 
1017
        if (!isset($this->_pv_define_params_data)) {
1018
            $this->_pv_define_params_data = '';
1019
        }
1020
 
1021
        if ($this->checkEventPop($word, $pevent)) {
1022
            if ($this->_last_pevent == PARSER_EVENT_QUOTE ||
1023
                $this->_last_pevent == PARSER_EVENT_EOFQUOTE
1024
            ) {
1025
                $this->_pv_define_params_data .= $this->_pv_quote_data;
1026
                unset($this->_pv_quote_data);
1027
            }
1028
            if (is_array($word)) {
1029
                $word = $word[1];
1030
            }
1031
            if (!empty($this->_pv_define_params_data)) {
1032
                //echo $this->_pv_define_params_data."\n";
1033
                $this->_pv_define_value = $this->_pv_define_params_data;
1034
            } else {
1035
                $w = $this->_pv_last_word;
1036
                if (is_array($this->_pv_last_word)) {
1037
                    $w = $this->_pv_last_word[1];
1038
                }
1039
                if (!empty($w)) {
1040
                    $this->_pv_define_value = $w;
1041
                } else {
1042
                    $this->_pv_define_value = "";
1043
                    switch ($w) {
1044
                    case 0:
1045
                        $this->_pv_define_value = "0";
1046
                        break;
1047
                    case null:
1048
                        $this->_pv_define_value = "null";
1049
                        break;
1050
                    case "":
1051
                        $this->_pv_define_value = "";
1052
                        break;
1053
                    }
1054
                }
1055
            }
1056
        }
1057
        if ($this->_pf_definename_isset) {
1058
            if (is_array($word)) {
1059
                $word = $word[1];
1060
            }
1061
            $this->_pv_define_params_data .= $word;
1062
        } else {
1063
            if ($word != ",") {
1064
                if (is_array($word)) {
1065
                    $word = $word[1];
1066
                }
1067
                $this->_pv_define_params_data .= $word;
1068
            } else {
1069
                if (substr($this->_pv_define_params_data, 0, 1) ==
1070
                    substr($this->_pv_define_params_data,
1071
                        strlen($this->_pv_define_params_data) - 1) &&
1072
                    in_array(substr($this->_pv_define_params_data,
1073
                        0, 1), array('"', "'"))
1074
                ) {
1075
                    // remove leading and ending quotation marks
1076
                    // if there are only two
1077
                    $a = substr($this->_pv_define_params_data, 0, 1);
1078
                    $b = substr($this->_pv_define_params_data, 1,
1079
                        strlen($this->_pv_define_params_data) - 2);
1080
                    if (strpos($b, $a) === false) {
1081
                        $this->_pv_define_params_data = $b;
1082
                    }
1083
                }
1084
                $this->_pf_definename_isset   = true;
1085
                $this->_pv_define_name        = $this->_pv_define_params_data;
1086
                $this->_pv_define_params_data = '';
1087
            }
1088
        }
1089
    }
1090
 
1091
    /**
1092
     * handler for DEFINE_PARAMS_PARENTHESIS.
1093
     *
1094
     * this handler takes all parenthetical statements within constant or value in:
1095
     * define(constant, value) of a define statement, and handles them properly
1096
     */
1097
    function handleDefineParamsParenthesis($word, $pevent)
1098
    {
1099
        $e = $this->checkEventPush($word, $pevent);
1100
        $this->checkEventPop($word, $pevent);
1101
        if ($this->_last_pevent == PARSER_EVENT_QUOTE) {
1102
            $this->_pv_define_params_data .= $this->_pv_quote_data;
1103
            unset($this->_pv_quote_data);
1104
        }
1105
        if (is_array($word)) {
1106
            $word = $word[1];
1107
        }
1108
        $this->_pv_define_params_data .= $word;
1109
    }
1110
 
1111
    /**
1112
     * handler for IMPLEMENTS.
1113
     *
1114
     * this handler parses a class statement's implements clause (PHP 5)
1115
     */
1116
    function handleImplements($word, $pevent)
1117
    {
1118
        if ($this->checkEventPop($word, $pevent)) {
1119
            $this->_wp->backupPos();
1120
            return;
1121
        }
1122
        if (is_array($word) && $word[0] == T_STRING) {
1123
            $this->_pv_class->addImplements($word[1]);
1124
        }
1125
    }
1126
 
1127
    /**
1128
     * handler for ACCESS_MODIFIER.
1129
     *
1130
     * this handler parses public/private/protected/static/abstract PHP 5 modifiers
1131
     */
1132
    function handleAccessModifier($word, $pevent)
1133
    {
1134
        if (!isset($this->_accessModifiers)) {
1135
            $this->_accessModifiers = array();
1136
        }
1137
        $this->_wp->backupPos();
1138
        $this->_event_stack->popEvent();
1139
        if ($word[0] == T_VARIABLE) {
1140
            // this is a PHP5-style variable with no "var"
1141
            $this->_event_stack->pushEvent(PARSER_EVENT_VAR);
1142
        }
1143
        $this->_accessModifiers[] = strtolower($this->_pv_last_word[1]);
1144
    }
1145
 
1146
    /**
1147
     * handler for CLASS.
1148
     *
1149
     * this handler parses a class/interface statement
1150
     */
1151
    function handleClass($word, $pevent)
1152
    {
1153
        if (!$this->_pf_in_class) {
1154
            $this->_pf_in_class = true;
1155
            if ($this->_pv_last_word[0] == T_INTERFACE) {
1156
                $this->_pf_interface = true;
1157
            } else {
1158
                $this->_pf_interface = false;
1159
            }
1160
        }
1161
        $a = $this->checkEventPush($word, $pevent);
1162
 
1163
        if (!isset($this->_pv_class)) {
1164
            $this->_pv_class = false;
1165
        }
1166
        if (!is_subclass_of($this->_pv_class, "parserBase")) {
1167
            $this->_pv_class = new parserClass;
1168
            if (isset($this->_accessModifiers)) {
1169
                $this->_pv_class->setModifiers($this->_accessModifiers);
1170
                unset($this->_accessModifiers);
1171
            }
1172
            if ($this->_pf_interface) {
1173
                $this->_pv_class->setInterface();
1174
            }
1175
            $this->_pv_class->setLineNumber($this->_wp->linenum + 1);
1176
            $this->_pv_class->setname($word[1]);
1177
            $this->_pv_cur_class = $word[1];
1178
            $this->_pv_class->setSourceLocation($this->source_location);
1179
        }
1180
 
1181
        if (is_array($this->_pv_last_word) && $this->_pv_last_word[0] == T_EXTENDS
1182
        ) {
1183
            // I don't know why I am so nice, this fixes 1150809
1184
            if ($word[1] == $this->_pv_class->getName()) {
1185
                addErrorDie(PDERROR_CANNOT_EXTEND_SELF, $word[1]);
1186
            }
1187
            $this->_pv_class->setExtends($word[1]);
1188
        }
1189
 
1190
        if ($word == "{") {
1191
            $this->publishEvent(PHPDOCUMENTOR_EVENT_CLASS, $this->_pv_class);
1192
        }
1193
        //echo $this->wp->getPos() . ": |$word|\n";
1194
        if ($this->checkEventPop($word, $pevent)) {
1195
            $this->_pv_class->setEndLineNumber($this->_wp->linenum + 1);
1196
            $this->_pf_in_class = $this->_pf_interface = false;
1197
            // throw an event when class is done
1198
            $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE, STATE_END_CLASS);
1199
            $this->_pv_class = false;
1200
        }
1201
    }
1202
 
1203
    /**
1204
     * handler for VAR_ARRAY_COMMENT
1205
     *
1206
     * if parsing a default value, add the comment to the text
1207
     */
1208
    function handleVarArrayComment($word, $pevent)
1209
    {
1210
        $this->_pv_function_data .= $this->_pv_last_word[1];
1211
        return $this->handleComment($word, $pevent);
1212
    }
1213
 
1214
    /**
1215
     * handler for VAR.
1216
     *
1217
     * handle a var $varname = default_value;
1218
     * or var $varname; statement
1219
     * in a class definition
1220
     */
1221
    function handleVar($word, $pevent)
1222
    {
1223
        if (!$this->_pf_in_var) {
1224
            $this->_pf_set_var_value = false;
1225
            $this->_pv_var_value     = '';
1226
            $this->_pv_linenum       = $this->_wp->linenum + 1;
1227
        }
1228
        $this->_pf_in_var = true;
1229
        //echo $word."\n";
1230
        $e = $this->checkEventPush($word, $pevent);
1231
 
1232
        if (!isset($this->_pv_var)) {
1233
            $this->_pv_var = false;
1234
        }
1235
        if ($word == '=' || $word == ';' || $word == ',') {
1236
            $this->_wp->setWhitespace(true);
1237
            $this->_pf_var_equals = true;
1238
            $this->_pv_var        = new parserVar($this->_pv_cur_class);
1239
            $this->_pv_var->setName($this->_pv_varname);
1240
        }
1241
        if ($this->_last_pevent == PARSER_EVENT_VAR_ARRAY) {
1242
            if (isset($this->_pv_function_data)) {
1243
                $this->_pv_var->setValue($this->_pv_function_data);
1244
            }
1245
            $this->_pf_set_var_value = true;
1246
            unset($this->_pv_function_data);
1247
        } elseif ($this->_pf_var_equals && $word != ';' &&
1248
            $word != '=' && $word != ',' && !$e
1249
        ) {
1250
            if (is_array($word)) {
1251
                $word = $word[1];
1252
            }
1253
            $this->_pv_var_value .= $word;
1254
        }
1255
        if ($word == ',') {
1256
            if (!$this->_pf_set_var_value) {
1257
                $this->_pv_var->setValue($this->_pv_var_value);
1258
            }
1259
            $this->_pf_set_var_value = false;
1260
            unset($this->_pv_var_value);
1261
            $this->_pv_var->setEndLineNumber($this->_wp->linenum + 1);
1262
            $this->_pv_var->setLineNumber($this->_pv_linenum);
1263
            if (isset($this->_accessModifiers)) {
1264
                $this->_pv_var->setModifiers($this->_accessModifiers);
1265
            }
1266
            $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR, $this->_pv_var);
1267
            unset($this->_pv_var);
1268
            $this->_pf_in_var     = false;
1269
            $this->_pf_var_equals = false;
1270
            $this->_pv_varname    = '';
1271
            return;
1272
        }
1273
        if ($this->checkEventPop($word, $pevent)) {
1274
            $this->_wp->setWhitespace(false);
1275
            if (!$this->_pf_set_var_value) {
1276
                $this->_pv_var->setValue($this->_pv_var_value);
1277
            }
1278
            $this->_pf_set_var_value = false;
1279
            unset($this->_pv_var_value);
1280
            $this->_pv_var->setEndLineNumber($this->_wp->linenum + 1);
1281
            $this->_pv_var->setLineNumber($this->_pv_linenum);
1282
            if (isset($this->_accessModifiers)) {
1283
                $this->_pv_var->setModifiers($this->_accessModifiers);
1284
                unset($this->_accessModifiers);
1285
            }
1286
            $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR, $this->_pv_var);
1287
            unset($this->_pv_var);
1288
            $this->_pf_in_var     = false;
1289
            $this->_pf_var_equals = false;
1290
            $this->_pv_varname    = '';
1291
            return;
1292
        }
1293
        if ($word[0] == T_VARIABLE) {
1294
            $this->_pv_varname = $word[1];
1295
        }
1296
    }
1297
 
1298
    /**
1299
     * handler for CLASS_CONSTANT.
1300
     *
1301
     * handle a const constname = default_value; statement in a class definition
1302
     */
1303
    function handleClassConstant($word, $pevent)
1304
    {
1305
        if (!$this->_pf_in_const) {
1306
            $this->_pf_set_const_value = false;
1307
            $this->_pv_const_value     = '';
1308
            $this->_pv_linenum         = $this->_wp->linenum + 1;
1309
        }
1310
        $this->_pf_in_const = true;
1311
        //echo $word."\n";
1312
        $e = $this->checkEventPush($word, $pevent);
1313
 
1314
        if (!isset($this->_pv_const)) {
1315
            $this->_pv_const = false;
1316
        }
1317
        if ($word == '=' || $word == ';' || $word == ',') {
1318
            $this->_wp->setWhitespace(true);
1319
            $this->_pf_const_equals = true;
1320
            $this->_pv_const        = new parserConst($this->_pv_cur_class);
1321
            $this->_pv_const->setName($this->_pv_constname);
1322
        }
1323
        if ($this->_last_pevent == PARSER_EVENT_VAR_ARRAY) {
1324
            if (isset($this->_pv_function_data)) {
1325
                $this->_pv_const->setValue($this->_pv_function_data);
1326
            }
1327
            $this->_pf_set_const_value = true;
1328
            unset($this->_pv_function_data);
1329
        } elseif ($this->_pf_const_equals && $word != ';' &&
1330
            $word != '=' && $word != ',' && !$e
1331
        ) {
1332
            if (is_array($word)) {
1333
                $word = $word[1];
1334
            }
1335
            $this->_pv_const_value .= $word;
1336
        }
1337
        if ($word == ',') {
1338
            if (!$this->_pf_set_const_value) {
1339
                $this->_pv_const->setValue($this->_pv_const_value);
1340
            }
1341
            $this->_pf_set_const_value = false;
1342
            unset($this->_pv_const_value);
1343
            $this->_pv_const->setEndLineNumber($this->_wp->linenum + 1);
1344
            $this->_pv_const->setLineNumber($this->_pv_linenum);
1345
            $this->publishEvent(PHPDOCUMENTOR_EVENT_CONST, $this->_pv_const);
1346
            unset($this->_pv_const);
1347
            $this->_pf_in_const     = false;
1348
            $this->_pf_const_equals = false;
1349
            $this->_pv_constname    = '';
1350
            return;
1351
        }
1352
        if ($this->checkEventPop($word, $pevent)) {
1353
            $this->_wp->setWhitespace(false);
1354
            if (!$this->_pf_set_const_value) {
1355
                $this->_pv_const->setValue($this->_pv_const_value);
1356
            }
1357
            $this->_pf_set_const_value = false;
1358
            unset($this->_pv_const_value);
1359
            $this->_pv_const->setEndLineNumber($this->_wp->linenum + 1);
1360
            $this->_pv_const->setLineNumber($this->_pv_linenum);
1361
            $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR, $this->_pv_const);
1362
            unset($this->_pv_const);
1363
            $this->_pf_in_const     = false;
1364
            $this->_pf_const_equals = false;
1365
            $this->_pv_constname    = '';
1366
            return;
1367
        }
1368
        if ($word[0] == T_STRING && !$this->_pf_const_equals) {
1369
            $this->_pv_constname = $word[1];
1370
        }
1371
    }
1372
 
1373
    /**
1374
     * Handler for the
1375
     * {@tutorial phpDocumentor.howto.pkg#using.command-line.javadocdesc}
1376
     * command-line switch DocBlocks.
1377
     *
1378
     * @todo CS cleanup - rename to javaDoc* for camelCasing rule
1379
     */
1380
    function JavaDochandleDocblock($word, $pevent)
1381
    {
1382
        $this->commonDocBlock($word, $pevent, 'handleJavaDocDesc');
1383
    }
1384
 
1385
    /**
1386
     * Handler for normal DocBlocks
1387
     */
1388
    function handleDocBlock($word, $pevent)
1389
    {
1390
        $this->commonDocBlock($word, $pevent, 'handleDesc');
1391
    }
1392
    /**#@-*/
1393
 
1394
    /**
1395
     * Helper function for {@link handleFunctionParams()}
1396
     *
1397
     * This function adds a new parameter to the parameter list
1398
     *
1399
     * @param string $word the parameter word
1400
     *
1401
     * @return void
1402
     * @access private
1403
     */
1404
    function endFunctionParam($word)
1405
    {
1406
        if (isset($this->_pv_quote_data)) {
1407
            $this->_pv_function_data .= $this->_pv_quote_data;
1408
            unset($this->_pv_quote_data);
1409
        }
1410
        if (isset($this->_pv_function_param)) {
1411
            $this->_pv_func->addParam($this->_pv_function_param,
1412
                $this->_pv_function_data,
1413
                $this->_pf_funcparam_val,
1414
                $this->_pv_function_param_type);
1415
            unset($this->_pv_function_param);
1416
            $this->_pv_function_data       = '';
1417
            $this->_pf_funcparam_val       = false;
1418
            $this->_pv_function_param_type = null;
1419
        }
1420
    }
1421
 
1422
    /**
1423
     * Common DocBlock Handler for both JavaDoc-format and normal DocBlocks
1424
     *
1425
     * @param string $word        the word
1426
     * @param int    $pevent      the parser event
1427
     * @param string $deschandler the handler to use
1428
     *
1429
     * @return void
1430
     * @access private
1431
     */
1432
    function commonDocBlock($word, $pevent, $deschandler)
1433
    {
1434
        $this->_wp->backupPos();
1435
        $this->_event_stack->popEvent();
1436
        $word  = $this->_pv_last_word[1];
1437
        $dtype = '_pv_docblock';
1438
        if (strpos($word, '/**') !== 0) {
1439
            // not a docblock
1440
            // $this->_wp->backupPos();
1441
            $this->_event_stack->pushEvent(PARSER_EVENT_COMMENT);
1442
            return;
1443
        }
1444
        if ($word == '/**#@-*/') {
1445
            // stop using docblock template
1446
            $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,
1447
                PHPDOCUMENTOR_EVENT_END_DOCBLOCK_TEMPLATE);
1448
            unset($this->_pv_dtemplate);
1449
            return;
1450
        }
1451
        if (strpos($word, '/**#@+') === 0) {
1452
            // docblock template definition
1453
            $dtype = '_pv_dtemplate';
1454
            // strip /**#@+ and */
1455
            $word = substr($word, 6).'*';
1456
            $word = trim(substr($word, 0, strlen($word) - 3));
1457
            if (strlen($word) && $word{0} != '*') {
1458
                $word = "* $word";
1459
            }
1460
        } else {
1461
            // strip /** and */
1462
            $word = substr($word, 2);
1463
            $word = substr($word, 0, strlen($word) - 2);
1464
        }
1465
        $lines = explode("\n", trim($word));
1466
        $go    = count($lines);
1467
        for ($i=0; $i < $go; $i++) {
1468
            if (substr(trim($lines[$i]), 0, 1) != '*') {
1469
                unset($lines[$i]);
1470
            } else {
1471
                // remove leading "* "
1472
                $lines[$i] = substr(trim($lines[$i]), 1);
1473
            }
1474
        }
1475
        // remove empty lines
1476
        if ($lines == array(false)) {
1477
            // prevent PHP 5.2 segfault (see http://bugs.php.net/bug.php?id=39350)
1478
            $lines = array('');
1479
        }
1480
        $lines = explode("\n", trim(join("\n", $lines)));
1481
        for ($i = 0; $i < count($lines); $i++) {
1482
            if (substr(trim($lines[$i]), 0, 1) == '@' &&
1483
                substr(trim($lines[$i]), 0, 2) != '@ '
1484
            ) {
1485
                $tagindex = $i;
1486
                $i        = count($lines);
1487
            }
1488
        }
1489
        if (isset($tagindex)) {
1490
            $tags = array_slice($lines, $tagindex);
1491
            $desc = array_slice($lines, 0, $tagindex);
1492
        } else {
1493
            $tags = array();
1494
            $desc = $lines;
1495
        }
1496
        //var_dump($desc,$tags);
1497
        $this->$dtype = new parserDocBlock;
1498
        $this->$dtype->setLineNumber($this->_wp->_docblock_linenum + 1);
1499
        $this->$dtype->setEndLineNumber($this->_wp->linenum);
1500
        $this->_pv_dtype = $dtype;
1501
        $this->$deschandler($desc);
1502
        $this->handleTags($tags);
1503
        if ($dtype == '_pv_docblock') {
1504
            $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK, $this->$dtype);
1505
            $this->$dtype = new parserDocBlock();
1506
        } else {
1507
            $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK_TEMPLATE,
1508
                $this->$dtype);
1509
        }
1510
    }
1511
 
1512
    /**
1513
     * Handles JavaDoc descriptions
1514
     *
1515
     * @param string $desc the description
1516
     *
1517
     * @return void
1518
     * @access private
1519
     */
1520
    function handleJavaDocDesc($desc)
1521
    {
1522
        unset($this->_pv_periodline);
1523
        $this->_pf_useperiod = false;
1524
        if (empty($desc)) {
1525
            $desc = array('');
1526
        }
1527
        foreach ($desc as $i => $line) {
1528
            $line = trim($line);
1529
            if (!isset($this->_pv_periodline) &&
1530
                substr($line, strlen($line) - 1) == '.'
1531
            ) {
1532
                $this->_pv_periodline = $i;
1533
                $this->_pf_useperiod  = true;
1534
            }
1535
        }
1536
        if (!isset($this->_pv_periodline)) {
1537
            $this->_pv_periodline = 0;
1538
        }
1539
 
1540
        $dtype = $this->_pv_dtype;
1541
        if ($dtype == '_pv_docblock') {
1542
            $save = $desc;
1543
            // strip leading <p>
1544
            if (strpos($desc[0], '<p>') === 0) {
1545
                $desc[0] = substr($desc[0], 3);
1546
            }
1547
            $sdesc = new parserDesc;
1548
            $desci = '';
1549
            for ($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++
1550
            ) {
1551
                if (strpos($desc[$i], '.') !== false) {
1552
                    $desci .= substr($desc[$i], 0, strpos($desc[$i], '.') + 1);
1553
                } else {
1554
                    $desci .= $desc[$i];
1555
                }
1556
                $desci .= "\n";
1557
            }
1558
            $sdesc->add($this->getInlineTags($desci));
1559
            $desc = $save;
1560
 
1561
            $my_desc = new parserDesc;
1562
            if (isset($this->_pv_dtemplate)) {
1563
                // copy template values if not overridden
1564
                if (!$this->_pv_docblock->getExplicitPackage()) {
1565
                    if ($p = $this->_pv_dtemplate->getKeyword('package')) {
1566
                        $this->_pv_docblock->addKeyword('package', $p);
1567
                        $this->_pv_docblock->setExplicitPackage();
1568
                    }
1569
                    if ($p = $this->_pv_dtemplate->getKeyword('category')) {
1570
                        $this->_pv_docblock->addKeyword('category', $p);
1571
                        $this->_pv_docblock->setExplicitCategory();
1572
                    }
1573
                    if ($p = $this->_pv_dtemplate->getKeyword('subpackage')) {
1574
                        $this->_pv_docblock->addKeyword('subpackage', $p);
1575
                    }
1576
                }
1577
                $tags = $this->_pv_dtemplate->listTags();
1578
                foreach ($tags as $tag) {
1579
                    $this->_pv_docblock->addTag($tag);
1580
                }
1581
                if (!count($this->_pv_docblock->params)) {
1582
                    $this->_pv_docblock->params = $this->_pv_dtemplate->params;
1583
                }
1584
                $my_desc->add($this->_pv_dtemplate->desc);
1585
            }
1586
            //echo "i = ".$this->_pv_periodline."; i < " . count($desc) . "\n";
1587
            $desci = '';
1588
            for ($i = 0; $i < count($desc); $i++) {
1589
                // the line will not be set if it doesn't start with a *
1590
                if (isset($desc[$i])) {
1591
                    $desci .= $desc[$i] . "\n";
1592
                }
1593
            }
1594
            $my_desc->add($this->getInlineTags($desci));
1595
        } else {
1596
            $sdesc = new parserDesc;
1597
            $save  = $desc;
1598
            // strip leading <p>
1599
            if (strpos($desc[0], '<p>') === 0) {
1600
                $desc[0] = substr($desc[0], 3);
1601
            }
1602
            $desci = '';
1603
            for ($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++
1604
            ) {
1605
                if (strpos($desc[$i], '.') !== false) {
1606
                    $desci .= substr($desc[$i], 0, strpos($desc[$i], '.') + 1);
1607
                } else {
1608
                    $desci .= $desc[$i];
1609
                }
1610
                $desci .= "\n";
1611
            }
1612
            $sdesc->add($this->getInlineTags($desci));
1613
            $desc = $save;
1614
 
1615
            $my_desc = new parserDesc;
1616
            $desci   = '';
1617
            for ($i=0; $i < count($desc); $i++) {
1618
                if (isset($desc[$i])) {
1619
                    $desci .= $desci[$i] . "\n";
1620
                }
1621
            }
1622
            $my_desc->add($this->getInlineTags($desci));
1623
        }
1624
 
1625
        if ($this->_pf_internal) {
1626
            addError(PDERROR_INTERNAL_NOT_CLOSED);
1627
            $this->_pf_internal = false;
1628
        }
1629
        $this->$dtype->setShortDesc($sdesc);
1630
        $this->$dtype->setDesc($my_desc);
1631
        unset($my_desc);
1632
        //var_dump($this->$dtype);
1633
        //exit;
1634
    }
1635
 
1636
    /**
1637
     * Process the Long Description of a DocBlock
1638
     *
1639
     * @param array $desc array of lines containing the description
1640
     *                    with leading asterisk "*" stripped off.
1641
     *
1642
     * @return void
1643
     * @access private
1644
     */
1645
    function handleDesc($desc)
1646
    {
1647
        unset($this->_pv_periodline);
1648
        $this->_pf_useperiod = false;
1649
        foreach ($desc as $i => $line) {
1650
            $line = trim($line);
1651
            if (!isset($this->_pv_periodline) &&
1652
                substr($line, strlen($line) - 1) == '.'
1653
            ) {
1654
                $this->_pv_periodline = $i;
1655
                $this->_pf_useperiod  = true;
1656
            }
1657
        }
1658
        if (!isset($this->_pv_periodline)) {
1659
            $this->_pv_periodline = 0;
1660
        }
1661
        if ($this->_pv_periodline > 3) {
1662
            $this->_pf_useperiod = false;
1663
        } else {
1664
            for ($i = 0; $i < $this->_pv_periodline; $i++) {
1665
                if (strlen($desc[$i]) == 0 && isset($desc[$i - 1]) &&
1666
                    strlen($desc[$i - 1])
1667
                ) {
1668
                    $this->_pv_periodline = $i;
1669
                }
1670
            }
1671
        }
1672
        for ($i=0;$i <= $this->_pv_periodline && $i < count($desc);$i++) {
1673
            if (!strlen(trim($desc[$i]))) {
1674
                $this->_pf_useperiod = false;
1675
            }
1676
        }
1677
        // figure out the shortdesc
1678
        if ($this->_pf_useperiod === false) {
1679
            // use the first non blank line for short desc
1680
            for ($i = 0; $i < count($desc); $i++) {
1681
                if (strlen($desc[$i]) > 0) {
1682
                    $this->_pv_periodline = $i;
1683
                    $i                    = count($desc);
1684
                }
1685
            }
1686
 
1687
            // check to see if we are going to use a blank line to end the shortdesc
1688
            // this can only be in the first 4 lines
1689
            if (count($desc) > 4) {
1690
                $max = 4;
1691
            } else {
1692
                $max = count($desc);
1693
            }
1694
 
1695
            for ($i = $this->_pv_periodline; $i < $max; $i++) {
1696
                if (strlen(trim($desc[$i])) == 0) {
1697
                    $this->_pv_periodline = $i;
1698
                    $i                    = $max;
1699
                }
1700
            }
1701
        }
1702
 
1703
        $dtype = $this->_pv_dtype;
1704
        if ($dtype == '_pv_docblock') {
1705
            $sdesc = new parserDesc;
1706
            $desci = '';
1707
            for ($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++
1708
            ) {
1709
                $desci .= $desc[$i] . "\n";
1710
            }
1711
            $sdesc->add($this->getInlineTags($desci));
1712
            $this->_pv_periodline++;
1713
 
1714
            $my_desc = new parserDesc;
1715
            if (isset($this->_pv_dtemplate)) {
1716
                // copy template values if not overridden
1717
                if (!$this->_pv_docblock->getExplicitPackage()) {
1718
                    if ($p = $this->_pv_dtemplate->getKeyword('package')) {
1719
                        $this->_pv_docblock->addKeyword('package', $p);
1720
                        $this->_pv_docblock->setExplicitPackage();
1721
                    }
1722
                    if ($p = $this->_pv_dtemplate->getKeyword('category')) {
1723
                        $this->_pv_docblock->addKeyword('category', $p);
1724
                        $this->_pv_docblock->setExplicitCategory();
1725
                    }
1726
                    if ($p = $this->_pv_dtemplate->getKeyword('subpackage')) {
1727
                        $this->_pv_docblock->addKeyword('subpackage', $p);
1728
                    }
1729
                }
1730
                $tags = $this->_pv_dtemplate->listTags();
1731
                foreach ($tags as $tag) {
1732
                    $this->_pv_docblock->addTag($tag);
1733
                }
1734
                if (!count($this->_pv_docblock->params)) {
1735
                    $this->_pv_docblock->params = $this->_pv_dtemplate->params;
1736
                }
1737
                if (!$this->_pv_docblock->return) {
1738
                    $this->_pv_docblock->return = $this->_pv_dtemplate->return;
1739
                }
1740
                if (!$this->_pv_docblock->var) {
1741
                    $this->_pv_docblock->var = $this->_pv_dtemplate->var;
1742
                }
1743
                $my_desc->add($this->_pv_dtemplate->sdesc);
1744
                $my_desc->add($this->_pv_dtemplate->desc);
1745
            }
1746
            //echo "i = ".$this->_pv_periodline."; i < " . count($desc) . "\n";
1747
            $desci = '';
1748
            for ($i = $this->_pv_periodline; $i < count($desc); $i++) {
1749
                // the line will not be set if it doesn't start with a *
1750
                if (isset($desc[$i])) {
1751
                    $desci .= $desc[$i] . "\n";
1752
                }
1753
            }
1754
            $my_desc->add($this->getInlineTags($desci));
1755
        } else {
1756
            // this is a docblock template
1757
            $sdesc = new parserDesc;
1758
            $desci = '';
1759
            for ($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++
1760
            ) {
1761
                if (isset($desc[$i])) {
1762
                    $desci .= $desc[$i] . "\n";
1763
                }
1764
            }
1765
            $sdesc->add($this->getInlineTags($desci));
1766
            $this->_pv_periodline++;
1767
 
1768
            $my_desc = new parserDesc;
1769
            $desci   = '';
1770
            for ($i=$this->_pv_periodline; $i < count($desc); $i++) {
1771
                if (isset($desc[$i])) {
1772
                    $desci .= $desc[$i] . "\n";
1773
                }
1774
            }
1775
            $my_desc->add($this->getInlineTags($desci));
1776
        }
1777
        if ($this->_pf_internal) {
1778
            addError(PDERROR_INTERNAL_NOT_CLOSED);
1779
            $this->_pf_internal = false;
1780
        }
1781
        $this->$dtype->setShortDesc($sdesc);
1782
        $this->$dtype->setDesc($my_desc);
1783
        unset($my_desc);
1784
        //var_dump($this->$dtype);
1785
        //exit;
1786
    }
1787
 
1788
    /**
1789
     * Process the tags of a DocBlock
1790
     *
1791
     * @param array $tags array of lines that contain all @tags
1792
     *
1793
     * @return void
1794
     * @access private
1795
     */
1796
    function handleTags($tags)
1797
    {
1798
        $newtags = array();
1799
        $curtag  = '';
1800
        for ($i=0; $i < count($tags); $i++) {
1801
            if (strpos(trim($tags[$i]), '@') === 0) {
1802
                $tags[$i] = ltrim($tags[$i]);
1803
            }
1804
            if (substr($tags[$i], 0, 1) == '@' && substr($tags[$i], 0, 2) != '@ '
1805
            ) {
1806
                // start a new tag
1807
                if (!empty($curtag)) {
1808
                    $newtags[] = $curtag;
1809
                }
1810
                $curtag = $tags[$i];
1811
            } else {
1812
                $curtag .= "\n" . $tags[$i];
1813
            }
1814
        }
1815
        if (!empty($curtag)) {
1816
            $newtags[] = $curtag;
1817
        }
1818
        foreach ($newtags as $tag) {
1819
            $x         = explode(' ', str_replace("\t", '    ', $tag));
1820
            $tagname   = trim(substr(array_shift($x), 1));
1821
            $restoftag = $x;
1822
            if (isset($this->tagHandlers[$tagname])) {
1823
                $handle = $this->tagHandlers[$tagname];
1824
            } else {
1825
                $handle = $this->tagHandlers['*'];
1826
            }
1827
            $this->$handle($tagname, $restoftag);
1828
        }
1829
    }
1830
 
1831
    /**
1832
     * Process all inline tags in text, and convert them to their abstract
1833
     * object representations.
1834
     *
1835
     * @param string|array $value complete code to search for inline tags,
1836
     *                            if an array, it's an array of strings
1837
     *
1838
     * @return parserStringWithInlineTags
1839
     * @access private
1840
     */
1841
    function getInlineTags($value)
1842
    {
1843
        if (is_array($value)) {
1844
            $value = join("\n", $value);
1845
        }
1846
        global $_phpDocumentor_setting;
1847
        $priv = (isset($_phpDocumentor_setting['parseprivate']) &&
1848
            $_phpDocumentor_setting['parseprivate'] == 'on');
1849
        $a    = new parserStringWithInlineTags();
1850
        if (!$priv && $this->_pf_internal) {
1851
            if ($x = strpos($value, '}}')) {
1852
                $x                  = strrpos($value, '}}');
1853
                $value              = substr($value, $x + 1);
1854
                $this->_pf_internal = false;
1855
            } else {
1856
                $value = '';
1857
            }
1858
        } elseif ($this->_pf_internal) {
1859
            if ($x = strpos($value, '}}')) {
1860
                $x     = strrpos($value, '}}');
1861
                $value = substr($value, 0, $x) . substr($value, $x+2);
1862
            }
1863
        }
1864
        $save   = $value;
1865
        $value  = explode('{@', $value);
1866
        $newval = array();
1867
        if ($priv || (!$priv && !$this->_pf_internal)) {
1868
            // ignore anything between {@internal and }}
1869
            $a->add($value[0]);
1870
        }
1871
        for ($i=1; $i < count($value); $i++) {
1872
            if (substr($value[$i], 0, 1) == '}') {
1873
                if ($priv || (!$priv && !$this->_pf_internal)) {
1874
                    // ignore anything between {@internal and }}
1875
                    $a->add('{@' . substr($value[$i], 1));
1876
                }
1877
            } elseif (substr($value[$i], 0, 2) == '*}') {
1878
                // used for inserting */ in code examples
1879
                if ($priv || (!$priv && !$this->_pf_internal)) {
1880
                    // ignore anything between {@internal and }}
1881
                    $a->add('*/' . substr($value[$i], 2));
1882
                }
1883
            } else {
1884
                $save      = $value[$i];
1885
                $value[$i] = preg_split("/[\t ]/", str_replace("\t", '    ', $value[$i]));
1886
                $word      = trim(array_shift($value[$i]));
1887
                $val       = join(' ', $value[$i]);
1888
                if (trim($word) == 'internal') {
1889
                    if ($this->_pf_internal) {
1890
                        addErrorDie(PDERROR_NESTED_INTERNAL);
1891
                    }
1892
                    $this->_pf_internal = true;
1893
                    $value[$i]          = substr($save, strlen('internal') + 1);
1894
                    if (!$value[$i]) {
1895
                        // substr can set this to false
1896
                        $value[$i] = '';
1897
                    }
1898
                    if (strpos($value[$i], '}}') !== false) {
1899
                        $x = strrpos($value[$i], '}}');
1900
                        // strip internal and cycle as if it were normal text.
1901
                        $startval = substr($value[$i], 0, $x);
1902
                        if ($priv) {
1903
                            $a->add($startval);
1904
                        }
1905
                        $value[$i] = substr($value[$i], $x + 2);
1906
                        if (!$value[$i]) {
1907
                            $value[$i] = '';
1908
                        }
1909
                        $this->_pf_internal = false;
1910
                        $a->add($value[$i]);
1911
                        continue;
1912
                    } elseif ($priv) {
1913
                        $a->add($value[$i]);
1914
                    }
1915
                    continue;
1916
                }
1917
                if (in_array(str_replace('}', '', trim($word)),
1918
                    $this->allowableInlineTags)
1919
                ) {
1920
                    if (strpos($word, '}')) {
1921
                        $res  = substr($word, strpos($word, '}'));
1922
                        $word = str_replace('}', '', trim($word));
1923
                        $val  = $res . $val;
1924
                    }
1925
                    if ($priv || (!$priv && !$this->_pf_internal)) {
1926
                        // ignore anything between {@internal and }}
1927
                        if ($word == 'source') {
1928
                            $this->_pf_get_source = true;
1929
                        }
1930
                    }
1931
                    $val = explode('}', $val);
1932
                    if (count($val) == 1) {
1933
                           addError(PDERROR_UNTERMINATED_INLINE_TAG,
1934
                               $word, '', $save);
1935
                    }
1936
                    $rest = $val;
1937
                    $val  = array_shift($rest);
1938
                    $rest = join('}', $rest);
1939
                    if (isset($this->inlineTagHandlers[$word])) {
1940
                        $handle = $this->inlineTagHandlers[$word];
1941
                    } else {
1942
                        $handle = $this->inlineTagHandlers['*'];
1943
                    }
1944
                    $val = $this->$handle($word, $val);
1945
                    if ($priv || (!$priv && !$this->_pf_internal)) {
1946
                        // ignore anything between {@internal and }}
1947
                        $a->add($val);
1948
                    }
1949
                    if ($this->_pf_internal) {
1950
                        if (($x = strpos($rest, '}}')) !== false) {
1951
                            $value[$i] = $rest;
1952
                            $startval  = substr($value[$i], 0, $x);
1953
                            if ((false !== $startval) && $priv) {
1954
                                $a->add($startval);
1955
                            }
1956
                            $value[$i] = substr($value[$i], $x + 2);
1957
                            if (!$value[$i]) {
1958
                                $value[$i] = '';
1959
                            }
1960
                            $this->_pf_internal = false;
1961
                            $a->add($value[$i]);
1962
                        } else {
1963
                            $rest = explode('}}', $rest);
1964
                            if ($priv) {
1965
                                $a->add(array_shift($rest));
1966
                            }
1967
                            $this->_pf_internal = false;
1968
                            // try this line again without internal
1969
                            $value[$i--] = join('}}', $rest);
1970
                            continue;
1971
                        }
1972
                    } else {
1973
                        $a->add($rest);
1974
                    }
1975
                } else {
1976
                    $val = $word . ' ' . $val;
1977
                    if ($priv || (!$priv && !$this->_pf_internal)) {
1978
                        // ignore anything between {@internal and }}
1979
                        $a->add('{@' . $val);
1980
                    }
1981
                }
1982
            }
1983
        }
1984
        return $a;
1985
    }
1986
 
1987
    /**#@+
1988
     * @param string $name name of the tag
1989
     * @param string $value any parameters passed to the inline tag
1990
     * @access private
1991
     */
1992
    /**
1993
     * Most inline tags require no special processing
1994
     *
1995
     * @return mixed some type of parser_*_InlineTag object
1996
     */
1997
    function handleDefaultInlineTag($name, $value)
1998
    {
1999
        $tag = 'parser' . ucfirst($name) . 'InlineTag';
2000
        return new $tag($value, $value);
2001
    }
2002
 
2003
    /**
2004
     * Handle the inline {@}link} tag
2005
     *
2006
     * @return parserLinkInlineTag
2007
     * @tutorial tags.inlinelink.pkg
2008
     */
2009
    function handleLinkInlineTag($name, $value)
2010
    {
2011
        // support hyperlinks of any protocol
2012
        if (is_numeric(strpos($value, '://')) ||
2013
            (strpos(trim($value), 'mailto:') === 0)
2014
        ) {
2015
            $value = str_replace('\\,', '###commanana####', $value);
2016
            if (strpos($value, ',')) {
2017
                $val = new parserLinkInlineTag($value, $value);
2018
            } elseif (strpos(trim($value), ' ')) {
2019
                // if there is more than 1 parameter,
2020
                // the stuff after the space is the hyperlink text
2021
                $i1   = strpos(trim($value), ' ') + 1;
2022
                $link = substr(trim($value), 0, $i1 - 1);
2023
                $text = substr(trim($value), $i1);
2024
                $val  = new parserLinkInlineTag($link, $text);
2025
            } else {
2026
                $val = new parserLinkInlineTag($value, $value);
2027
            }
2028
        } else {
2029
            $value = str_replace('\\,', '###commanana####', $value);
2030
            if (!strpos($value, ',')) {
2031
                $testp = explode('#', $value);
2032
                if (count($testp) - 1) {
2033
                    $val = new parserLinkInlineTag($value, $testp[1]);
2034
                } else {
2035
                    $val = new parserLinkInlineTag($value, $value);
2036
                }
2037
            } else {
2038
                $val = new parserLinkInlineTag($value, $value);
2039
            }
2040
        }
2041
        return $val;
2042
    }
2043
    /**#@-*/
2044
 
2045
    /**#@+
2046
     * @access private
2047
     * @param string $name name of tag
2048
     * @param array $value all words in the tag that were separated by a space ' '
2049
     * @return void
2050
     */
2051
    /**
2052
     * Most tags only need the value as a string
2053
     *
2054
     * @uses getInlineTags() all tag handlers check their values for inline tags
2055
     * @uses parserDocBlock::addKeyword()
2056
     */
2057
    function defaultTagHandler($name, $value)
2058
    {
2059
        $dtype = $this->_pv_dtype;
2060
        $this->$dtype->addKeyword($name, $this->getInlineTags(join(' ', $value)));
2061
    }
2062
 
2063
    /**
2064
     * handles the @example tag
2065
     *
2066
     * @tutorial tags.example.pkg
2067
     * @uses parserDocBlock::addExample()
2068
     */
2069
    function exampleTagHandler($name, $value)
2070
    {
2071
        $dtype = $this->_pv_dtype;
2072
        $this->$dtype->addExample($this->getInlineTags(join(' ', $value)),
2073
            $this->_path);
2074
    }
2075
 
2076
    /**
2077
     * handles the @filesource tag
2078
     *
2079
     * @tutorial tags.filesource.pkg
2080
     * @uses phpDocumentorTWordParser::getFileSource() retrieves the source for
2081
     *       use in the @filesource tag
2082
     * @uses parserDocBlock::addFileSource()
2083
     */
2084
    function filesourceTagHandler($name, $value)
2085
    {
2086
        $dtype = $this->_pv_dtype;
2087
        $this->$dtype->addFileSource($this->_path, $this->_wp->getFileSource());
2088
    }
2089
 
2090
    /**
2091
     * handles the @uses tag
2092
     *
2093
     * @tutorial tags.uses.pkg
2094
     * @uses parserDocBlock::addUses()
2095
     */
2096
    function usesTagHandler($name, $value)
2097
    {
2098
        $dtype = $this->_pv_dtype;
2099
        $seel  = '';
2100
        while ($seel == '' && count($value)) {
2101
            $seel = array_shift($value);
2102
        }
2103
        $this->$dtype->addUses($this->getInlineTags($seel),
2104
            $this->getInlineTags(join(' ', $value)));
2105
    }
2106
 
2107
    /**
2108
     * handles the @author tag
2109
     *
2110
     * @tutorial tags.author.pkg
2111
     * @uses parserDocBlock::addKeyword()
2112
     */
2113
    function authorTagHandler($name, $value)
2114
    {
2115
        $dtype = $this->_pv_dtype;
2116
        $value = join(' ', $value);
2117
        if ((strpos($value, '<') !== false) && (strpos($value, '>') !== false)) {
2118
            $email = substr($value,
2119
                strpos($value, '<') + 1,
2120
                strpos($value, '>') - strpos($value, '<') - 1);
2121
            $value = str_replace('<' . $email . '>',
2122
                '<{@link mailto:' . $email . ' ' .  $email . '}>',
2123
                $value);
2124
        }
2125
        $this->$dtype->addKeyword('author', $this->getInlineTags($value));
2126
    }
2127
 
2128
    /**
2129
     * handles the @package tag
2130
     *
2131
     * @tutorial tags.package.pkg
2132
     * @uses parserDocBlock::setExplicitPackage()
2133
     */
2134
    function packageTagHandler($name, $value)
2135
    {
2136
        if (count($value) && empty($value[0])) {
2137
            $found = false;
2138
            // CRB - I believe this loop is correct in not having a body...
2139
            //       I think it is only to determine the $i value needed
2140
            //       by the one array_splice() call...
2141
            for ($i=0; $i < count($value) && !strlen($value[$i]); $i++);
2142
            array_splice($value, 0, $i);
2143
        }
2144
        $this->defaultTagHandler($name, $value);
2145
        $dtype = $this->_pv_dtype;
2146
        $this->$dtype->setExplicitPackage();
2147
    }
2148
 
2149
    /**
2150
     * handles the @category tag
2151
     *
2152
     * @tutorial tags.category.pkg
2153
     * @uses parserDocBlock::setExplicitCategory()
2154
     */
2155
    function categoryTagHandler($name, $value)
2156
    {
2157
        if (count($value) && empty($value[0])) {
2158
            $found = false;
2159
            // CRB - I believe this loop is correct in not having a body...
2160
            //       I think it is only to determine the $i value needed
2161
            //       by the one array_splice() call...
2162
            for ($i=0; $i < count($value) && !strlen($value[$i]); $i++);
2163
            array_splice($value, 0, $i);
2164
        }
2165
        $this->defaultTagHandler($name, $value);
2166
        $dtype = $this->_pv_dtype;
2167
        $this->$dtype->setExplicitCategory();
2168
    }
2169
 
2170
    /**
2171
     * handles the @global tag
2172
     *
2173
     * @tutorial tags.global.pkg
2174
     * @uses parserDocBlock::addFuncGlobal()
2175
     */
2176
    function globalTagHandler($name, $value)
2177
    {
2178
        $info = $this->retrieveType($value, true);
2179
        if (!$info) {
2180
            addError(PDERROR_MALFORMED_TAG, '@global');
2181
        }
2182
        $type  = $info['type'];
2183
        $var   = $info['var'];
2184
        $desc  = $info['desc'];
2185
        $dtype = $this->_pv_dtype;
2186
        if (!$var && empty($desc)) {
2187
            if ($type{0} == '$') {
2188
                addError(PDERROR_MALFORMED_GLOBAL_TAG);
2189
            }
2190
            return $this->$dtype->addFuncGlobal($type,
2191
                new parserStringWithInlineTags);
2192
        }
2193
        if ($var) {
2194
            // global define
2195
            $this->_pv_global_type = $type;
2196
            if (!empty($desc)) {
2197
                $var .= ' '.$desc;
2198
            }
2199
            $this->findGlobal(trim($var));
2200
        } elseif (!empty($desc)) {
2201
            // function global
2202
            if ($type{0} == '$') {
2203
                addError(PDERROR_MALFORMED_GLOBAL_TAG);
2204
            }
2205
            $this->$dtype->addFuncGlobal($type, $this->getInlineTags($desc));
2206
        } else {
2207
            addError(PDERROR_MALFORMED_GLOBAL_TAG);
2208
        }
2209
    }
2210
 
2211
    /**
2212
     * handles the @staticvar tag
2213
     *
2214
     * @tutorial tags.staticvar.pkg
2215
     * @uses parserDocBlock::addStaticVar()
2216
     */
2217
    function staticvarTagHandler($name, $value)
2218
    {
2219
        $info = $this->retrieveType($value, true);
2220
        if (!$info) {
2221
            addError(PDERROR_MALFORMED_TAG, '@staticvar');
2222
        }
2223
        $type  = $info['type'];
2224
        $var   = $info['var'];
2225
        $desc  = $info['desc'];
2226
        $dtype = $this->_pv_dtype;
2227
        if (!$var && empty($desc)) {
2228
            $this->$dtype->addStaticVar(null, $type,
2229
                new parserStringWithInlineTags);
2230
        } else {
2231
            if ($var) {
2232
                $this->$dtype->addStaticVar($var, $type,
2233
                    $this->getInlineTags($desc));
2234
            } else {
2235
                $this->$dtype->addStaticVar(null, $type,
2236
                    $this->getInlineTags($desc));
2237
            }
2238
        }
2239
    }
2240
 
2241
    /**
2242
     * handles the @param tag
2243
     *
2244
     * @tutorial tags.param.pkg
2245
     * @uses parserDocBlock::addParam()
2246
     */
2247
    function paramTagHandler($name, $value)
2248
    {
2249
        $info = $this->retrieveType($value, true);
2250
        if (!$info) {
2251
            addError(PDERROR_MALFORMED_TAG, '@param');
2252
            return;
2253
        }
2254
        $type  = $info['type'];
2255
        $var   = $info['var'];
2256
        $desc  = $info['desc'];
2257
        $dtype = $this->_pv_dtype;
2258
        if (!$var && empty($desc)) {
2259
            $this->$dtype->addParam(null, $type, new parserStringWithInlineTags);
2260
        } else {
2261
            if ($var) {
2262
                $this->$dtype->addParam($var, $type, $this->getInlineTags($desc));
2263
            } else {
2264
                $this->$dtype->addParam(null, $type, $this->getInlineTags($desc));
2265
            }
2266
        }
2267
    }
2268
 
2269
    /**
2270
     * handles the @return tag
2271
     *
2272
     * @tutorial tags.return.pkg
2273
     * @uses parserDocBlock::addReturn()
2274
     */
2275
    function returnTagHandler($name, $value)
2276
    {
2277
        $info = $this->retrieveType($value, true);
2278
        if (!$info) {
2279
            addError(PDERROR_MALFORMED_TAG, '@return');
2280
            return;
2281
        }
2282
        $type  = $info['type'];
2283
        $desc  = $info['desc'];
2284
        $dtype = $this->_pv_dtype;
2285
        $this->$dtype->addReturn($type, $this->getInlineTags($desc));
2286
    }
2287
 
2288
    /**
2289
     * handles the @var tag
2290
     *
2291
     * @tutorial tags.var.pkg
2292
     * @uses parserDocBlock::addVar()
2293
     */
2294
    function varTagHandler($name, $value)
2295
    {
2296
        $info = $this->retrieveType($value, true);
2297
        if (!$info) {
2298
            addError(PDERROR_MALFORMED_TAG, '@var');
2299
        }
2300
        $type  = $info['type'];
2301
        $desc  = $info['desc'];
2302
        $dtype = $this->_pv_dtype;
2303
        $this->$dtype->addVar($type, $this->getInlineTags($desc));
2304
    }
2305
 
2306
    /**
2307
     * Handles @property(-read or -write) and @method magic tags
2308
     *
2309
     * @tutorial tags.method.pkg
2310
     * @tutorial tags.property.pkg
2311
     * @uses parserDocBlock::addProperty()
2312
     */
2313
    function propertyTagHandler($name, $value)
2314
    {
2315
        $info = $this->retrieveType($value, true);
2316
        if (!$info) {
2317
            addError(PDERROR_MALFORMED_TAG, '@' . $name);
2318
        }
2319
        $type  = $info['type'];
2320
        $var   = $info['var'];
2321
        $desc  = $info['desc'];
2322
        $dtype = $this->_pv_dtype;
2323
        $this->$dtype->addProperty($name, $var, $type, $this->getInlineTags($desc));
2324
    }
2325
    /**#@-*/
2326
 
2327
    /**#@+
2328
     * @access private
2329
     */
2330
 
2331
    /**
2332
     * Retrieve the type portion of a @tag type description
2333
     *
2334
     * Tags like @param, @return and @var all have a PHP type portion in their
2335
     * description.  Since the type may contain the expression "object blah"
2336
     * where blah is a classname, it makes parsing out the type field complex.
2337
     *
2338
     * Even more complicated is the case where a tag variable can contain
2339
     * multiple types, such as object blah|object blah2|false, and so this
2340
     * method handles these cases.
2341
     *
2342
     * @param array $value       array of words that were separated by spaces
2343
     * @param bool  $checkforvar flag to determine whether to check for the end of a
2344
     *                           type is defined by a $varname
2345
     *
2346
     * @return bool|array FALSE if there is no value,
2347
     *     or an array of Format:
2348
     *    <pre>
2349
     *         array(
2350
     *             'type' => string,
2351
     *             'var'  => false|string variable name,
2352
     *             'desc' => rest of the tag
2353
     *         )
2354
     *    </pre>
2355
     */
2356
    function retrieveType($value, $checkforvar = false)
2357
    {
2358
        if (!count($value)) {
2359
            return false;
2360
        }
2361
        $result = array();
2362
        $types  = '';
2363
        // remove empty entries resulting from extra spaces between @tag and type
2364
        $this->_removeWhiteSpace($value, 0);
2365
        $index = 0;
2366
        if (trim($value[0]) == 'object') {
2367
            $types .= array_shift($value) . ' ';
2368
            $this->_removeWhiteSpace($value, 0);
2369
            if (!count($value)) {
2370
                // was just passed "object"
2371
                $result = array('type' => rtrim($types), 'desc' => '');
2372
                if ($checkforvar) {
2373
                    $result['var'] = false;
2374
                }
2375
                return $result;
2376
            }
2377
            if ($value[0]{0} == '$' || substr($value[0], 0, 2) == '&$') {
2378
                // was just passed "object" and the next thing is a variable name
2379
                $result['var']  = trim($value[0]);
2380
                $result['type'] = 'object';
2381
                array_shift($value);
2382
                $result['desc'] = join(' ', $value);
2383
                return $result;
2384
            }
2385
        }
2386
        $done = false;
2387
        do {
2388
            // this loop checks for type|type|type
2389
            // and for type|object classname|type|object classname2
2390
            if (strpos($value[0], '|')) {
2391
                $temptypes = explode('|', $value[0]);
2392
                while (count($temptypes)) {
2393
                    $type   = array_shift($temptypes);
2394
                    $types .= $type;
2395
                    if (count($temptypes)) {
2396
                        $types .= '|';
2397
                    }
2398
                }
2399
                if (trim($type) == 'object') {
2400
                    $types .= ' ';
2401
                    $this->_removeWhiteSpace($value, 0);
2402
                } else {
2403
                    $done = true;
2404
                }
2405
                array_shift($value);
2406
                if (isset ($value[0]) && strlen($value[0]) && ($value[0]{0} == '$' ||
2407
                    substr($value[0], 0, 2) == '&$')
2408
                ) {
2409
                    // was just passed "object" and the next thing is a variable name
2410
                    $result['var']  = trim($value[0]);
2411
                    $result['type'] = $types;
2412
                    array_shift($value);
2413
                    $result['desc'] = join(' ', $value);
2414
                    return $result;
2415
                }
2416
            } else {
2417
                $types .= $value[0];
2418
                array_shift($value);
2419
                $done = true;
2420
            }
2421
        } while (!$done && count($value));
2422
        $result['type'] = rtrim($types);
2423
        $this->_removeWhiteSpace($value, 0);
2424
        if ($checkforvar) {
2425
            if (!count($value)) {
2426
                $result['var'] = false;
2427
            } else {
2428
                /*
2429
                 * check for:
2430
                 *    variable name ($)
2431
                 *    var passed by reference (&$)
2432
                 *    method name (only used by magic method)
2433
                 */
2434
                if (substr($value[0], 0, 1) == '$' ||
2435
                    substr($value[0], 0, 2) == '&$' ||
2436
                    substr($value[0], -2, 2) == '()'
2437
                ) {
2438
                    $result['var'] = trim($value[0]);
2439
                    array_shift($value);
2440
                } else {
2441
                    $result['var'] = false;
2442
                }
2443
            }
2444
        }
2445
        $result['desc'] = join(' ', $value);
2446
        return $result;
2447
    }
2448
 
2449
    /**
2450
     * remove whitespace from a value
2451
     *
2452
     * @param array   &$value array of string
2453
     * @param integer $index  index to seek non-whitespace to
2454
     *
2455
     * @return void
2456
     */
2457
    function _removeWhiteSpace(&$value, $index)
2458
    {
2459
        if (count($value) > $index && empty($value[$index])) {
2460
            $found = false;
2461
            // CRB - I believe this loop is correct in not having a body...
2462
            //       I think it is only to determine the $i value needed
2463
            //       by the one array_splice() call...
2464
            for ($i=$index; $i < count($value) && !strlen($value[$i]); $i++);
2465
            array_splice($value, $index, $i - $index);
2466
        }
2467
    }
2468
 
2469
    /**
2470
     * Retrieve all the tokens that represent the definition of the global variable
2471
     *
2472
     * {@source}
2473
     *
2474
     * @param string $name the global variable to find
2475
     *
2476
     * @return void
2477
     */
2478
    function findGlobal($name)
2479
    {
2480
        $tokens = token_get_all('<?php ' . $name);
2481
        $tokens = array_slice($tokens, 1);
2482
        $this->_wp->findGlobal($tokens);
2483
        $this->_pv_findglobal = $name;
2484
    }
2485
 
2486
    /**
2487
     * this function checks whether parameter $word
2488
     * is a token for pushing a new event onto the Event Stack.
2489
     *
2490
     * @param string $word   the word to check
2491
     * @param int    $pevent the event to push
2492
     *
2493
     * @return mixed returns false, or the event number
2494
     */
2495
    function checkEventPush($word, $pevent)
2496
    {
2497
        if (is_array($word) && $word[0] == T_STRING) {
2498
            $word = $word[1];
2499
        }
2500
        if (is_array($word)) {
2501
            $pushEvent = &$this->tokenpushEvent;
2502
            $word      = $word[0];
2503
        } else {
2504
            $pushEvent = &$this->wordpushEvent;
2505
            $word      = strtolower($word);
2506
        }
2507
        $e = false;
2508
        if (isset($pushEvent[$pevent])) {
2509
            if (isset($pushEvent[$pevent][$word])) {
2510
                $e = $pushEvent[$pevent][$word];
2511
            }
2512
        }
2513
        if ($e) {
2514
            $this->_event_stack->pushEvent($e);
2515
            return $e;
2516
        } else {
2517
            return false;
2518
        }
2519
    }
2520
 
2521
    /**
2522
     * this function checks whether parameter $word
2523
     * is a token for popping the current event off of the Event Stack.
2524
     *
2525
     * @param string $word   the word to check
2526
     * @param int    $pevent the event to pop
2527
     *
2528
     * @return mixed returns false, or the event number popped off of the stack
2529
     */
2530
    function checkEventPop($word, $pevent)
2531
    {
2532
        if (is_array($word) && $word[0] == T_STRING) {
2533
            $word = $word[1];
2534
        }
2535
        if (is_array($word)) {
2536
            $popEvent = &$this->tokenpopEvent;
2537
            $word     = $word[0];
2538
        } else {
2539
            $popEvent = &$this->wordpopEvent;
2540
            $word     = strtolower($word);
2541
        }
2542
        if (!isset($popEvent[$pevent])) {
2543
            return false;
2544
        }
2545
        if (in_array($word, $popEvent[$pevent])) {
2546
            return $this->_event_stack->popEvent();
2547
        } else {
2548
            return false;
2549
        }
2550
    }
2551
 
2552
    /**
2553
     * returns the token from the $word array
2554
     *
2555
     * @param mixed $word the token array
2556
     *
2557
     * @return mixed the token from the array,
2558
     *               or FALSE if it's not an array
2559
     */
2560
    function getToken($word)
2561
    {
2562
        if (is_array($word)) {
2563
            return $word[0];
2564
        }
2565
        return false;
2566
    }
2567
 
2568
    /**
2569
     * setup the parser tokens, and the pushEvent/popEvent arrays
2570
     *
2571
     * @return void
2572
     * @see $tokens, $pushEvent, $popEvent
2573
     */
2574
    function setupStates()
2575
    {
2576
        unset($this->_wp);
2577
        $this->_wp                     = new phpDocumentorTWordParser;
2578
        $this->_pv_class               = null;
2579
        $this->_pv_cur_class           = null;
2580
        $this->_pv_define              = null;
2581
        $this->_pv_define_name         = null;
2582
        $this->_pv_define_value        = null;
2583
        $this->_pv_define_params_data  = null;
2584
        $this->_pv_dtype               = null;
2585
        $this->_pv_docblock            = null;
2586
        $this->_pv_dtemplate           = null;
2587
        $this->_pv_func                = null;
2588
        $this->_pv_findglobal          = null;
2589
        $this->_pv_global_name         = null;
2590
        $this->_pv_global_val          = null;
2591
        $this->_pv_globals             = null;
2592
        $this->_pv_global_count        = null;
2593
        $this->_pv_include_params_data = null;
2594
        $this->_pv_include_name        = null;
2595
        $this->_pv_include_value       = null;
2596
        $this->_pv_linenum             = null;
2597
        $this->_pv_periodline          = null;
2598
        $this->_pv_paren_count         = 0;
2599
        $this->_pv_statics             = null;
2600
        $this->_pv_static_count        = null;
2601
        $this->_pv_static_val          = null;
2602
        $this->_pv_quote_data          = null;
2603
        $this->_pv_function_data       = null;
2604
        $this->_pv_var                 = null;
2605
        $this->_pv_varname             = null;
2606
        $this->_pv_const               = null;
2607
        $this->_pv_constname           = null;
2608
        $this->_pv_function_param_type = null;
2609
        $this->_pf_definename_isset    = false;
2610
        $this->_pf_includename_isset   = false;
2611
        $this->_pf_get_source          = false;
2612
        $this->_pf_getting_source      = false;
2613
        $this->_pf_in_class            = false;
2614
        $this->_pf_in_define           = false;
2615
        $this->_pf_in_global           = false;
2616
        $this->_pf_in_include          = false;
2617
        $this->_pf_in_var              = false;
2618
        $this->_pf_in_const            = false;
2619
        $this->_pf_funcparam_val       = false;
2620
        $this->_pf_quote_active        = false;
2621
        $this->_pf_reset_quote_data    = true;
2622
        $this->_pf_useperiod           = false;
2623
        $this->_pf_var_equals          = false;
2624
        $this->_pf_const_equals        = false;
2625
        $this->_event_stack            = new EventStack;
2626
    }
2627
 
2628
    /**
2629
     * Creates the state arrays
2630
     *
2631
     * @return void
2632
     */
2633
    function setupEventStates()
2634
    {
2635
        if (!defined('T_DOC_COMMENT')) {
2636
            define('T_DOC_COMMENT', T_DOC_COMMENT);
2637
        }
2638
        /**************************************************************/
2639
 
2640
        $this->wordpushEvent[PARSER_EVENT_LOGICBLOCK]  =
2641
            array(
2642
                "{" => PARSER_EVENT_LOGICBLOCK,
2643
                '"' => PARSER_EVENT_QUOTE,
2644
            );
2645
        $this->tokenpushEvent[PARSER_EVENT_LOGICBLOCK] =
2646
            array(
2647
                T_GLOBAL                   => PARSER_EVENT_FUNC_GLOBAL,
2648
                T_STATIC                   => PARSER_EVENT_STATIC_VAR,
2649
                T_START_HEREDOC            => PARSER_EVENT_EOFQUOTE,
2650
                T_CURLY_OPEN               => PARSER_EVENT_LOGICBLOCK,
2651
                T_DOLLAR_OPEN_CURLY_BRACES => PARSER_EVENT_LOGICBLOCK,
2652
            );
2653
 
2654
        $this->wordpopEvent[PARSER_EVENT_LOGICBLOCK]  = array("}");
2655
        $this->tokenpopEvent[PARSER_EVENT_LOGICBLOCK] = array(T_CURLY_OPEN);
2656
        /**************************************************************/
2657
 
2658
        $this->tokenpushEvent[PARSER_EVENT_NOEVENTS] =
2659
            array(
2660
                T_OPEN_TAG => PARSER_EVENT_PHPCODE,
2661
            );
2662
 
2663
        /**************************************************************/
2664
 
2665
        $this->tokenpopEvent[PARSER_EVENT_EOFQUOTE] = array(T_END_HEREDOC);
2666
        /**************************************************************/
2667
 
2668
        $this->tokenpushEvent[PARSER_EVENT_PHPCODE] =
2669
            array(
2670
                T_FUNCTION     => PARSER_EVENT_FUNCTION,
2671
                T_ABSTRACT     => PARSER_EVENT_ACCESS_MODIFIER,
2672
                T_CLASS        => PARSER_EVENT_CLASS,
2673
                T_INTERFACE    => PARSER_EVENT_CLASS,
2674
                T_INCLUDE_ONCE => PARSER_EVENT_INCLUDE,
2675
                T_INCLUDE      => PARSER_EVENT_INCLUDE,
2676
                T_REQUIRE      => PARSER_EVENT_INCLUDE,
2677
                T_REQUIRE_ONCE => PARSER_EVENT_INCLUDE,
2678
                T_COMMENT      => PARSER_EVENT_DOCBLOCK,
2679
                T_DOC_COMMENT  => PARSER_EVENT_DOCBLOCK,
2680
                //"/**#@+"       => PARSER_EVENT_DOCBLOCK_TEMPLATE,
2681
                //"/**#@-*/"     => PARSER_EVENT_END_DOCBLOCK_TEMPLATE,
2682
                T_CLOSE_TAG    => PARSER_EVENT_OUTPHP,
2683
            );
2684
        $this->wordpushEvent[PARSER_EVENT_PHPCODE]  =
2685
            array(
2686
                "define" => PARSER_EVENT_DEFINE,
2687
            );
2688
        /**************************************************************/
2689
 
2690
        $this->tokenpopEvent[PARSER_EVENT_OUTPHP] = array(T_OPEN_TAG);
2691
        /**************************************************************/
2692
 
2693
        $this->wordpushEvent[PARSER_EVENT_FUNCTION]  =
2694
            array(
2695
                '{' => PARSER_EVENT_LOGICBLOCK,
2696
                '(' => PARSER_EVENT_FUNCTION_PARAMS,
2697
            );
2698
        $this->tokenpushEvent[PARSER_EVENT_FUNCTION] =
2699
            array(
2700
                T_COMMENT     => PARSER_EVENT_COMMENT,
2701
                T_DOC_COMMENT => PARSER_EVENT_COMMENT,
2702
            );
2703
 
2704
        $this->wordpopEvent[PARSER_EVENT_FUNCTION] = array("}",';');
2705
        /**************************************************************/
2706
 
2707
        $this->wordpopEvent[PARSER_EVENT_QUOTE] = array('"');
2708
        /**************************************************************/
2709
 
2710
        $this->tokenpushEvent[PARSER_EVENT_FUNCTION_PARAMS] =
2711
            array(
2712
                T_VARIABLE    => PARSER_EVENT_FUNCTION_PARAM_VAR,
2713
                T_COMMENT     => PARSER_EVENT_COMMENT,
2714
                T_DOC_COMMENT => PARSER_EVENT_COMMENT,
2715
            );
2716
        $this->wordpopEvent[PARSER_EVENT_FUNCTION_PARAMS]   = array(")");
2717
        /**************************************************************/
2718
 
2719
        $this->tokenpushEvent[PARSER_EVENT_FUNCTION_PARAM_VAR] =
2720
            array(
2721
                T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
2722
                T_COMMENT                  => PARSER_EVENT_COMMENT,
2723
                T_DOC_COMMENT              => PARSER_EVENT_COMMENT,
2724
                T_ARRAY                    => PARSER_EVENT_ARRAY,
2725
            );
2726
        $this->wordpushEvent[PARSER_EVENT_FUNCTION_PARAM_VAR]  =
2727
            array(
2728
                '"' => PARSER_EVENT_QUOTE,
2729
                "'" => PARSER_EVENT_QUOTE,
2730
            );
2731
        $this->wordpopEvent[PARSER_EVENT_FUNCTION_PARAM_VAR]   = array(",", ")");
2732
        /**************************************************************/
2733
 
2734
        $this->tokenpushEvent[PARSER_EVENT_ARRAY] =
2735
            array(
2736
                T_COMMENT     => PARSER_EVENT_COMMENT,
2737
                T_DOC_COMMENT => PARSER_EVENT_COMMENT,
2738
            );
2739
        $this->wordpopEvent[PARSER_EVENT_ARRAY]   = array(")");
2740
        /**************************************************************/
2741
 
2742
        $this->tokenpushEvent[PARSER_EVENT_VAR_ARRAY] =
2743
            array(
2744
                T_COMMENT     => PARSER_EVENT_VAR_ARRAY_COMMENT,
2745
                T_DOC_COMMENT => PARSER_EVENT_VAR_ARRAY_COMMENT,
2746
            );
2747
        $this->wordpopEvent[PARSER_EVENT_VAR_ARRAY]   = array(")");
2748
        /**************************************************************/
2749
 
2750
        $this->tokenpushEvent[PARSER_EVENT_FUNC_GLOBAL] =
2751
            array(
2752
                T_COMMENT     => PARSER_EVENT_COMMENT,
2753
                T_DOC_COMMENT => PARSER_EVENT_COMMENT,
2754
            );
2755
        $this->wordpopEvent[PARSER_EVENT_FUNC_GLOBAL]   = array(";");
2756
        /**************************************************************/
2757
 
2758
        $this->tokenpushEvent[PARSER_EVENT_STATIC_VAR] =
2759
            array(
2760
                T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
2761
                T_COMMENT                  => PARSER_EVENT_COMMENT,
2762
                T_DOC_COMMENT              => PARSER_EVENT_COMMENT,
2763
            );
2764
        $this->wordpushEvent[PARSER_EVENT_STATIC_VAR]  =
2765
            array(
2766
                "=" => PARSER_EVENT_STATIC_VAR_VALUE,
2767
            );
2768
        $this->wordpopEvent[PARSER_EVENT_STATIC_VAR]   = array(";");
2769
        /**************************************************************/
2770
 
2771
        $this->tokenpushEvent[PARSER_EVENT_STATIC_VAR_VALUE] =
2772
            array(
2773
                T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
2774
                T_COMMENT                  => PARSER_EVENT_COMMENT,
2775
                T_DOC_COMMENT              => PARSER_EVENT_COMMENT,
2776
                T_ARRAY                    => PARSER_EVENT_ARRAY,
2777
            );
2778
        $this->wordpushEvent[PARSER_EVENT_STATIC_VAR_VALUE]  =
2779
            array(
2780
                '"' => PARSER_EVENT_QUOTE,
2781
                "'" => PARSER_EVENT_QUOTE,
2782
            );
2783
        $this->wordpopEvent[PARSER_EVENT_STATIC_VAR_VALUE]   = array(";",",");
2784
        /**************************************************************/
2785
 
2786
        $this->tokenpushEvent[PARSER_EVENT_DEFINE] =
2787
            array(
2788
                T_COMMENT                  => PARSER_EVENT_COMMENT,
2789
                T_DOC_COMMENT              => PARSER_EVENT_COMMENT,
2790
                T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
2791
            );
2792
        $this->wordpushEvent[PARSER_EVENT_DEFINE]  =
2793
            array(
2794
                "(" => PARSER_EVENT_DEFINE_PARAMS,
2795
            );
2796
        $this->wordpopEvent[PARSER_EVENT_DEFINE]   = array(";");
2797
        /**************************************************************/
2798
 
2799
        $this->tokenpushEvent[PARSER_EVENT_INCLUDE] =
2800
            array(
2801
                T_COMMENT     => PARSER_EVENT_COMMENT,
2802
                T_DOC_COMMENT => PARSER_EVENT_COMMENT,
2803
            );
2804
        $this->wordpushEvent[PARSER_EVENT_INCLUDE]  =
2805
            array(
2806
                "(" => PARSER_EVENT_INCLUDE_PARAMS,
2807
            );
2808
        $this->wordpopEvent[PARSER_EVENT_INCLUDE]   = array(";");
2809
        /**************************************************************/
2810
 
2811
        $this->tokenpushEvent[PARSER_EVENT_DEFINE_PARAMS] =
2812
            array(
2813
                T_COMMENT       => PARSER_EVENT_COMMENT,
2814
                T_DOC_COMMENT   => PARSER_EVENT_COMMENT,
2815
                T_START_HEREDOC => PARSER_EVENT_EOFQUOTE,
2816
            );
2817
        $this->wordpushEvent[PARSER_EVENT_DEFINE_PARAMS]  =
2818
            array(
2819
                "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
2820
                '"' => PARSER_EVENT_QUOTE,
2821
                "'" => PARSER_EVENT_QUOTE,
2822
            );
2823
        $this->wordpopEvent[PARSER_EVENT_DEFINE_PARAMS]   = array(")");
2824
        /**************************************************************/
2825
 
2826
        $this->tokenpushEvent[PARSER_EVENT_INCLUDE_PARAMS] =
2827
            array(
2828
                T_COMMENT     => PARSER_EVENT_COMMENT,
2829
                T_DOC_COMMENT => PARSER_EVENT_COMMENT,
2830
            );
2831
        $this->wordpushEvent[PARSER_EVENT_INCLUDE_PARAMS]  =
2832
            array(
2833
                "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
2834
            );
2835
        $this->wordpopEvent[PARSER_EVENT_INCLUDE_PARAMS]   = array(")");
2836
        /**************************************************************/
2837
 
2838
        $this->tokenpushEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] =
2839
            array(
2840
                T_COMMENT     => PARSER_EVENT_COMMENT,
2841
                T_DOC_COMMENT => PARSER_EVENT_COMMENT,
2842
            );
2843
        $this->wordpushEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS]  =
2844
            array(
2845
                "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
2846
                '"' => PARSER_EVENT_QUOTE,
2847
                "'" => PARSER_EVENT_QUOTE,
2848
            );
2849
        $this->wordpopEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS]   = array(")");
2850
        /**************************************************************/
2851
 
2852
        $this->tokenpushEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] =
2853
            array(
2854
                T_COMMENT     => PARSER_EVENT_COMMENT,
2855
                T_DOC_COMMENT => PARSER_EVENT_COMMENT,
2856
            );
2857
        $this->wordpushEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS]  =
2858
            array(
2859
                "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
2860
            );
2861
        $this->wordpopEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS]   = array(")");
2862
        /**************************************************************/
2863
 
2864
        $this->tokenpushEvent[PARSER_EVENT_VAR] =
2865
            array(
2866
                T_COMMENT     => PARSER_EVENT_COMMENT,
2867
                T_DOC_COMMENT => PARSER_EVENT_COMMENT,
2868
                T_ARRAY       => PARSER_EVENT_VAR_ARRAY,
2869
            );
2870
        $this->wordpopEvent[PARSER_EVENT_VAR]   = array(";");
2871
        /**************************************************************/
2872
 
2873
        $this->tokenpushEvent[PARSER_EVENT_CLASS_CONSTANT] =
2874
            array(
2875
                T_COMMENT     => PARSER_EVENT_COMMENT,
2876
                T_DOC_COMMENT => PARSER_EVENT_COMMENT,
2877
                T_ARRAY       => PARSER_EVENT_VAR_ARRAY,
2878
            );
2879
        $this->wordpopEvent[PARSER_EVENT_CLASS_CONSTANT]   = array(";");
2880
        /**************************************************************/
2881
 
2882
        $this->wordpopEvent[PARSER_EVENT_IMPLEMENTS] = array('{');
2883
        /**************************************************************/
2884
 
2885
        $this->tokenpushEvent[PARSER_EVENT_CLASS] =
2886
            array(
2887
                T_ABSTRACT    => PARSER_EVENT_ACCESS_MODIFIER,
2888
                T_PUBLIC      => PARSER_EVENT_ACCESS_MODIFIER,
2889
                T_PRIVATE     => PARSER_EVENT_ACCESS_MODIFIER,
2890
                T_PROTECTED   => PARSER_EVENT_ACCESS_MODIFIER,
2891
                T_STATIC      => PARSER_EVENT_ACCESS_MODIFIER,
2892
                T_IMPLEMENTS  => PARSER_EVENT_IMPLEMENTS,
2893
                T_CONST       => PARSER_EVENT_CLASS_CONSTANT,
2894
                T_FUNCTION    => PARSER_EVENT_FUNCTION,
2895
                T_VAR         => PARSER_EVENT_VAR,
2896
                T_COMMENT     => PARSER_EVENT_DOCBLOCK,
2897
                T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
2898
                T_CLOSE_TAG   => PARSER_EVENT_OUTPHP,
2899
            );
2900
        $this->wordpopEvent[PARSER_EVENT_CLASS]   = array("}");
2901
        /**************************************************************/
2902
 
2903
        $this->tokenpushEvent[PARSER_EVENT_DEFINE_GLOBAL] =
2904
            array(
2905
                T_COMMENT     => PARSER_EVENT_COMMENT,
2906
                T_DOC_COMMENT => PARSER_EVENT_COMMENT,
2907
            );
2908
        $this->wordpushEvent[PARSER_EVENT_DEFINE_GLOBAL]  =
2909
            array(
2910
                "=" => PARSER_EVENT_GLOBAL_VALUE,
2911
            );
2912
        $this->wordpopEvent[PARSER_EVENT_DEFINE_GLOBAL]   = array(";");
2913
        /**************************************************************/
2914
 
2915
        $this->tokenpushEvent[PARSER_EVENT_GLOBAL_VALUE] =
2916
            array(
2917
                T_ARRAY         => PARSER_EVENT_ARRAY,
2918
                T_COMMENT       => PARSER_EVENT_COMMENT,
2919
                T_DOC_COMMENT   => PARSER_EVENT_COMMENT,
2920
                T_START_HEREDOC => PARSER_EVENT_EOFQUOTE,
2921
            );
2922
        $this->wordpushEvent[PARSER_EVENT_GLOBAL_VALUE]  =
2923
            array(
2924
                '"' => PARSER_EVENT_QUOTE,
2925
                "'" => PARSER_EVENT_QUOTE,
2926
            );
2927
        $this->wordpopEvent[PARSER_EVENT_GLOBAL_VALUE]   = array(";");
2928
    }
2929
 
2930
    /**
2931
     * initializes all the setup
2932
     *
2933
     * @param mixed &$data the data parser (?)
2934
     *
2935
     * @return void
2936
     */
2937
    function configWordParser(&$data)
2938
    {
2939
        $this->_wp->setup($data);
2940
        $this->_wp->setWhitespace(false);
2941
    }
2942
 
2943
    /**#@-*/
2944
 
2945
}
2946
?>