home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 June / ENTER.ISO / files / xampp-win32-1.4.5-installer.exe / xampp / Parser.inc < prev    next >
Encoding:
Text File  |  2004-03-24  |  130.5 KB  |  3,099 lines

  1. <?php
  2. //
  3. // +------------------------------------------------------------------------+
  4. // | phpDocumentor                                                          |
  5. // +------------------------------------------------------------------------+
  6. // | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver                 |
  7. // | Email         jeichorn@phpdoc.org, cellog@phpdoc.org                   |
  8. // | Web           http://www.phpdoc.org                                    |
  9. // | Mirror        http://phpdocu.sourceforge.net/                          |
  10. // | PEAR          http://pear.php.net/package-info.php?pacid=137           |
  11. // +------------------------------------------------------------------------+
  12. // | This source file is subject to version 3.00 of the PHP License,        |
  13. // | that is available at http://www.php.net/license/3_0.txt.               |
  14. // | If you did not receive a copy of the PHP license and are unable to     |
  15. // | obtain it through the world-wide-web, please send a note to            |
  16. // | license@php.net so we can mail you a copy immediately.                 |
  17. // +------------------------------------------------------------------------+
  18. //
  19.  
  20. /**
  21.  * @package     phpDocumentor
  22.  * @subpackage Parsers
  23.  */
  24. /** used when a backslash is encountered in parsing a string or other escapable entity */ 
  25. define("PARSER_EVENT_ESCAPE"        ,    900);
  26. /** used when a backslash is encountered in parsing a string or other escapable entity */ 
  27. define("STATE_ESCAPE"            ,    1000);
  28.  
  29. /** Class published to IntermediateParser with this event */
  30. define("PHPDOCUMENTOR_EVENT_CLASS"        ,    800);
  31. /** DocBlock published to IntermediateParser with this event */
  32. define("PHPDOCUMENTOR_EVENT_DOCBLOCK"        ,    801);
  33. /** Function published to IntermediateParser with this event */
  34. define("PHPDOCUMENTOR_EVENT_FUNCTION"        ,    802);
  35. /** Class Variable published to IntermediateParser with this event */
  36. define("PHPDOCUMENTOR_EVENT_VAR"        ,    803);
  37. /** New File (page) published to IntermediateParser with this event */
  38. define("PHPDOCUMENTOR_EVENT_PAGE"        ,    804);
  39. /** Constant (define) published to IntermediateParser with this event */
  40. define("PHPDOCUMENTOR_EVENT_DEFINE"        ,    805);
  41. /** @deprecated */
  42. define("PHPDOCUMENTOR_EVENT_MESSAGE"        ,    806);
  43. /** use to inform IntermediateParser of a new element being parsed */
  44. define("PHPDOCUMENTOR_EVENT_NEWSTATE"        ,    807);
  45. /**
  46.  * used to inform phpDocumentor_IntermediateParser that the current file has been completely parsed.
  47.  * Render then flushes all buffers for functions/classes/defines/includes on the current page
  48.  * @see phpDocumentor_IntermediateParser::HandleEvent()
  49.  */
  50. define("PHPDOCUMENTOR_EVENT_END_PAGE"        ,    808);
  51. /** Package-level page published to IntermediateParser with this event */
  52. define("PHPDOCUMENTOR_EVENT_PACKAGEPAGE"        ,    809);
  53. /** Include (include/require/include_once/include_once) published to IntermediateParser with this event */
  54. define("PHPDOCUMENTOR_EVENT_INCLUDE"        ,    810);
  55. /** Tutorial published to IntermediateParser with this event */
  56. define("PHPDOCUMENTOR_EVENT_TUTORIAL"        ,    811);
  57. /** Contents of README/INSTALL/CHANGELOG files published to IntermediateParser with this event */
  58. define("PHPDOCUMENTOR_EVENT_README_INSTALL_CHANGELOG"        ,    812);
  59.  
  60. /** use to inform ErrorTracker of a new file being parsed */
  61. define("PHPDOCUMENTOR_EVENT_NEWFILE"    ,    811);
  62. /** use to inform ErrorTracker of the next line number being parsed */
  63. define("PHPDOCUMENTOR_EVENT_NEWLINENUM"    ,    812);
  64. /** used when a global variable definition is encountered in the source */
  65. define("PHPDOCUMENTOR_EVENT_GLOBAL"    ,    813);
  66. /** used when a docblock template is encountered in the source */
  67. define("PHPDOCUMENTOR_EVENT_DOCBLOCK_TEMPLATE"    ,    814);
  68. /** used when a docblock template is encountered in the source */
  69. define("PHPDOCUMENTOR_EVENT_END_DOCBLOCK_TEMPLATE"    ,    815);
  70. /** used when double quotation mark (") encountered in parsing */
  71. define("PARSER_EVENT_QUOTE"        ,    101);
  72. /** currently parsing a quote */
  73. define("STATE_QUOTE"            ,    201);
  74.  
  75. /** { encountered in parsing a function or php code */
  76. define("PARSER_EVENT_LOGICBLOCK"    ,    102);
  77. /** currently parsing a { } block */
  78. define("STATE_LOGICBLOCK"        ,    202);
  79.  
  80. /** used for the beginning of parsing, before first < ? php encountered */
  81. define("PARSER_EVENT_NOEVENTS"        ,    103);
  82. /** out of < ? php tag */
  83. define("STATE_NOEVENTS"            ,    203);
  84.  
  85. /** used when long comment /x x/ where x is an asterisk is encountered in parsing */
  86. define("PARSER_EVENT_COMMENTBLOCK"    ,    104);
  87. /** currently parsing a long comment /x x/ where x is an asterisk */
  88. define("STATE_COMMENTBLOCK"        ,    204);
  89.  
  90. /** used when short comment // is encountered in parsing */
  91. define("PARSER_EVENT_COMMENT"        ,    105);
  92. /** currently parsing a short comment // */
  93. define("STATE_COMMENT"            ,    205);
  94.  
  95. /** used when php code processor instruction (< ? php) is encountered in parsing */
  96. define("PARSER_EVENT_PHPCODE"        ,    106);
  97. /** currently parsing php code */
  98. define("STATE_PHPCODE"            ,    206);
  99.  
  100. /** used when a define statement is encountered in parsing */
  101. define("PARSER_EVENT_DEFINE"        ,    107);
  102. /** currently parsing a define statement */
  103. define("STATE_DEFINE"            ,    207);
  104.  
  105. /** used when a define statement opening parenthesis is encountered in parsing */
  106. define("PARSER_EVENT_DEFINE_PARAMS"    ,    108);
  107. /** currently parsing the stuff in ( ) of a define statement */
  108. define("STATE_DEFINE_PARAMS"        ,    208);
  109.  
  110. /** used when a function statement opening parenthesis is encountered in parsing */
  111. define("PARSER_EVENT_FUNCTION_PARAMS"    ,    109);
  112. /** currently parsing the stuff in ( ) of a function definition */
  113. define("STATE_FUNCTION_PARAMS"        ,    209);
  114.  
  115. /** used when a single quote (') is encountered in parsing */
  116. define("PARSER_EVENT_SINGLEQUOTE"    ,    110);
  117. /** currently parsing a string enclosed in single quotes (') */
  118. define("STATE_SINGLEQUOTE"        ,    210);
  119.  
  120. /** used when a class definition is encountered in parsing */
  121. define("PARSER_EVENT_CLASS"        ,    111);
  122. /** currently parsing a class definition */
  123. define("STATE_CLASS"            ,    211);
  124. /** used to tell Render that a class has been completely parsed, and to flush buffers */
  125. define("STATE_END_CLASS"        ,    311);
  126.  
  127. /** used when a DocBlock is encountered in parsing */
  128. define("PARSER_EVENT_DOCBLOCK"        ,    112);
  129. /** currently parsing a DocBlock */
  130. define("STATE_DOCBLOCK"            ,    212);
  131.  
  132. /** used when a @tag is encountered in DocBlock parsing */
  133. define("PARSER_EVENT_DOCKEYWORD"    ,    113);
  134. /** currently parsing a @tag in a DocBlock */
  135. define("STATE_DOCKEYWORD"        ,    213);
  136.  
  137. /** used when a <email@address> is encountered in parsing an @author tag*/
  138. define("PARSER_EVENT_DOCKEYWORD_EMAIL"    ,    114);
  139. /** currently parsing an email in brackets in an @author tag of a DocBlock */
  140. define("STATE_DOCKEYWORD_EMAIL"        ,    214);
  141.  
  142. /** used when an array definition is encountered in parsing */
  143. define("PARSER_EVENT_ARRAY"        ,    115);
  144. /** currently parsing an array */
  145. define("STATE_ARRAY"            ,    215);
  146.  
  147. /** used when a var statement is encountered in parsing a class definition */
  148. define("PARSER_EVENT_VAR"        ,    116);
  149. /** currently parsing a Class variable */
  150. define("STATE_VAR"            ,    216);
  151.  
  152. /** used when a function definition is encountered in parsing */
  153. define("PARSER_EVENT_FUNCTION"        ,    117);
  154. /** currently parsing a Function or Method */
  155. define("STATE_FUNCTION"            ,    217);
  156.  
  157. /** used when a ? > (with no space) is encountered in parsing */
  158. define("PARSER_EVENT_OUTPHP"        ,    118);
  159. /** currently out of php code */
  160. define("STATE_OUTPHP"            ,    218);
  161.  
  162. /** used when an inline {@tag} is encountered in parsing a DocBlock */
  163. define("PARSER_EVENT_INLINE_DOCKEYWORD"    ,    119);
  164. /** currently parsing an inline tag like { @link} in a DocBlock */
  165. define("STATE_INLINE_DOCKEYWORD"        ,    219);
  166.  
  167. /** used when a define statement's opening parenthesis is encountered in parsing */
  168. define("PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS"    ,    120);
  169. /** currently parsing an inner parenthetical statement of a define( ) */
  170. define("STATE_DEFINE_PARAMS_PARENTHESIS"        ,    220);
  171.  
  172. define("PARSER_EVENT_END_STATEMENT",    121);
  173.  
  174. /** used when a <<< is encountered in parsing */
  175. define("PARSER_EVENT_EOFQUOTE"    ,    122);
  176. /** currently parsing a string defined using Perl <<< */
  177. define("STATE_EOFQUOTE"        ,    222);
  178.  
  179. /** used when an include/require/include_once/include_once statement is encountered in parsing */
  180. define("PARSER_EVENT_INCLUDE"    ,    123);
  181. /** currently parsing an include/require/include_once/include_once */
  182. define("STATE_INCLUDE"    ,    223);
  183.  
  184. /** used when an opening parenthesis of an include/require/include_once/include_once statement is encountered in parsing */
  185. define("PARSER_EVENT_INCLUDE_PARAMS"    ,    124);
  186. /** currently parsing the stuff in ( ) of a define statement */
  187. define("STATE_INCLUDE_PARAMS"    ,    224);
  188.  
  189. /** used when an inner ( ) is encountered while parsing an include/require/include_once/include_once statement */
  190. define("PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS"    ,    125);
  191. /** currently parsing an inner parenthetical statement of an include/includeonce/require/requireonce( ) */
  192. define("STATE_INCLUDE_PARAMS_PARENTHESIS"    ,    225);
  193.  
  194. /** used when parsing the desc part of a docblock */
  195. define("PARSER_EVENT_DESC"    ,    126);
  196. /** currently parsing the desc part of a docblock */
  197. define("STATE_DESC"    ,    226);
  198.  
  199. /** used when parsing the @tag block of a docblock */
  200. define("PARSER_EVENT_TAGS"    ,    127);
  201. /** currently parsing the @tag block of a docblock */
  202. define("STATE_TAGS"    ,    227);
  203.  
  204. /** used when parsing a global variable declaration */
  205. define("PARSER_EVENT_DEFINE_GLOBAL"    ,    128);
  206. /** currently parsing a global variable declaration */
  207. define("STATE_GLOBAL"    ,    228);
  208.  
  209. /** used when parsing the default value in a global variable declaration */
  210. define("PARSER_EVENT_GLOBAL_VALUE"    ,    129);
  211. /** currently parsing the default value in a global variable declaration */
  212. define("STATE_GLOBAL_VALUE"    ,    229);
  213.  
  214. /** used when parsing a "global $var1, $var2;" declaration in a function */
  215. define("PARSER_EVENT_FUNC_GLOBAL"    ,    130);
  216. /** currently parsing a "global $var1, $var2;" declaration in a function */
  217. define("STATE_FUNC_GLOBAL"    ,    230);
  218.  
  219. /** used when parsing a "static $var1, $var2;" declaration in a function */
  220. define("PARSER_EVENT_STATIC_VAR"    ,    131);
  221. /** currently parsing a "static $var1, $var2;" declaration in a function */
  222. define("STATE_STATIC_VAR"    ,    231);
  223.  
  224. /** used when parsing the value in a "static $var1 = x" declaration in a function */
  225. define("PARSER_EVENT_STATIC_VAR_VALUE"    ,    132);
  226. /** currently parsing the value in a "static $var1 = x" declaration in a function */
  227. define("STATE_STATIC_VAR_VALUE"    ,    232);
  228.  
  229. /** used when encountering a /**#@+ comment marking a new docblock template */
  230. define("PARSER_EVENT_DOCBLOCK_TEMPLATE"    ,    133);
  231. /** currently parsing the value in a "static $var1 = x" declaration in a function */
  232. define("STATE_DOCBLOCK_TEMPLATE"    ,    233);
  233.  
  234. /** used when encountering a /**#@-* / comment (no space) marking the end of using a docblock template */
  235. define("PARSER_EVENT_END_DOCBLOCK_TEMPLATE"    ,    134);
  236. /** currently parsing the value in a "static $var1 = x" declaration in a function */
  237. define("STATE_END_DOCBLOCK_TEMPLATE"    ,    234);
  238.  
  239. /** used by the {@link HighlightParser} only, when a method starts */
  240. define("PARSER_EVENT_METHOD"    ,    135);
  241. /** currently parsing a method using the {@link HighlightParser} */
  242. define("STATE_METHOD"    ,    235);
  243.  
  244. /** used by the {@link HighlightParser} only, when a method body is parsed */
  245. define("PARSER_EVENT_METHOD_LOGICBLOCK"    ,    136);
  246. /** currently parsing the method body using the {@link HighlightParser} */
  247. define("STATE_METHOD_LOGICBLOCK"    ,    236);
  248.  
  249. /** used by the {@link HighlightParser} only, when ->var or ->function() is encountered in a method */
  250. define("PARSER_EVENT_CLASS_MEMBER"    ,    137);
  251. /** currently parsing a class member using the {@link HighlightParser} */
  252. define("STATE_CLASS_MEMBER"    ,    237);
  253.  
  254. /** used by the {@link HighlightParser} only, when {$var} is encountered in a string */
  255. define("PARSER_EVENT_QUOTE_VAR"    ,    138);
  256. /** currently parsing a {$encapsed_var} using the {@link HighlightParser} */
  257. define("STATE_QUOTE_VAR"    ,    238);
  258.  
  259. /**
  260.  * PHP Parser for PHP 4.2.3-
  261.  *
  262.  * This parser is slower than the tokenizer-based parser, and is deprecated.
  263.  * @author    Joshua Eichorn <jeichorn@phpdoc.org>
  264.  * @author    Gregory Beaver <cellog@users.sourceforge.net>
  265.  * @version    $Id: Parser.inc,v 1.183.2.7 2003/08/19 15:47:14 CelloG Exp $
  266.  * @package     phpDocumentor
  267.  * @subpackage Parsers
  268.  * @deprecated in favor of {@link phpDocumentorTParser}
  269.  */
  270. class Parser extends Publisher
  271. {
  272.     /**#@+
  273.      * @access private
  274.      */
  275.     /**
  276.      * Word parser
  277.      * @see WordParser
  278.      */
  279.     var $wp;
  280.     
  281.     /**
  282.      * temporary parser variables
  283.      */
  284.     var $p_vars = array('func' => false, 'function_data' => '', 'quote_data' => '', 'event_stack' => false, 'last_pevent' => 0,
  285.                         'two_words_ago' => '', 'temp_word' => '', 'docblock' => false, 'line' => array(), 'linecount' => 0, 'startword' => '',
  286.                         'periodline' => 0, 'shortdesc' => '', 'docblock_desc' => '', 'class' => false, 'source_location' => '',
  287.                         'define_params_data' => '', 'define' => false, 'define_name' => '', 'define_value' => '', 'var' => false,
  288.                         'oldtoken' => false, 'comment_data' => '', 'function_param' => NULL, 'inline_dockeyword_type' => false,
  289.                         'inline_dockeyword_data' => false, 'dockeyword_type' => false, 'dockeyword_data' =>false, 'param_var' => false,
  290.                         'include_name' => '', 'include_value' => '','include' => false, 'return_type' => '', 'cur_class' => '',
  291.                         'function_data' => false, 'varname' => '', 'returntype' => false, 'vartype' => false, 'paramtype' => false,
  292.                         'tagname' => '', 'find_global' => '', 'global_type' => '', 'paramname' => false, 'statics' => array(),
  293.                         'static_count' => 0, 'static_val' => array(), 'docblock_type' => 'docblock', 'seelement' => false);
  294.     
  295.     /**
  296.      * parser flags, for states that don't warrant a new event (like new line in a docblock)
  297.      */
  298.     var $p_flags = array('docblocknewline' => false, 'docblockintags' => false, 'useperiod' => false,
  299.                         'definename_isset' => false, 'define_parens' => false, 'reset_quote_data' => false,
  300.                         'in_desc' => true, 'in_tag' => false, 'newline' => true, 'tempnewline' => false,
  301.                         'start_docblock' => false, 'includename_isset' => false, 'return_isset' => false,
  302.                         'is_return' => false, 'in_class' => false, 'asterisk' => false, 'var_equals' => false,
  303.                         'arrayinvarname' => false, 'valid_newline' => true, 'startline' => false,
  304.                         'function_global' => false, 'define_global' => false, 'static_value' => false,'funcparam_val' => false,
  305.                         'get_source' => false, 'getting_source' => false);
  306.  
  307.     /**
  308.      * lookup table for event handler methods
  309.      * @see Parser::parse()
  310.      */
  311.     var $eventHandlers = array(
  312.                                 'handleArray' => PARSER_EVENT_ARRAY,
  313.                                 'handleClass' => PARSER_EVENT_CLASS,
  314.                                 'handleComment' => PARSER_EVENT_COMMENT,
  315.                                 'handleDocBlockTemplate' => PARSER_EVENT_DOCBLOCK_TEMPLATE,
  316.                                 'handleEndDocBlockTemplate' => PARSER_EVENT_END_DOCBLOCK_TEMPLATE,
  317.                                 'handleEscape' => PARSER_EVENT_ESCAPE,
  318.                                 'handleLogicBlock' => PARSER_EVENT_LOGICBLOCK,
  319.                                 'defaultHandler' => PARSER_EVENT_NOEVENTS,
  320. //                                'defaultHandler' => PARSER_EVENT_COMMENTBLOCK, (set in constructor below)
  321. //                                'defaultHandler' => PARSER_EVENT_OUTPHP,
  322.                                 'handleDefine' => PARSER_EVENT_DEFINE,
  323.                                 'handleDefineParams' => PARSER_EVENT_DEFINE_PARAMS,
  324.                                 'handleDefineParamsParenthesis' => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
  325.                                 'handleIncludeParamsParenthesis' => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
  326. //                                'handleDocBlock' => PARSER_EVENT_DOCBLOCK,
  327.                                 'BetterhandleDocBlock' => PARSER_EVENT_DOCBLOCK,
  328.                                 'handleTags' => PARSER_EVENT_TAGS,
  329.                                 'handleDesc' => PARSER_EVENT_DESC,
  330. //                                'handleDockeyword' => PARSER_EVENT_DOCKEYWORD,
  331.                                 'handleTag' => PARSER_EVENT_DOCKEYWORD,
  332.                                 'handleDockeywordEmail' => PARSER_EVENT_DOCKEYWORD_EMAIL,
  333.                                 'handleEOFQuote' => PARSER_EVENT_EOFQUOTE,
  334.                                 'handleFunction' => PARSER_EVENT_FUNCTION,
  335.                                 'handleFunctionParams' => PARSER_EVENT_FUNCTION_PARAMS,
  336.                                 'handleFuncGlobal' => PARSER_EVENT_FUNC_GLOBAL,
  337.                                 'handleGlobal' => PARSER_EVENT_DEFINE_GLOBAL,
  338.                                 'handleGlobalValue' => PARSER_EVENT_GLOBAL_VALUE,
  339.                                 'handleInlineDockeyword' => PARSER_EVENT_INLINE_DOCKEYWORD,
  340.                                 'handleInclude' => PARSER_EVENT_INCLUDE,
  341.                                 'handleIncludeParams' => PARSER_EVENT_INCLUDE_PARAMS,
  342.                                 'handleQuote' => PARSER_EVENT_QUOTE,
  343.                                 'handlePhpCode' => PARSER_EVENT_PHPCODE,
  344.                                 'handleSingleQuote' => PARSER_EVENT_SINGLEQUOTE,
  345.                                 'handleStaticVar' => PARSER_EVENT_STATIC_VAR,
  346.                                 'handleStaticValue' => PARSER_EVENT_STATIC_VAR_VALUE,
  347.                                 'handleVar' => PARSER_EVENT_VAR,
  348.     );
  349.     
  350.     /**
  351.      * event handlers for @tags
  352.      * @tutorial tags.pkg
  353.      */
  354.     var $tagHandlers = array(
  355.                                 '*' => 'defaultTagHandler',
  356.                                 'category' => 'categoryTagHandler',
  357.                                 'example' => 'exampleTagHandler',
  358.                                 'filesource' => 'invalidTagHandler',
  359.                                 'return' => 'returnTagHandler',
  360.                                 'returns' => 'returnTagHandler',
  361.                                 'var' => 'varTagHandler',
  362.                                 'package' => 'packageTagHandler',
  363.                                 'param' => 'paramTagHandler',
  364.                                 'parameter' => 'paramTagHandler',
  365.                                 'global' => 'globalTagHandler',
  366.                                 'staticvar' => 'staticvarTagHandler',
  367.                                 'uses' => 'usesTagHandler'
  368.                             );
  369.  
  370.     var $laststart = false;
  371.  
  372.     /**
  373.      * An array of allowable @tags
  374.      */
  375.     var $allowableTags;
  376.  
  377.  
  378.     /**
  379.      * An array of allowed inline @tags
  380.      */
  381.     var $allowableInlineTags;
  382.     
  383.     /**
  384.      * Sets the states up, and creates a new WordParser
  385.      */
  386.     
  387.     /**
  388.      * an array of parsing tokens organized by event number.
  389.      * A token is defined as the smallest group of characters that separates or
  390.      * defines a new parser element.  In English, a space or punctuation are
  391.      * tokens that separate words.  in PHP, tokens may be //, or even "
  392.      * Format: array(eventnum =>array(token1, token2, token3, ...),...)
  393.      * @var array
  394.      */
  395.     var $tokens;
  396.     
  397.     /**
  398.      * array of events that are raised, organized by the tokens that raise them.
  399.      * Format: array(eventnum => array(token => neweventnum, token2 => neweventnum2,...),...)
  400.      * @var array
  401.      */
  402.     var $pushEvent;
  403.     
  404.     /**
  405.      * array of tokens that end an event, organized by event
  406.      * Format: array(eventnum => array(token => neweventnum, token2 => neweventnum2,...),...)
  407.      * @var array
  408.      */
  409.     var $popEvent;
  410.     /**#@-*/
  411.     
  412.     /**
  413.      * Set up invariant parsing variables
  414.      */
  415.     function Parser()
  416.     {
  417.         $this->allowableTags = $GLOBALS['_phpDocumentor_tags_allowed'];
  418.         $this->allowableInlineTags = $GLOBALS['_phpDocumentor_inline_doc_tags_allowed'];
  419.         $this->wp = new WordParser;
  420.         // strange PHP 4.0.6 behavior: it converts constants to strings without warning if it's an array index
  421.         $this->eventHandlers = array_flip($this->eventHandlers);
  422.         $this->eventHandlers[PARSER_EVENT_COMMENTBLOCK] = 'defaultHandler';
  423.         $this->eventHandlers[PARSER_EVENT_OUTPHP] = 'defaultHandler';
  424.         $this->subscribe(PHPDOCUMENTOR_EVENT_NEWLINENUM,$GLOBALS['phpDocumentor_errors']);
  425.         $this->subscribe(PHPDOCUMENTOR_EVENT_NEWFILE,$GLOBALS['phpDocumentor_errors']);
  426.     }
  427.  
  428.     /**
  429.      * Parse a new file
  430.      *
  431.      * @param    string    $parse_data
  432.      * @param    string    $path
  433.      * @param    int    $base    number of directories to drop off the bottom when creating names using path
  434.      * @staticvar    integer    used for recursion limiting if a handler for an event is not found
  435.      * @return    bool
  436.      */
  437.     function parse (&$parse_data, $path, $base = 0, $packages = false)
  438.     {
  439.         global $_phpDocumentor_options;
  440.         static $endrecur = 0;
  441.         $this->p_vars = array('func' => false, 'function_data' => '', 'quote_data' => '', 'event_stack' => false, 'last_pevent' => 0,
  442.                         'two_words_ago' => '', 'temp_word' => '', 'docblock' => false, 'line' => array(), 'linecount' => 0, 'startword' => '',
  443.                         'periodline' => 0, 'shortdesc' => '', 'docblock_desc' => '', 'class' => false, 'source_location' => '',
  444.                         'define_params_data' => '', 'define' => false, 'define_name' => '', 'define_value' => '', 'var' => false,
  445.                         'oldtoken' => false, 'comment_data' => '', 'function_param' => NULL, 'inline_dockeyword_type' => false,
  446.                         'inline_dockeyword_data' => false, 'dockeyword_type' => false, 'dockeyword_data' =>false, 'param_var' => false,
  447.                         'include_name' => '', 'include_value' => '','include' => false, 'return_type' => '', 'cur_class' => '',
  448.                         'function_data' => false, 'varname' => '', 'returntype' => false, 'vartype' => false, 'paramtype' => false,
  449.                         'tagname' => '', 'find_global' => '', 'global_type' => '', 'paramname' => false, 'statics' => array(),
  450.                         'static_count' => 0, 'static_val' => array(), 'docblock_type' => 'docblock', 'linenum' => false,
  451.                         'seelement' => false);
  452.     
  453.         $this->p_flags = array('docblocknewline' => false, 'docblockintags' => false, 'useperiod' => false,
  454.                         'definename_isset' => false, 'define_parens' => false, 'reset_quote_data' => false,
  455.                         'in_desc' => true, 'in_tag' => false, 'newline' => true, 'tempnewline' => false,
  456.                         'start_docblock' => false, 'includename_isset' => false, 'return_isset' => false,
  457.                         'is_return' => false, 'in_class' => false, 'asterisk' => false, 'var_equals' => false,
  458.                         'arrayinvarname' => false, 'valid_newline' => true, 'startline' => false,
  459.                         'function_global' => false, 'define_global' => false, 'static_value' => false,'funcparam_val' => false,
  460.                         'get_source' => false, 'getting_source' => false, 'in_define' => false, 'in_include' => false,
  461.                         'in_var' => false, 'in_global' => false);
  462.         $this->p_vars['parsepath'] = $path;
  463.         $this->setupStates();
  464.         if (strlen($parse_data) == 0)
  465.         {
  466.             return false;
  467.         }
  468.  
  469.         // initialize variables so E_ALL error_reporting doesn't complain
  470.         $pevent = 0;
  471.         $word = 0;
  472.         $this->p_vars['event_stack'] = new EventStack;
  473.  
  474.         $this->wp->setup($parse_data);
  475.         
  476.  
  477.         $page = new ParserPage;
  478.         $page->setPath($path);
  479.         $page->setPackageOutput($packages);
  480.         $page->setFile(basename($path));
  481.         $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWFILE,basename($path));
  482.         //$name = str_replace("/","_",dirname($path)) . "_" . array_shift(explode(".",$page->getFile()));
  483.         // fc@fc.clever-soft.com 11/29/2001
  484.         $name = str_replace(PATH_DELIMITER,"_",dirname($path)) . "_" .  str_replace(".","_",$page->getFile());
  485.         $tmp = explode("_",$name);
  486.         $name = str_replace(':','_',implode("_",array_slice($tmp,$base)));
  487.         // if base is '', drive letter is present in windows
  488.  
  489.         $page->setName($name);
  490.         $temploc = $_phpDocumentor_options['Program_Root'] . PATH_DELIMITER. implode(PATH_DELIMITER,
  491.             array_slice(explode(PATH_DELIMITER,$path),$base));
  492.         
  493.         if ($temploc == $_phpDocumentor_options['Program_Root'] . PATH_DELIMITER) $temploc .= $path;
  494.         
  495.         $this->p_vars['source_location'] = $source_location = $temploc;
  496.         $page->setSourceLocation($source_location);
  497.  
  498.         $this->publishEvent(PHPDOCUMENTOR_EVENT_PAGE,$page);
  499.         unset($page);
  500.         $this->p_flags['reset_quote_data'] = true;
  501.  
  502.         do
  503.         {
  504.             $lpevent = $pevent;
  505.             $pevent = $this->p_vars['event_stack']->getEvent();
  506.             if ($lpevent != $pevent)
  507.             {
  508.                 $this->p_vars['last_pevent'] = $lpevent;
  509.             }
  510.  
  511.             if ($this->p_vars['last_pevent'] != $pevent)
  512.             {
  513.                 // its a new event so the word parser needs to be reconfigured 
  514.                 $this->configWordParser($pevent);
  515.             }
  516.         
  517.             $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,($pevent + 100));
  518.  
  519.             if ($pevent == PARSER_EVENT_GLOBAL_VALUE || $pevent == PARSER_EVENT_DOCBLOCK || $pevent == PARSER_EVENT_DOCBLOCK_TEMPLATE)
  520.             {
  521.                 $this->wp->setWhitespace(true);
  522.             }
  523.  
  524.             $this->p_vars['last_word'] = $word;
  525.             $word = $this->wp->getWord();
  526.             // in wordparser, have to keep track of lines
  527.             $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWLINENUM, $this->wp->linenum);
  528.  
  529.             if (0)//PHPDOCUMENTOR_DEBUG == true)
  530.             {
  531.                 echo "\nLAST: |" . $this->p_vars['last_word'] . "|\n";
  532.                 echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";
  533.                 echo "LASTPEVENT: " . $this->getParserEventName($this->p_vars['last_pevent']) . "\n";
  534.                 echo $this->wp->getPos() . ": |$word|\n--------------------------\n\n";
  535.             }
  536.             if ($this->p_flags['get_source'])
  537.             {
  538.                 if ($pevent == PARSER_EVENT_FUNCTION)
  539.                 {
  540.                     $this->wp->retrievesource("function $word");
  541.                     $this->p_flags['get_source'] = false;
  542.                     $this->p_flags['getting_source'] = true;
  543.                 }
  544.             }
  545.             if (false)//$this->p_flags['getting_source'] && ($pevent == PARSER_EVENT_DOCBLOCK) || ($pevent == PARSER_EVENT_NOEVENTS))
  546.             {
  547.                 addError(PDERROR_SOURCE_TAG_FUNCTION_NOT_FOUND);
  548.                 // throw away source
  549.                 $this->wp->getSource();
  550.             }
  551.             if (isset($this->eventHandlers[$pevent]))
  552.             {
  553.                 $handle = $this->eventHandlers[$pevent];
  554.                 $this->$handle($word, $pevent);
  555.             } else
  556.             {
  557.                 debug('WARNING: possible error, no handler for event number '.$pevent);
  558.                 if ($endrecur++ == 25)
  559.                 {
  560.                     die("FATAL ERROR, recursion limit reached");
  561.                 }
  562.             }
  563.         } while (!($word === false));
  564.         $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,PHPDOCUMENTOR_EVENT_END_PAGE);
  565.     }
  566.     
  567.     /**#@+
  568.      * @access private
  569.      * @param string token parsed from source
  570.      * @param integer parser constant from {@link Parser.inc}
  571.      */
  572.     /**
  573.      * handler for NOEVENTS, OUTPHP, COMMENTBLOCK
  574.      */
  575.     
  576.     function defaultHandler($word, $pevent)
  577.     {
  578.         $this->checkEventPush( $word, $pevent);
  579.         $this->checkEventPop($word,$pevent);
  580.     }
  581.     
  582.     /**
  583.      * handler for LOGICBLOCK
  584.      *
  585.      * Logic Blocks are the stuff between { and } in a function/method.  A
  586.      * logic block can clearly contain other logic blocks, as in:
  587.      *
  588.      * <code>
  589.      * function test($a)
  590.      * {
  591.      *    if (testcondition)
  592.      *    { // nested logic block
  593.      *    }
  594.      * }
  595.      * </code>
  596.      *
  597.      * So, the exit portion of the logic block handler must check to see if the
  598.      * logic block being exited is the top-level, and it does this by retrieving
  599.      * the last event from the stack.  If it is a function (and not a logic block)
  600.      * then it backs up the word parser so that the function will exit properly.
  601.      *
  602.      * {@source 11}
  603.      */
  604.     
  605.     function handleLogicBlock($word, $pevent)
  606.     {
  607.         $a = $this->checkEventPush( $word, $pevent);
  608.         if ($a == PARSER_EVENT_FUNC_GLOBAL || $a == PARSER_EVENT_STATIC_VAR)
  609.         {
  610.             if (substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != ' ' && substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != "\t" && substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != "\n" && substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != ";" && substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != "}" && substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != "{")
  611.             {
  612.                 $this->p_vars['event_stack']->popEvent();
  613.             }
  614.         }
  615.         if ($this->checkEventPop($word,$pevent))
  616.         {
  617.             $e = $this->p_vars['event_stack']->popEvent();
  618.             $this->p_vars['event_stack']->pushEvent($e);
  619.             if ($e == PARSER_EVENT_FUNCTION)
  620.             {
  621.                 $this->wp->backupPos($word); 
  622.             }
  623.         }
  624.     }
  625.     
  626.     /**
  627.      * handler for ESCAPE.
  628.      * this event handler parses <code>"this string \"with its escape backslashes\""</code> and returns:
  629.      * <code>this string "with its escape backslashes"</code>
  630.      * to make it human-readable
  631.      */
  632.     
  633.     function handleEscape($word, $pevent)
  634.     {
  635.         $this->p_vars['event_stack']->popEvent();
  636.     }
  637.     
  638.     /**
  639.      * handler for COMMENT.
  640.      * this event handler parses single-line comments like:
  641.      * // this one
  642.      */
  643.     
  644.     function handleComment($word, $pevent)
  645.     {
  646.         $this->checkEventPush( $word, $pevent);
  647.     
  648.         if (!isset($this->p_vars['comment_data'])) $this->p_vars['comment_data'] = '';
  649.         $this->p_vars['comment_data'] .= $word;
  650.     
  651.         $this->checkEventPop($word,$pevent);
  652.     }
  653.  
  654.     /**
  655.      * handler for ARRAY.
  656.      * this event handler parses arrays in default values of function and var definitions
  657.      */
  658.     
  659.     function handleArray($word, $pevent)
  660.     {
  661.         $e = $this->checkEventPush( $word, $pevent); 
  662.         if (($e == PARSER_EVENT_COMMENTBLOCK) ||
  663.             ($e == PARSER_EVENT_COMMENT)) return;
  664.  
  665.         if (!isset($this->p_vars['function_data']) || (isset($this->p_vars['function_data']) && empty($this->p_vars['function_data'])))
  666.         {
  667.             $this->p_vars['function_data'] = "array";
  668.         }
  669.  
  670.         if ( ($this->p_vars['last_word'] == "'"))
  671.         {
  672.             $this->p_vars['function_data'] .= $this->p_vars['quote_data']."'";
  673.         }
  674.         if ( ($this->p_vars['last_word'] == "\""))
  675.         {
  676.             $this->p_vars['function_data'] .= $this->p_vars['quote_data']."\"";
  677.         }
  678.  
  679.         $this->p_vars['function_data'] .= $word;
  680.         //echo "function_data = |$this->p_vars['function_data']|\n";
  681.  
  682.         if ($this->checkEventPop($word,$pevent))
  683.         {
  684.         }
  685.     }
  686.  
  687.     /**
  688.      * handler for DEFINE.
  689.      * handles define(constant, value); statements
  690.      */
  691.     
  692.     function handleDefine($word, $pevent)
  693.     {
  694.         if (!$this->p_flags['in_define'])
  695.         {
  696.             $this->p_vars['linenum'] = $this->wp->linenum;
  697.         }
  698.         $this->p_flags['in_define'] = true;
  699.         $this->checkEventPush( $word, $pevent);
  700.  
  701.         $this->p_flags['definename_isset'] = false;
  702.         $this->p_vars['define_params_data'] = '';
  703.         unset($this->p_vars['quote_data']);
  704.         if ($this->checkEventPop($word,$pevent))
  705.         {
  706.             $this->p_flags['in_define'] = false;
  707.             $this->p_vars['define'] = new parserDefine;
  708.             $this->p_vars['define']->setLineNumber($this->p_vars['linenum']);
  709.             $this->p_vars['define']->setName($this->p_vars['define_name']);
  710.             $this->p_vars['define']->setValue($this->p_vars['define_value']);
  711.             $this->publishEvent(PHPDOCUMENTOR_EVENT_DEFINE,$this->p_vars['define']);
  712.             $this->p_flags['definename_isset'] = false;
  713.             unset($this->p_vars['define']);
  714.             unset($this->p_vars['define_name']);
  715.             unset($this->p_vars['define_value']);
  716.             $this->p_flags['in_define'] = false;
  717.             $this->p_vars['define_params_data'] = '';
  718.         }
  719.     }
  720.     
  721.     /**
  722.      * handler for DEFINE_PARAMS.
  723.      * handles the parsing of constant and value in define(constant, value);
  724.      */
  725.     
  726.     function handleDefineParams($word, $pevent)
  727.     {
  728.         if ($this->checkEventPush( $word, $pevent))
  729.         {
  730.             if ($word == '(')
  731.             {
  732.                 $this->p_vars['define_params_data'] .= $word;
  733.             }
  734.             return;
  735.         }
  736.         
  737.         $this->p_flags['define_parens'] = true;
  738.         if(!isset($this->p_vars['define_params_data'])) $this->p_vars['define_params_data'] = '';
  739.         
  740.         if ($this->checkEventPop($word,$pevent))
  741.         {
  742.             if (!empty($this->p_vars['quote_data']))
  743.             {
  744.                 $this->p_vars['define_params_data'] .= $this->p_vars['quote_data'];
  745.             }
  746.             if (!empty($this->p_vars['define_params_data']))
  747.             {
  748.                 //echo $this->p_vars['define_params_data']."\n";
  749.                 $this->p_vars['define_value'] = $this->p_vars['define_params_data'];
  750.             }
  751.             else
  752.             {
  753.                 if (    $this->p_vars['last_word'] != "/*" && 
  754.                     $this->p_vars['last_word'] != "//" && $this->p_vars['last_word'] != "#")
  755.                 {
  756.                     $this->p_vars['define_value'] = trim($this->p_vars['last_word']);
  757.                 }
  758.                 else
  759.                 {
  760.                     $this->p_vars['define_value'] = "";
  761.                 }
  762.             }
  763.         }
  764.         if ($this->p_flags['definename_isset'])
  765.         {
  766.             if (isset($this->p_vars['quote_data']))
  767.             {
  768.                 $this->p_vars['define_params_data'] .= '"'.$this->p_vars['quote_data'].'"';
  769.                 unset($this->p_vars['quote_data']);
  770.             }
  771.             $this->p_vars['define_params_data'] .= $word;
  772.         } else
  773.         {
  774.             if ($word != ",")
  775.             {
  776.                 if (isset($this->p_vars['quote_data']))
  777.                 {
  778.                     $this->p_vars['define_params_data'] .= $this->p_vars['quote_data'];
  779.                     unset($this->p_vars['quote_data']);
  780.                 }
  781.                 $this->p_vars['define_params_data'] .= $word;
  782.             } else
  783.             {
  784.                 if (isset($this->p_vars['quote_data']) && !$this->p_flags['definename_isset'])
  785.                 {
  786.                     $this->p_vars['define_params_data'] .= $this->p_vars['quote_data'];
  787.                     unset($this->p_vars['quote_data']);
  788.                 }
  789.                 $this->p_flags['definename_isset'] = true;
  790.                 $this->p_vars['define_name'] = $this->p_vars['define_params_data'];
  791.                 unset($this->p_vars['quote_data']);
  792.                 $this->p_vars['define_params_data'] = '';
  793.             }
  794.         }
  795.     }
  796.     
  797.     /**
  798.      * handler for DEFINE_PARAMS_PARENTHESIS.
  799.      * this handler takes all parenthetical statements within constant or value in:
  800.      * define(constant, value) of a define statement, and handles them properly
  801.      */
  802.     
  803.     function handleDefineParamsParenthesis($word, $pevent)
  804.     {
  805.         if (isset($this->p_vars['quote_data']))
  806.         {
  807.             $this->p_vars['define_params_data'] .= '"'.$this->p_vars['quote_data'].'"';
  808.             unset($this->p_vars['quote_data']);
  809.         }
  810.         $this->p_vars['define_params_data'] .= $word;
  811.         $this->checkEventPush( $word, $pevent);
  812.         $this->checkEventPop( $word, $pevent);
  813.     }
  814.  
  815.     /**
  816.      * handler for CLASS.
  817.      * this handler parses a class statement
  818.      */
  819.     
  820.     function handleClass($word, $pevent)
  821.     {
  822.         $this->p_flags['in_class'] = true;
  823.         $a = $this->checkEventPush( $word, $pevent);
  824.         if ($a == PARSER_EVENT_DOCBLOCK || $a == PARSER_EVENT_DOCBLOCK_TEMPLATE)
  825.         {
  826.             $this->wp->setWhitespace(true);
  827.         }
  828.  
  829.         if (!isset($this->p_vars['class'])) $this->p_vars['class'] = false;
  830.         if (!is_subclass_of($this->p_vars['class'],"parserBase"))
  831.         {
  832.             $this->p_vars['class'] = new parserClass;
  833.             $this->p_vars['class']->setLineNumber($this->wp->linenum);
  834.             $this->p_vars['class']->setname($word);
  835.             $this->p_vars['cur_class'] = $word;
  836.             $this->p_vars['class']->setSourceLocation($this->p_vars['source_location']);
  837.         }
  838.  
  839.         if (strtolower($this->p_vars['last_word']) == "extends")
  840.         {
  841.             $this->p_vars['class']->setExtends($word);
  842.         }
  843.  
  844.         if ($word == "{")
  845.         {
  846.             $this->publishEvent(PHPDOCUMENTOR_EVENT_CLASS,$this->p_vars['class']);
  847.         }
  848.         //echo $this->wp->getPos() . ": |$word|\n";
  849.         if ($this->checkEventPop($word,$pevent))
  850.         {
  851.             $this->p_flags['in_class'] = false;
  852.             // throw an event when class is done
  853.             $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,STATE_END_CLASS);
  854.             $this->p_vars['class'] = false;
  855.         }
  856.     }
  857.  
  858.     /**
  859.      * handler for VAR.
  860.      * handle a var $varname = default_value; or var $varname; statement in a class definition
  861.      */
  862.     
  863.     function handleVar($word, $pevent)
  864.     {
  865.         if (!$this->p_flags['in_var'])
  866.         {
  867.             $this->p_vars['linenum'] = $this->wp->linenum;
  868.         }
  869.         $this->p_flags['in_var'] = true;
  870.         //echo $word."\n";
  871.         $e = $this->checkEventPush( $word, $pevent);
  872.         
  873.         if (!isset($this->p_vars['var'])) $this->p_vars['var'] = false;
  874.         if ($word == '=' || $word == ';') $this->p_flags['var_equals'] = true;
  875.         if (!$this->p_flags['var_equals'])
  876.         {
  877.             // if we haven't parsed the = yet, no arrays are possible!
  878.             if ($e == PARSER_EVENT_ARRAY)
  879.             {
  880.                 $this->p_flags['arrayinvarname'] = true;
  881.                 $this->p_vars['event_stack']->popEvent();
  882.             }
  883.             if (!$e || ($e == PARSER_EVENT_ARRAY))
  884.             $this->p_vars['varname'] .= $word;
  885.         }
  886.  
  887.         if (!$this->p_flags['var_equals'])
  888.         {
  889.             if ($word != "/*" && $word != "//" && $word != "#")
  890.             {
  891.                 $this->p_vars['var'] = new parserVar($this->p_vars['cur_class']);
  892.                 $this->p_vars['var']->setName($this->p_vars['varname']);
  893.             }
  894.         }
  895.         if ($this->p_vars['last_word'] == "=")
  896.         {
  897.             if ($word != "/*" && $word != "//" && $word != "#")
  898.             {
  899.                 $this->p_vars['var']->setValue($word);
  900.             }
  901.         }
  902.         if (isset($this->p_vars['quote_data']) && $this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE || $this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE)
  903.         {
  904.             $this->p_vars['var']->setValue($this->p_vars['quote_data']);
  905.             unset($this->p_vars['quote_data']);
  906.         }
  907.         if ($this->p_vars['last_pevent'] == PARSER_EVENT_ARRAY)
  908.         {
  909.             $this->p_vars['var']->setValue($this->p_vars['function_data']);
  910.             $this->p_vars['function_data'] = false;
  911.         }
  912.             
  913.         if ($this->checkEventPop($word,$pevent))
  914.         {
  915.             $this->p_vars['var']->setLineNumber($this->p_vars['linenum']);
  916.             $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR,$this->p_vars['var']);
  917.             unset($this->p_vars['var']);
  918.             $this->p_flags['in_var'] = false;
  919.             $this->p_flags['var_equals'] = false;
  920.             $this->p_flags['arrayinvarname'] = false;
  921.             $this->p_vars['varname'] = '';
  922.         }
  923.     }
  924.  
  925.     /**
  926.      * handler for QUOTE.
  927.      * this handler recognizes strings defined with double quotation marks (") and handles them correctly
  928.      * in any place that they legally appear in php code
  929.      */
  930.     
  931.     function handleQuote($word, $pevent)
  932.     {
  933.         if ($this->p_flags['reset_quote_data'] === true)
  934.         {
  935.             $this->p_flags['reset_quote_data'] = false;
  936.             $this->p_vars['quote_data'] = "";
  937.         }
  938.         $this->checkEventPush( $word, $pevent);
  939.         if ($word != "\"")
  940.         {
  941.             $this->p_vars['quote_data'] .= $word;
  942.         }
  943.         if ($this->checkEventPop($word,$pevent))
  944.         {
  945.             $this->p_flags['reset_quote_data'] = true;
  946.         }
  947.     }
  948.     
  949.     /**
  950.      * handler for SINGLEQUOTE.
  951.      * this handler recognizes strings defined with single quotation marks (') and handles them correctly
  952.      * in any place that they legally appear in php code
  953.      */
  954.     
  955.     function handleSingleQuote($word, $pevent)
  956.     {
  957.         $this->checkEventPush( $word, $pevent);
  958.         if ($this->checkEventPop($word,$pevent))
  959.         {
  960.             if ($this->p_vars['last_word'] != "'")
  961.             {
  962.                 $this->p_vars['quote_data'] = $this->p_vars['last_word'];
  963.             } else {
  964.                 $this->p_vars['quote_data'] = "";
  965.             }
  966.         }
  967.     }
  968.  
  969.     /**
  970.      * handler for EOFQUOTE.
  971.      * this handler recognizes strings defined with perl-style <<< EOF quotes, and handles them correctly
  972.      * in any place that they legally appear in php code
  973.      *
  974.      * an example:
  975.      * <code>$var <<< EOF
  976.      * blah blah blah
  977.      * EOF;</code>
  978.      */
  979.     
  980.     function handleEOFQuote($word, $pevent)
  981.     {
  982.         //    echo $this->wp->getPos() . ": word=|$word|\t\t\tlastword=|$this->p_vars['last_word']|\n";
  983.         if (trim($this->p_vars['last_word']) == "<<<")
  984.         {
  985.             // ok we found the keyword
  986.             //echo "Keyword == $word\n";
  987.             $this->p_vars['oldtoken'] = $this->tokens[STATE_EOFQUOTE];
  988.             $this->tokens[STATE_EOFQUOTE] = array($word);
  989.         } 
  990.         else if ($this->p_vars['last_pevent'] || PARSER_EVENT_EOFQUOTE) 
  991.         {
  992.             // i don't think anything will ever use this so were not going to set it
  993.             //$this->p_vars['quote_data'] = $this->p_vars['last_word']; 
  994.             $this->p_vars['event_stack']->popEvent();
  995.             $this->tokens[STATE_EOFQUOTE] = $this->p_vars['oldtoken'];
  996.         }
  997.     }
  998.     /**#@-*/
  999.  
  1000.     /**
  1001.      * Tells the parser to search for a global variable definition as
  1002.      * defined by a @global type $name tag.
  1003.      *
  1004.      * The parser is fooled into looking for the entire global variable as a
  1005.      * single token by amending the {@link $tokens} array.
  1006.      *
  1007.      * {@source}
  1008.      * @access private
  1009.      * @param string name of global variable as it appears in the source code
  1010.      */
  1011.     function findGlobal($name)
  1012.     {
  1013.         if (!isset($this->p_vars['globaltofind']))
  1014.         {
  1015.             $this->p_vars['globaltofind'] = $name;
  1016.             $this->pushEvent[PARSER_EVENT_PHPCODE][strtolower($name)] = PARSER_EVENT_DEFINE_GLOBAL;
  1017.             $this->tokens[STATE_PHPCODE][] = $name;
  1018.         } else
  1019.         {
  1020.             addError(PDERROR_MULTIPLE_GLOBAL_TAGS,$this->p_vars['globaltofind'],$name);
  1021.         }
  1022.     }
  1023.     
  1024.     /**#@+
  1025.      * @access private
  1026.      * @param string token parsed from source
  1027.      * @param integer parser constant from {@link Parser.inc}
  1028.      */
  1029.     /**
  1030.      * handler for PHPCODE.
  1031.      * this handler recognizes the <code><?</code> php processor directive, and begins parsing php code
  1032.      */
  1033.     
  1034.     function handlePhpCode($word, $pevent)
  1035.     {
  1036.         $e = $this->checkEventPush( $word, $pevent);
  1037.         if ($e == PARSER_EVENT_DOCBLOCK || $e == PARSER_EVENT_DOCBLOCK_TEMPLATE)
  1038.         {
  1039.             $this->wp->setWhitespace(true);
  1040.         }
  1041.         if (isset($this->p_vars['globaltofind']) && $e)
  1042.         {
  1043.             if ($e != PARSER_EVENT_DEFINE_GLOBAL && $e != PARSER_EVENT_ARRAY && $e != PARSER_EVENT_QUOTE && $e != PARSER_EVENT_SINGLEQUOTE && $e != PARSER_EVENT_COMMENT && $e != PARSER_EVENT_COMMENTBLOCK)
  1044.             {
  1045.                 addError(PDERROR_GLOBAL_NOT_FOUND,$this->p_vars['globaltofind']);
  1046.                 unset($this->pushEvent[PARSER_EVENT_PHPCODE][strtolower($this->p_vars['globaltofind'])]);
  1047.                 foreach($this->tokens[STATE_PHPCODE] as $i => $notme)
  1048.                 if ($this->tokens[STATE_PHPCODE][$i] == $this->p_vars['globaltofind'])
  1049.                 unset($this->tokens[STATE_PHPCODE][$i]);
  1050.                 unset($this->p_vars['globaltofind']);
  1051.             }
  1052.         }
  1053.     }
  1054.     
  1055.     /**
  1056.      * handler for global variables
  1057.      */
  1058.     function handleGlobal($word, $pevent)
  1059.     {
  1060.         if (!$this->p_flags['in_global'])
  1061.         {
  1062.             $this->p_vars['linenum'] = $this->wp->linenum;
  1063.         }
  1064.         $this->p_flags['in_global'] = true;
  1065.         $e = $this->checkEventPush($word, $pevent);
  1066.         if ($this->checkEventPop($word, $pevent))
  1067.         {
  1068.             $this->p_flags['in_global'] = false;
  1069.             $a = new parserGlobal;
  1070.             $a->setDataType($this->p_vars['global_type']);
  1071.             $this->p_vars['global_type'] = '';
  1072.             $a->setLineNumber($this->p_vars['linenum']);
  1073.             $a->setName($this->p_vars['globaltofind']);
  1074.             if (isset($this->p_vars['global_val']))
  1075.             $a->setValue(trim($this->p_vars['global_val']));
  1076.             unset($this->p_vars['global_val']);
  1077.             $this->publishEvent(PHPDOCUMENTOR_EVENT_GLOBAL,$a);
  1078.             unset($this->pushEvent[PARSER_EVENT_PHPCODE][strtolower($this->p_vars['globaltofind'])]);
  1079.             foreach($this->tokens[STATE_PHPCODE] as $i => $notme)
  1080.             if ($this->tokens[STATE_PHPCODE][$i] == $this->p_vars['globaltofind'])
  1081.             unset($this->tokens[STATE_PHPCODE][$i]);
  1082.             unset($this->p_vars['globaltofind']);
  1083.         }
  1084.     }
  1085.     
  1086.     /**
  1087.      * Handles the stuff after the = in <code>$globalvar = value</code>
  1088.      */
  1089.     function handleGlobalValue($word, $pevent)
  1090.     {
  1091.         if ($this->checkEventPush($word, $pevent))
  1092.         {
  1093.             $this->wp->setWhitespace(false);
  1094.             return;
  1095.         }
  1096.         if (!isset($this->p_vars['global_val'])) $this->p_vars['global_val'] = '';
  1097.         if ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE || $this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE)
  1098.         {
  1099.             if (!isset($this->p_vars['quote_data'])) $this->p_vars['quote_data'] = '';
  1100.             $this->p_vars['global_val'] .= '"'.$this->p_vars['quote_data'].'"';
  1101.             unset($this->p_vars['quote_data']);
  1102.             $this->p_vars['last_pevent'] = PARSER_EVENT_GLOBAL_VALUE;
  1103.         }
  1104.         if ($this->p_vars['last_pevent'] == PARSER_EVENT_ARRAY)
  1105.         {
  1106.             $this->p_vars['global_val'] .= $this->p_vars['function_data'];
  1107.             $this->p_vars['function_data'] = false;
  1108.         }
  1109.         if ($word != ';')
  1110.         $this->p_vars['global_val'] .= $word;
  1111.         if ($this->checkEventPop($word, $pevent))
  1112.         {
  1113.             $this->wp->setWhitespace(false);
  1114.             $this->wp->backupPos($word);
  1115.         }
  1116.     }
  1117.     
  1118.     /**
  1119.      * handler for FUNC_GLOBAL.
  1120.      * this handler recognizes "global $var1, $var2" declarations in a function, and parses them
  1121.      */
  1122.     
  1123.     function handleFuncGlobal($word, $pevent)
  1124.     {
  1125.         if ((substr(trim($word),0,1) != '$') && ($word != ',') && ($word != ';'))
  1126.         { // not a global declaration, using a variable named "$global"
  1127.             $this->p_vars['event_stack']->popEvent();
  1128.             return;
  1129.         }
  1130.         if ($this->checkEventPop($word, $pevent))
  1131.         {
  1132.             return;
  1133.         }
  1134.         if (!$this->checkEventPush($word, $pevent))
  1135.         {
  1136.             if ($word == ',')
  1137.             { // another variable
  1138.                 $this->p_vars['global_count']++;
  1139.             } else
  1140.             {
  1141.                 if (!isset($this->p_vars['globals'][$this->p_vars['global_count']]))
  1142.                 $this->p_vars['globals'][$this->p_vars['global_count']] = '';
  1143.                 if (!empty($this->p_vars['globals'][$this->p_vars['global_count']])) $this->p_vars['global_count']++;
  1144.                 $this->p_vars['globals'][$this->p_vars['global_count']] = trim($word);
  1145.             }
  1146.         }
  1147.     }
  1148.     
  1149.     /**
  1150.      * handler for STATIC_VAR.
  1151.      * this handler recognizes "static $var1, $var2 = 6" declarations in a function, and parses them
  1152.      */
  1153.     
  1154.     function handleStaticVar($word, $pevent)
  1155.     {
  1156.         if ($this->checkEventPop($word, $pevent))
  1157.         {
  1158.             $this->p_vars['static_count']++;
  1159.             return;
  1160.         }
  1161.         if (!$this->checkEventPush($word, $pevent))
  1162.         {
  1163.             if ($word == ',')
  1164.             {
  1165.                 $this->p_vars['static_count']++;
  1166.                 return;
  1167.             }
  1168.             if (!isset($this->p_vars['statics'][$this->p_vars['static_count']]))
  1169.             $this->p_vars['statics'][$this->p_vars['static_count']] = '';
  1170.             if (!empty($this->p_vars['statics'][$this->p_vars['static_count']])) $this->p_vars['static_count']++;
  1171.             $this->p_vars['statics'][$this->p_vars['static_count']] = trim($word);
  1172.         }
  1173.     }
  1174.     
  1175.     /**
  1176.      * handler for STATIC_VAR_VALUE.
  1177.      * this handler parses the 6 in "static $var1, $var2 = 6"
  1178.      */
  1179.     
  1180.     function handleStaticValue($word, $pevent)
  1181.     {
  1182.         if ($this->checkEventPush($word, $pevent))
  1183.         {
  1184.             return;
  1185.         }
  1186.         if (!isset($this->p_vars['static_val'][$this->p_vars['static_count']])) $this->p_vars['static_val'][$this->p_vars['static_count']] = '';
  1187.         if ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE || $this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE)
  1188.         {
  1189.             $this->p_vars['static_val'][$this->p_vars['static_count']] .= '"'.$this->p_vars['quote_data'].'"';
  1190.             unset($this->p_vars['quote_data']);
  1191.         }
  1192.         if ($this->p_vars['last_pevent'] == PARSER_EVENT_ARRAY)
  1193.         {
  1194.             $this->p_vars['static_val'][$this->p_vars['static_count']] .= $this->p_vars['function_data'];
  1195.             $this->p_vars['function_data'] = false;
  1196.         }
  1197.         if ($this->checkEventPop($word, $pevent))
  1198.         {
  1199.             $this->p_vars['static_val'][$this->p_vars['static_count']] = trim($this->p_vars['static_val'][$this->p_vars['static_count']]);
  1200.             $this->wp->backupPos($word);
  1201.             return;
  1202.         } else $this->p_vars['static_val'][$this->p_vars['static_count']] .= $word;
  1203.     }
  1204.     
  1205.     /**
  1206.      * handler for FUNCTION.
  1207.      * this handler recognizes function declarations, and parses them.  The body
  1208.      * of the function is parsed by handleLogicBlock()
  1209.      * @see handleLogicBlock()
  1210.      */
  1211.     
  1212.     function handleFunction($word, $pevent)
  1213.     {
  1214.         if ($e = $this->checkEventPush( $word, $pevent))
  1215.         {
  1216.             if ($e == PARSER_EVENT_COMMENT || $e == PARSER_EVENT_COMMENTBLOCK) return;
  1217.         }
  1218.     
  1219.         if (!isset($this->p_vars['func'])) $this->p_vars['func'] = false;
  1220.         if (! is_subclass_of($this->p_vars['func'],"parserBase")) 
  1221.         {
  1222.             $this->p_vars['globals'] = array();
  1223.             $this->p_vars['global_count'] = 0;
  1224.             if ($this->p_flags['in_class'])
  1225.             $this->p_vars['func'] = new parserMethod($this->p_vars['cur_class']); 
  1226.             else
  1227.             $this->p_vars['func'] = new parserFunction;
  1228.             $this->p_vars['func']->setLineNumber($this->wp->linenum);
  1229.             if (trim($word) != '&')
  1230.             $this->p_vars['func']->setName(trim($word));
  1231.             else
  1232.             $this->p_vars['func']->setReturnsReference();
  1233.         } else
  1234.         {
  1235.             if ($this->p_vars['func']->getReturnsReference())
  1236.             {
  1237.                 if ($this->p_vars['last_word'] == '&')
  1238.                 {
  1239.                     $this->p_vars['func']->setName(trim($word));
  1240.                 }
  1241.             }
  1242.         }
  1243.         if ($this->checkEventPop($word,$pevent)) 
  1244.         { 
  1245.             $this->p_vars['func']->addGlobals($this->p_vars['globals']);
  1246.             $this->p_vars['func']->addStatics($this->p_vars['statics'],$this->p_vars['static_val']);
  1247.             $this->p_vars['globals'] = array();
  1248.             $this->p_vars['global_count'] = 0;
  1249.             if ($this->p_flags['getting_source'])
  1250.             {
  1251.                 $x = $this->wp->getSource();
  1252.                 $this->p_vars['func']->addSource($x);
  1253.                 $this->p_flags['get_source'] = false;
  1254.                 $this->p_flags['getting_source'] = false;
  1255.             }
  1256.             $this->publishEvent(PHPDOCUMENTOR_EVENT_FUNCTION,$this->p_vars['func']); 
  1257.             $this->p_vars['func'] = false; 
  1258.         } 
  1259.     }
  1260.  
  1261.     /**#@-*/
  1262.     /**
  1263.      * Helper function for {@link handleFunctionParams()}
  1264.      *
  1265.      * This function adds a new parameter to the parameter list
  1266.      * @access private
  1267.      * @param string
  1268.      */
  1269.     function endFunctionParam($word)
  1270.     {
  1271.         if (isset($this->p_vars['quote_data']) && ($this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE))
  1272.         {
  1273.             $this->p_vars['function_data'] .= "'".$this->p_vars['quote_data']."'";
  1274.             unset($this->p_vars['quote_data']);
  1275.         }
  1276.         if (isset($this->p_vars['quote_data']) && ($this->p_vars['quote_data'] != '') && ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE))
  1277.         {
  1278.             $this->p_vars['function_data'] .= '"'.$this->p_vars['quote_data'].'"';
  1279.             unset($this->p_vars['quote_data']);
  1280.         }
  1281.         if (isset($this->p_vars['function_param']))
  1282.         {
  1283.             $this->p_vars['func']->addParam($this->p_vars['function_param'],$this->p_vars['function_data'], $this->p_flags['funcparam_val']);
  1284.             unset($this->p_vars['function_param']);
  1285.             $this->p_vars['function_data'] = '';
  1286.             $this->p_flags['funcparam_val'] = false;
  1287.         }
  1288.     }
  1289.     /**#@+
  1290.      * @access private
  1291.      * @param string token parsed from source
  1292.      * @param integer parser constant from {@link Parser.inc}
  1293.      */
  1294.     /**
  1295.      * handler for FUNCTION_PARAMS.
  1296.      * this handler recognizes the parameters of a function within parentheses like function(param, param = default_value)
  1297.      * and parses them
  1298.      * @see endFunctionParam()
  1299.      */
  1300.     
  1301.     function handleFunctionParams($word, $pevent)
  1302.     {
  1303.         //echo $this->wp->getPos() . ": word=|$word|\t\t\tlastword=|".$this->p_vars['last_word']."|\n";
  1304.         //echo "function_param = '".$this->p_vars['function_param']."'\n";
  1305.         //echo "function_data = '".$this->p_vars['function_data']."'\n";
  1306.         $e1 = $this->checkEventPush( $word, $pevent); 
  1307.  
  1308.         if (!$e1)
  1309.         {
  1310.             if ($word == ',' || $this->checkEventPop($word,$pevent))
  1311.             {
  1312.                 $this->endFunctionParam($word);
  1313.             } elseif ($word == '=')
  1314.             {
  1315.                 $this->p_flags['funcparam_val'] = true;
  1316.             } else
  1317.             {
  1318.                 if ($this->p_flags['funcparam_val'])
  1319.                 {
  1320.                     if (isset($this->p_vars['quote_data']) && ($this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE))
  1321.                     {
  1322.                         $this->p_vars['function_data'] .= "'".$this->p_vars['quote_data']."'";
  1323.                         unset($this->p_vars['quote_data']);
  1324.                     }
  1325.                     if (isset($this->p_vars['quote_data']) && ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE))
  1326.                     {
  1327.                         $this->p_vars['function_data'] .= '"'.$this->p_vars['quote_data'].'"';
  1328.                         unset($this->p_vars['quote_data']);
  1329.                     }
  1330.                     $this->p_vars['function_data'] .= $word;
  1331.                 } else
  1332.                 {
  1333.                     $this->p_vars['function_param'] = $word;
  1334.                 }
  1335.             }
  1336.         }
  1337.     }
  1338.  
  1339.     
  1340.     /**
  1341.      * javadoc-desc-compliant handler for DOCBLOCK.
  1342.      * this handler recognizes @tags in DocBlocks and parses them for display.
  1343.      * It also parses out unknown tags into their own array for use by the docblock
  1344.      */
  1345.     
  1346.     function JavaDochandleDocblock($word, $pevent)
  1347.     {
  1348.         $e1 = $this->checkEventPush( $word, $pevent);
  1349.         if (!isset($this->p_vars[$this->p_vars['docblock_type']]) || !$this->p_vars[$this->p_vars['docblock_type']])
  1350.         {
  1351.             $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock();
  1352.             $this->p_vars['returntype'] = false;
  1353.             $this->p_vars['vartype'] = false;
  1354.             $this->p_flags['startdocblock'] = true;
  1355.             $this->p_flags['valid_newline'] = true;
  1356.             $this->p_flags['startline'] = true;
  1357.             $this->p_flags['newline'] = true;
  1358.             $this->p_flags['in_desc'] = true;
  1359.             $this->p_flags['in_tag'] = false;
  1360.             $this->p_flags['useperiod'] = false;
  1361.             $this->p_vars['line'] = array();
  1362.             $this->p_vars['linecount'] = 0;
  1363.         }
  1364.         $e = $this->checkEventPop( $word, $pevent);
  1365.         if (!$e1 && !$e)
  1366.         {
  1367.             if ($this->p_flags['in_desc']) $this->JavaDochandleDesc($word, $pevent);
  1368.             else $this->handleTags($word, $pevent);
  1369.         }
  1370.         if ($e)
  1371.         {
  1372.             if (!isset($this->p_vars['periodline'])) $this->p_vars['periodline'] = 0;
  1373.             if ($this->p_vars['periodline'] > 3)
  1374.             {
  1375.                 $this->p_flags['useperiod'] = false;
  1376.             }
  1377.  
  1378.             $this->p_vars['docblock_desc'] = new parserDesc;
  1379. //            echo "i = ".$this->p_vars['periodline']."; i < " . count($this->p_vars['line']) . "\n";
  1380.             if ($this->p_vars['docblock_type'] == 'docblock')
  1381.             {
  1382.                 if (isset($this->p_vars['docblock_template']))
  1383.                 {
  1384.                     // copy template values if not overridden
  1385.                     if (!$this->p_vars['docblock']->getExplicitPackage())
  1386.                     {
  1387.                         if ($p = $this->p_vars['docblock_template']->getKeyword('package'))
  1388.                         {
  1389.                             $this->p_vars['docblock']->addKeyword('package',$p);
  1390.                             $this->p_vars['docblock']->setExplicitPackage();
  1391.                         }
  1392.                         if ($p = $this->p_vars['docblock_template']->getKeyword('category'))
  1393.                         {
  1394.                             $this->p_vars['docblock']->addKeyword('category',$p);
  1395.                             $this->p_vars['docblock']->setExplicitCategory();
  1396.                         }
  1397.                         if ($p = $this->p_vars['docblock_template']->getKeyword('subpackage'))
  1398.                         {
  1399.                             $this->p_vars['docblock']->addKeyword('subpackage',$p);
  1400.                         }
  1401.                     }
  1402.                     $tags = $this->p_vars['docblock_template']->listTags();
  1403.                     foreach($tags as $tag)
  1404.                     {
  1405.                         $this->p_vars['docblock']->addKeyword($tag->keyword,$tag->value);
  1406.                     }
  1407.                     $this->p_vars['docblock_desc']->add($this->p_vars['docblock_template']->desc);
  1408.                     if (!count($this->p_vars['docblock']->params)) $this->p_vars['docblock']->params = $this->p_vars['docblock_template']->params;
  1409.                 }
  1410.                 if ($a = strpos(trim($this->p_vars['shortdesc']),'<p>') === 0)
  1411.                 $this->p_vars['shortdesc'] = substr($this->p_vars['shortdesc'],strpos($this->p_vars['shortdesc'],'<p>') + 4);
  1412.                 $this->p_vars[$this->p_vars['docblock_type']]->setShortDesc($this->p_vars['shortdesc']);
  1413.             }
  1414.             for($i = 0; $i < count($this->p_vars['line']); $i++)
  1415.             {
  1416.                 // the line will not be set if it doesn't start with a *
  1417.                 if (isset($this->p_vars['line'][$i]))
  1418.                 $this->p_vars['docblock_desc']->add($this->p_vars['line'][$i]);
  1419.             }
  1420.  
  1421.  
  1422.             $this->p_vars[$this->p_vars['docblock_type']]->setDesc($this->p_vars['docblock_desc']);
  1423.             unset($this->p_vars['docblock_desc']);
  1424. //            var_dump($this->p_vars[$this->p_vars['docblock_type']]);
  1425. //            exit;
  1426.             if ($this->p_vars['docblock_type'] == 'docblock')
  1427.             {
  1428.                 $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK,$this->p_vars[$this->p_vars['docblock_type']]);
  1429.                 unset($this->p_vars[$this->p_vars['docblock_type']]);
  1430.                 $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock();
  1431.             }
  1432.             $this->p_flags['in_desc'] = true;
  1433.             $this->p_flags['in_tag'] = false;
  1434.             $this->p_flags['useperiod'] = false;
  1435.             $this->p_vars['line'] = array();
  1436.             $this->p_vars['linecount'] = 0;
  1437.             $this->p_flags['start_docblock'] = true;
  1438.             $this->p_flags['valid_newline'] = true;
  1439.             $this->wp->setWhitespace(false);
  1440.         }
  1441.     }
  1442.  
  1443.     /**
  1444.      * handler for DOCKEYWORD_DESC.
  1445.      * this handler parses the short and long description of a dockeyword
  1446.      */
  1447.     
  1448.     function JavaDochandleDesc($word, $pevent)
  1449.     {
  1450.         if ($this->p_flags['valid_newline'])
  1451.         {
  1452.             if ($word == '@' && $this->p_flags['startline'])
  1453.             {
  1454.                 return $this->handleTag($word, $pevent);
  1455.             }
  1456.             if (!isset($this->p_vars['line'][$this->p_vars['linecount']]))
  1457.             {
  1458.                 $this->p_vars['line'][$this->p_vars['linecount']] = new parserStringWithInlineTags;
  1459.             }
  1460.             if ($this->p_vars['last_word'] == "." && $this->p_flags['useperiod'] == false)
  1461.             {
  1462.                 $this->p_vars['periodline'] = $this->p_vars['linecount'];
  1463.                 $this->p_vars['shortdesc'] = new parserDesc;
  1464.                 for($i = 0; ($i <= $this->p_vars['periodline']) && ($i < count($this->p_vars['line'])); $i++)
  1465.                 {
  1466.                     if (isset($this->p_vars['line'][$i]))
  1467.                     $this->p_vars['shortdesc']->add($this->p_vars['line'][$i]);
  1468.                 }
  1469.                 $this->p_flags['useperiod'] = true;
  1470.             }
  1471.             $this->p_vars['line'][$this->p_vars['linecount']]->add($word);
  1472. //            debug("DESC $word");
  1473.         }
  1474.         $this->handleCR($word);
  1475.     }
  1476.     
  1477.     /**
  1478.      * handler for DOCBLOCK.
  1479.      * this handler recognizes @tags in DocBlocks and parses them for display.
  1480.      * It also parses out unknown tags into their own array for use by the docblock
  1481.      */
  1482.     
  1483.     function BetterhandleDocblock($word, $pevent)
  1484.     {
  1485.         $e1 = $this->checkEventPush( $word, $pevent);
  1486.         if (!$this->wp->returnWhiteSpace)
  1487.         {
  1488.             addErrorDie(PDERROR_NEED_WHITESPACE);
  1489.         }
  1490.         if (!isset($this->p_vars[$this->p_vars['docblock_type']]) || !$this->p_vars[$this->p_vars['docblock_type']])
  1491.         {
  1492.             $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock();
  1493.             $this->p_vars['returntype'] = false;
  1494.             $this->p_vars['vartype'] = false;
  1495.             $this->p_flags['startdocblock'] = true;
  1496.             $this->p_flags['valid_newline'] = true;
  1497.             $this->p_flags['startline'] = true;
  1498.             $this->p_flags['newline'] = true;
  1499.             $this->p_flags['in_desc'] = true;
  1500.             $this->p_flags['in_tag'] = false;
  1501.             $this->p_flags['useperiod'] = false;
  1502.             $this->p_vars['line'] = array();
  1503.             $this->p_vars['linecount'] = 0;
  1504.         }
  1505.         $e = $this->checkEventPop( $word, $pevent);
  1506.         if (!$e1 && !$e)
  1507.         {
  1508.             if ($this->p_flags['in_desc']) $this->handleDesc($word, $pevent);
  1509.             else $this->handleTags($word, $pevent);
  1510.         }
  1511.         if ($e)
  1512.         {
  1513.             if (!isset($this->p_vars['periodline'])) $this->p_vars['periodline'] = 0;
  1514.             if ($this->p_vars['periodline'] > 3)
  1515.             {
  1516.                 $this->p_flags['useperiod'] = false;
  1517.             } else
  1518.             {
  1519.                 for($i = 0; $i < $this->p_vars['periodline']; $i++)
  1520.                 {
  1521.                     if (isset($this->p_vars['line'][$i]))
  1522.                     {
  1523.                         if ($this->p_vars['line'][$i]->trimmedStrlen() == 0 && isset($this->p_vars['line'][$i - 1]) && $this->p_vars['line'][$i - 1]->trimmedStrlen())
  1524.                         {
  1525.                             $this->p_vars['periodline'] = $i;
  1526.                         }
  1527.                     }
  1528.                 }
  1529.             }
  1530.             // figure out the shortdesc
  1531.             if ($this->p_flags['useperiod'] === false)
  1532.             {
  1533.                 // use the first non blank line for short desc
  1534.                 for($i = 0; $i < count($this->p_vars['line']); $i++)
  1535.                 {
  1536.                     if (!isset($this->p_vars['line'][$i]))
  1537.                     $this->p_vars['line'][$i] = new parserStringWithInlineTags;
  1538.                     if ($this->p_vars['line'][$i]->trimmedStrlen() > 0)
  1539.                     {
  1540.                         $this->p_vars['periodline'] = $i;
  1541.                         $i = count($this->p_vars['line']);
  1542.                     }
  1543.                 }
  1544.                         
  1545.                 // check to see if we are going to use a blank line to end the shortdesc
  1546.                 // this can only be in the first 4 lines
  1547.                 if (count($this->p_vars['line']) > 4)
  1548.                 {
  1549.                     $max = 4;
  1550.                 } else {
  1551.                     $max = count($this->p_vars['line']);
  1552.                 }
  1553.  
  1554.                 for($i = $this->p_vars['periodline']; $i < $max; $i++)
  1555.                 {
  1556.                     if (isset($this->p_vars['line'][$i]))
  1557.                     if ($this->p_vars['line'][$i]->trimmedStrlen() == 0)
  1558.                     {
  1559.                         $this->p_vars['periodline'] = $i;
  1560.                         $i = $max;
  1561.                     }
  1562.                 }
  1563.             }
  1564.  
  1565.             if ($this->p_vars['docblock_type'] == 'docblock')
  1566.             {
  1567.                 $this->p_vars['shortdesc'] = new parserDesc;
  1568.                 for($i = 0; ($i <= $this->p_vars['periodline']) && ($i < count($this->p_vars['line'])); $i++)
  1569.                 {
  1570.                     if (isset($this->p_vars['line'][$i]))
  1571.                     $this->p_vars['shortdesc']->add($this->p_vars['line'][$i]);
  1572.                 }
  1573.                 $this->p_vars['periodline']++;
  1574.     
  1575.                 $this->p_vars['docblock_desc'] = new parserDesc;
  1576.                 if (isset($this->p_vars['docblock_template']))
  1577.                 {
  1578.                     // copy template values if not overridden
  1579.                     if (!$this->p_vars['docblock']->getExplicitPackage())
  1580.                     {
  1581.                         if ($p = $this->p_vars['docblock_template']->getKeyword('package'))
  1582.                         {
  1583.                             $this->p_vars['docblock']->addKeyword('package',$p);
  1584.                             $this->p_vars['docblock']->setExplicitPackage();
  1585.                         }
  1586.                         if ($p = $this->p_vars['docblock_template']->getKeyword('category'))
  1587.                         {
  1588.                             $this->p_vars['docblock']->addKeyword('category',$p);
  1589.                             $this->p_vars['docblock']->setExplicitCategory();
  1590.                         }
  1591.                         if ($p = $this->p_vars['docblock_template']->getKeyword('subpackage'))
  1592.                         {
  1593.                             $this->p_vars['docblock']->addKeyword('subpackage',$p);
  1594.                         }
  1595.                     }
  1596.                     $tags = $this->p_vars['docblock_template']->listTags();
  1597.                     foreach($tags as $tag)
  1598.                     {
  1599.                         $this->p_vars['docblock']->addKeyword($tag->keyword,$tag->value);
  1600.                     }
  1601.                     if (!count($this->p_vars['docblock']->params)) $this->p_vars['docblock']->params = $this->p_vars['docblock_template']->params;
  1602.                     $this->p_vars['docblock_desc']->add($this->p_vars['docblock_template']->desc);
  1603.                 }
  1604.     //            echo "i = ".$this->p_vars['periodline']."; i < " . count($this->p_vars['line']) . "\n";
  1605.                 for($i = $this->p_vars['periodline']; $i < count($this->p_vars['line']); $i++)
  1606.                 {
  1607.                     // the line will not be set if it doesn't start with a *
  1608.                     if (isset($this->p_vars['line'][$i]))
  1609.                     $this->p_vars['docblock_desc']->add($this->p_vars['line'][$i]);
  1610.                 }
  1611.             } else
  1612.             {
  1613.                 $this->p_vars['shortdesc'] = new parserDesc;
  1614.                 for($i = 0; ($i <= $this->p_vars['periodline']) && ($i < count($this->p_vars['line'])); $i++)
  1615.                 {
  1616.                     if (isset($this->p_vars['line'][$i]))
  1617.                     $this->p_vars['shortdesc']->add($this->p_vars['line'][$i]);
  1618.                 }
  1619.                 $this->p_vars['periodline']++;
  1620.     
  1621.                 $this->p_vars['docblock_desc'] = new parserDesc;
  1622.                 for($i=$this->p_vars['periodline']; $i < count($this->p_vars['line']); $i++)
  1623.                 {
  1624.                     if (isset($this->p_vars['line'][$i]))
  1625.                     $this->p_vars['docblock_desc']->add($this->p_vars['line'][$i]);
  1626.                 }
  1627.             }
  1628.  
  1629.  
  1630.             $this->p_vars[$this->p_vars['docblock_type']]->setShortDesc($this->p_vars['shortdesc']);
  1631.             $this->p_vars[$this->p_vars['docblock_type']]->setDesc($this->p_vars['docblock_desc']);
  1632.             unset($this->p_vars['docblock_desc']);
  1633. //            var_dump($this->p_vars[$this->p_vars['docblock_type']]);
  1634. //            exit;
  1635.             if ($this->p_vars['docblock_type'] == 'docblock')
  1636.             {
  1637.                 $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK,$this->p_vars[$this->p_vars['docblock_type']]);
  1638.                 unset($this->p_vars[$this->p_vars['docblock_type']]);
  1639.                 $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock();
  1640.             } else
  1641.             {
  1642.                 $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK_TEMPLATE,$this->p_vars[$this->p_vars['docblock_type']]);
  1643.             }
  1644.             $this->p_flags['in_desc'] = true;
  1645.             $this->p_flags['in_tag'] = false;
  1646.             $this->p_flags['useperiod'] = false;
  1647.             $this->p_vars['line'] = array();
  1648.             $this->p_vars['linecount'] = 0;
  1649.             $this->p_flags['start_docblock'] = true;
  1650.             $this->p_flags['valid_newline'] = true;
  1651.             $this->wp->setWhitespace(false);
  1652.             $this->p_vars['docblock_type'] = 'docblock';
  1653.         }
  1654.     }
  1655.     
  1656.     /**
  1657.      * Handles docblock templates
  1658.      * @tutorial phpDocumentor.howto.pkg#basics.docblocktemplate
  1659.      */
  1660.     function handleDocBlockTemplate($word, $pevent)
  1661.     {
  1662.         $this->p_vars['docblock_type'] = 'docblock_template';
  1663.         $this->p_vars['event_stack']->popEvent();
  1664.         $this->p_vars['event_stack']->pushEvent(PARSER_EVENT_DOCBLOCK);
  1665.         // fool the docblock handler into thinking everything is totally normal
  1666.         $this->p_vars['last_word'] = '/**';
  1667.         $pevent = PARSER_EVENT_DOCBLOCK;
  1668.         $this->BetterhandleDocBlock($word, $pevent);
  1669.     }
  1670.     
  1671.     /**
  1672.      * Handles closing docblock templates /**#@-* /
  1673.      * @tutorial phpDocumentor.howto.pkg#basics.docblocktemplate
  1674.      */
  1675.     function handleEndDocBlockTemplate($word, $pevent)
  1676.     {
  1677.         unset($this->p_vars['docblock_template']);
  1678.         $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,PHPDOCUMENTOR_EVENT_END_DOCBLOCK_TEMPLATE);
  1679.         $this->p_vars['event_stack']->popEvent();
  1680.     }
  1681.     /**#@-*/
  1682.     /**
  1683.      * Handles a new line in a DocBlock
  1684.      * @param string token containing a newline \n
  1685.      * @access private
  1686.      */
  1687.     function handleCR($word)
  1688.     {
  1689.         $this->laststart = $this->p_flags['startline'];
  1690.         if ($word == "\n" || $word == ".\n")
  1691.         {
  1692.             $this->p_flags['start_docblock'] = false;
  1693.             $this->p_flags['newline'] = true;
  1694.             $this->p_flags['valid_newline'] = false;
  1695.             if ($this->p_flags['in_desc'] && !$this->p_flags['useperiod'])
  1696.             {
  1697.                 if ($word == ".\n")
  1698.                 {
  1699.                     $this->p_flags['useperiod'] = true;
  1700.                     $this->p_vars['periodline'] = $this->p_vars['linecount'];
  1701.                 }
  1702.             }
  1703.         } else
  1704.         {
  1705.             if ($this->p_flags['valid_newline'] && strlen(trim($word)))
  1706.             {
  1707.                 $this->p_flags['startline'] = false;
  1708.             }
  1709.             if ($this->p_flags['newline'] && ($word == '*' || $this->p_flags['start_docblock']))
  1710.             {
  1711.                 $this->p_flags['newline'] = false;
  1712.                 $this->p_flags['valid_newline'] = true;
  1713.                 if (!$this->p_flags['start_docblock'])
  1714.                 $this->p_vars['linecount']++;
  1715.                 $this->p_flags['startline'] = true;
  1716.                 $justset = true;
  1717. //                debug('valid newline');
  1718.             }
  1719.         }
  1720.     }
  1721.     
  1722.     /**
  1723.      * handler for DOCKEYWORD_DESC.
  1724.      * this handler parses the short and long description of a dockeyword
  1725.      * @access private
  1726.      */
  1727.     
  1728.     function handleDesc($word, $pevent)
  1729.     {
  1730. //        echo "|$word|\n";
  1731.         if ($this->p_flags['valid_newline'])
  1732.         {
  1733.             if ($word == '@' && $this->p_flags['startline'])
  1734.             {
  1735.                 return $this->handleTag($word, $pevent);
  1736.             }
  1737.             if ($this->p_vars['last_word'] == ". " || $this->p_vars['last_word'] == ".\t")
  1738.             {
  1739.                 $this->p_flags['useperiod'] = true;
  1740.                 $this->p_vars['periodline'] = $this->p_vars['linecount'];
  1741.                 $this->p_vars['linecount']++;
  1742.             }
  1743.             if (!isset($this->p_vars['line'][$this->p_vars['linecount']]))
  1744.             {
  1745.                 $this->p_vars['line'][$this->p_vars['linecount']] = new parserStringWithInlineTags;
  1746.             }
  1747.             if ($this->p_flags['startline'])
  1748.             {
  1749.                 if ($word[0] == ' ') $word = substr($word,1);
  1750. //                $word = ltrim($word," \t");
  1751.             }
  1752.             if ($word != '') $this->p_vars['line'][$this->p_vars['linecount']]->add($word);
  1753. //            debug("DESC $word");
  1754.         }
  1755.         $this->handleCR($word);
  1756.     }
  1757.     
  1758.     /**#@+
  1759.      * @access private
  1760.      * @param string token parsed from source
  1761.      * @param integer parser constant from {@link Parser.inc}
  1762.      */
  1763.     /**
  1764.      * handler for DOCKEYWORD_TAGS.
  1765.      * this handler recognizes @tags in DocBlocks and parses them for display
  1766.      * I think this may be unused.  We'll delete from 1.1 if so
  1767.      */
  1768.     function handleTags($word, $pevent)
  1769.     {
  1770.         if ($this->p_flags['valid_newline'])
  1771.         {
  1772. //            debug("TAGS $word");
  1773.         }
  1774.         $this->handleCR($word);
  1775.     }
  1776.     
  1777.     /**
  1778.      * handler for DOCKEYWORD.
  1779.      * this handler recognizes @tags in DocBlocks and parses them for display
  1780.      */
  1781.     function handleTag($word, $pevent)
  1782.     {
  1783.         if ($this->p_flags['in_desc'] && !$this->p_flags['valid_newline'])
  1784.         {
  1785.             $this->p_vars['event_stack']->popEvent();
  1786.             return $this->handleDesc($word, $pevent);
  1787.         }
  1788. //        if ($this->p_vars['last_word'] == '@') fancy_debug('here'.$word,$this->p_flags['startline'],$this->p_flags['in_tag']);
  1789.         if ($this->p_vars['tagname'] == 'author')
  1790.         {
  1791.             if ($word == '<')
  1792.             {
  1793.                 $this->p_vars['event_stack']->pushEvent(PARSER_EVENT_DOCKEYWORD_EMAIL);
  1794.                 return $this->handleDockeywordEmail($word, $pevent);
  1795.             }
  1796.         }
  1797.         if ($this->checkEventPush( $word, $pevent)) return;
  1798.         if ($this->p_vars['last_word'] == '@' && !$this->p_flags['startline'] && $this->p_flags['in_desc'])
  1799.         {
  1800.             $this->p_vars['event_stack']->popEvent();
  1801.             $this->p_vars['line'][$this->p_vars['linecount']]->add('@');
  1802.             return $this->handleDesc($word, $pevent);
  1803.         } elseif($this->p_vars['last_word'] == '@' && !strlen(trim($word)) && empty($this->p_vars['tagname']) && $this->p_flags['in_desc'])
  1804.         {
  1805.             $pevent = $this->p_vars['event_stack']->popEvent();
  1806.             $this->p_vars['line'][$this->p_vars['linecount']]->add('@');
  1807.             return $this->handleDesc($word, $pevent);
  1808.         }
  1809.         if ($word == '@' && $this->p_flags['startline'] && $this->p_flags['in_tag'])
  1810.         {
  1811.             $this->wp->backupPos($word);
  1812.             $white = $this->wp->returnWhiteSpace;
  1813.             $this->wp->setWhitespace(true);
  1814.             $word1 = $this->wp->getWord();
  1815.             $this->wp->backupPos($word1);
  1816.             if (strlen(trim($word1)))
  1817.             {
  1818.                 $this->endTag();
  1819.             }
  1820.             $this->wp->getWord();
  1821.             $this->wp->setWhitespace($white);
  1822.         }
  1823.         $this->p_flags['in_tag'] = true;
  1824.         $e = $this->checkEventPop($word, $pevent);
  1825.         if (!$e)
  1826.         {
  1827.             if ($this->p_flags['valid_newline'])
  1828.             {
  1829.                 if (($this->p_flags['startline'] || $this->laststart) && $word != '@')
  1830.                 {
  1831.                     if ($this->p_vars['last_word'] == '@')
  1832.                     {
  1833. //                        debug("TAGSTART $word");
  1834.                         $this->p_flags['in_tag'] = true;
  1835.                         $this->p_vars['tagname'] = $word;
  1836.                         $this->p_flags['startline'] = false;
  1837.                         $this->p_vars['tag_value'] = new parserStringWithInlineTags;
  1838.                     } else
  1839.                     {
  1840. //                        debug("TAG1 $word");
  1841.                         if (isset($this->tagHandlers[$this->p_vars['tagname']]))
  1842.                         $handler = $this->tagHandlers[$this->p_vars['tagname']];
  1843.                         else $handler = $this->tagHandlers['*'];
  1844.                         $this->$handler($word);
  1845.                     }
  1846.                 } else
  1847.                 {
  1848.                     if (empty($this->p_vars['tagname']))
  1849.                     {
  1850.                         if ($this->p_flags['in_desc'])
  1851.                         {
  1852.                             $this->p_flags['in_tag'] = false;
  1853.                             $this->p_vars['line'][$this->p_vars['linecount']]->add('@');
  1854.                             $this->p_vars['event_stack']->popEvent();
  1855.                             $this->handleCR($word);
  1856.                             return $this->handleDesc($word, $pevent);
  1857.                         }
  1858.                     }
  1859. //                    debug("TAG2 $word");
  1860.                     if (isset($this->tagHandlers[$this->p_vars['tagname']]))
  1861.                     $handler = $this->tagHandlers[$this->p_vars['tagname']];
  1862.                     else $handler = $this->tagHandlers['*'];
  1863.                     $this->$handler($word);
  1864.                 }
  1865.             }
  1866.             $this->handleCR($word);
  1867.         }
  1868.         $this->p_flags['in_desc'] = false;
  1869.         if ($e)
  1870.         {
  1871.             $this->endTag();
  1872.             $this->wp->setWhitespace(false);
  1873.             // walk back a word
  1874.             $this->wp->backupPos($word);
  1875.             $this->wp->setWhitespace(true);
  1876.         }
  1877.     }
  1878.     /**#@-*/
  1879.     /**
  1880.      * Called to clean up at the end of parsing a @tag in a docblock
  1881.      */
  1882.     function endTag()
  1883.     {
  1884.         if (isset($this->tagHandlers[$this->p_vars['tagname']]))
  1885.         $handler = $this->tagHandlers[$this->p_vars['tagname']];
  1886.         else $handler = $this->tagHandlers['*'];
  1887.         $this->$handler(false);
  1888.         $this->p_vars['tagname'] = '';
  1889.         $this->p_flags['startline'] = true;
  1890. //        debug("ENDTAG");
  1891.     }
  1892.     
  1893.     /**#@+
  1894.      * Tag Handlers
  1895.      * @param string
  1896.      */
  1897.     /**
  1898.      * Handles all standard tags that only have a description
  1899.      */
  1900.     function defaultTagHandler($word)
  1901.     {
  1902.         if ($word !== false)
  1903.         {
  1904.             $this->p_vars['tag_value']->add($word);
  1905.         } else
  1906.         {
  1907.             $this->p_vars[$this->p_vars['docblock_type']]->addKeyword($this->p_vars['tagname'],$this->p_vars['tag_value']);
  1908.         }
  1909.     }
  1910.     
  1911.     /**
  1912.      * Handles tags like '@filesource' that only work in PHP 4.3.0+
  1913.      */
  1914.     function invalidTagHandler($word)
  1915.     {
  1916.         if ($word === false)
  1917.         {
  1918.             addError(PDERROR_TAG_NOT_HANDLED,$this->p_vars['tagname']);
  1919.         }
  1920.     }
  1921.     
  1922.     /**
  1923.      * handles @package
  1924.      * @tutorial tags.package.pkg
  1925.      */
  1926.     function packageTagHandler($word)
  1927.     {
  1928.         if ($word !== false)
  1929.         {
  1930.             $this->p_vars['tag_value']->add($word);
  1931.         } else
  1932.         {
  1933.             $this->p_vars[$this->p_vars['docblock_type']]->addKeyword($this->p_vars['tagname'],$this->p_vars['tag_value']);
  1934.             $this->p_vars[$this->p_vars['docblock_type']]->setExplicitPackage();
  1935.         }
  1936.     }
  1937.     
  1938.     /**
  1939.      * handles @example
  1940.      * @tutorial tags.example.pkg
  1941.      */
  1942.     function exampleTagHandler($word)
  1943.     {
  1944.         if ($word !== false)
  1945.         {
  1946.             $this->p_vars['tag_value']->add($word);
  1947.         } else
  1948.         {
  1949.             $this->p_vars[$this->p_vars['docblock_type']]->addExample($this->p_vars['tag_value'], $this->p_vars['parsepath']);
  1950.         }
  1951.     }
  1952.     
  1953.     /**
  1954.      * handles @category
  1955.      * @tutorial tags.category.pkg
  1956.      */
  1957.     function categoryTagHandler($word)
  1958.     {
  1959.         if ($word !== false)
  1960.         {
  1961.             $this->p_vars['tag_value']->add($word);
  1962.         } else
  1963.         {
  1964.             $this->p_vars[$this->p_vars['docblock_type']]->addKeyword($this->p_vars['tagname'],$this->p_vars['tag_value']);
  1965.             $this->p_vars[$this->p_vars['docblock_type']]->setExplicitCategory();
  1966.         }
  1967.     }
  1968.     
  1969.     /**
  1970.      * handles @global
  1971.      * @tutorial tags.global.pkg
  1972.      */
  1973.     function globalTagHandler($word)
  1974.     {
  1975.         if ($word !== false)
  1976.         {
  1977.             // no data yet
  1978.             $a = trim($this->p_vars['tag_value']->getString());
  1979.             if (empty($a))
  1980.             {
  1981.                 // not an empty word
  1982.                 if (trim($word) != '')
  1983.                 {
  1984.                     if (!empty($this->p_vars['global_type']))
  1985.                     {
  1986.                         if (!$this->p_flags['define_global'] && !$this->p_flags['function_global'])
  1987.                         {
  1988.                             // @global type $GLOBALVARNAME ?
  1989.                             if (substr($word,0,1) == '$')
  1990.                             {
  1991.                                 $this->p_flags['define_global'] = true;
  1992.                                 $this->p_flags['function_global'] = false;
  1993.                                 $this->p_vars['find_global'] = $word;
  1994.                             } else
  1995.                             { // function @global type description
  1996.                                 $this->p_flags['function_global'] = true;
  1997.                                 $this->p_flags['define_global'] = false;
  1998.                                 $this->p_vars['tag_value']->add($word);
  1999.                             }
  2000.                         } else
  2001.                         {
  2002.                             if ($this->p_flags['define_global'])
  2003.                             {
  2004.                                 $this->p_vars['find_global'] .= $word;
  2005.                             } elseif($this->p_flags['function_global'])
  2006.                             {
  2007.                                 // description, to be added to the tag
  2008.                                 $this->p_vars['tag_value']->add($word);
  2009.                             }
  2010.                         }
  2011.                     } else
  2012.                     {
  2013.                         $this->p_vars['global_type'] = $word;
  2014.                     } 
  2015.                 } else $this->p_vars['tag_value']->add($word); // add whitespace to the tag description
  2016.             } else
  2017.             { // tag_value has data, must be a function @global
  2018.                 $this->p_vars['tag_value']->add($word);
  2019.             }
  2020.         } else
  2021.         { // endtag
  2022.             if ($this->p_flags['define_global'])
  2023.             {
  2024.                 $this->findGlobal($this->p_vars['find_global']);
  2025.             }
  2026.             elseif ($this->p_flags['function_global'])
  2027.             {
  2028.                 $this->p_vars[$this->p_vars['docblock_type']]->addFuncGlobal($this->p_vars['global_type'],$this->p_vars['tag_value']);
  2029.                 $this->p_vars['global_type'] = '';
  2030.             }
  2031.             else
  2032.             {
  2033.                 addError(PDERROR_MALFORMED_GLOBAL_TAG);
  2034.             }
  2035.             $this->p_vars['find_global'] = '';
  2036.             $this->p_flags['define_global'] = false;
  2037.             $this->p_flags['function_global'] = false;
  2038.         }
  2039.     }
  2040.     
  2041.     /**
  2042.      * handles @staticvar
  2043.      * @tutorial tags.staticvar.pkg
  2044.      */
  2045.     function staticvarTagHandler($word)
  2046.     {
  2047.         if ($word !== false)
  2048.         {
  2049.             if (!$this->p_vars['returntype']) $this->p_vars['returntype'] = trim($word);
  2050.             else
  2051.             {
  2052.                 if (!$this->p_vars['paramname'])
  2053.                 {
  2054.                     if (substr(trim($word),0,1) == "$")
  2055.                     $this->p_vars['paramname'] = trim($word);
  2056.                     else $this->p_vars['tag_value']->add($word);
  2057.                 } else
  2058.                 {
  2059.                     if (0)//strtolower($this->p_vars['paramtype']) == 'object')
  2060.                     {
  2061.                         if (strlen(trim($word)))
  2062.                         $this->p_vars['paramname'] = trim($word);
  2063.                     } else $this->p_vars['tag_value']->add($word);
  2064.                 }
  2065.             }
  2066.         } else
  2067.         {
  2068.             if (!$this->p_vars['paramname'])
  2069.             $this->p_vars[$this->p_vars['docblock_type']]->addStaticVar(null,$this->p_vars['returntype'],$this->p_vars['tag_value']);
  2070.             else
  2071.             $this->p_vars[$this->p_vars['docblock_type']]->addStaticVar($this->p_vars['paramname'],$this->p_vars['returntype'],$this->p_vars['tag_value']);
  2072.             $this->p_vars['paramname'] = false;
  2073.             $this->p_vars['returntype'] = false;
  2074.         }
  2075.     }
  2076.     
  2077.     /**
  2078.      * handles @uses
  2079.      * @tutorial tags.uses.pkg
  2080.      */
  2081.     function usesTagHandler($word)
  2082.     {
  2083.         if ($word !== false)
  2084.         {
  2085.             if (!$this->p_vars['seelement']) $this->p_vars['seelement'] = trim($word);
  2086.             else
  2087.             {
  2088.                 $this->p_vars['tag_value']->add($word);
  2089.             }
  2090.         } else
  2091.         {
  2092.             $see = new parserStringWithInlineTags;
  2093.             $see->add($this->p_vars['seelement']);
  2094.             $this->p_vars[$this->p_vars['docblock_type']]->addUses($see,$this->p_vars['tag_value']);
  2095.             $this->p_vars['seelement'] = false;
  2096.         }
  2097.     }
  2098.     
  2099.     /**
  2100.      * handles @param
  2101.      * @tutorial tags.param.pkg
  2102.      */
  2103.     function paramTagHandler($word)
  2104.     {
  2105.         if ($word !== false)
  2106.         {
  2107.             if (!$this->p_vars['returntype']) $this->p_vars['returntype'] = trim($word);
  2108.             else
  2109.             {
  2110.                 if (!$this->p_vars['paramname'])
  2111.                 {
  2112.                     if (substr(trim($word),0,1) == "$" || substr(trim($word),0,2) == "&$")
  2113.                     $this->p_vars['paramname'] = trim($word);
  2114.                     else $this->p_vars['tag_value']->add($word);
  2115.                 } else
  2116.                 {
  2117.                     if (0)//strtolower($this->p_vars['paramtype']) == 'object')
  2118.                     {
  2119.                         if (strlen(trim($word)))
  2120.                         $this->p_vars['paramname'] = trim($word);
  2121.                     } else $this->p_vars['tag_value']->add($word);
  2122.                 }
  2123.             }
  2124.         } else
  2125.         {
  2126.             if (!$this->p_vars['paramname'])
  2127.             $this->p_vars[$this->p_vars['docblock_type']]->addParam(null,$this->p_vars['returntype'],$this->p_vars['tag_value']);
  2128.             else
  2129.             $this->p_vars[$this->p_vars['docblock_type']]->addParam($this->p_vars['paramname'],$this->p_vars['returntype'],$this->p_vars['tag_value']);
  2130.             $this->p_vars['paramname'] = false;
  2131.             $this->p_vars['returntype'] = false;
  2132.         }
  2133.     }
  2134.     
  2135.     /**
  2136.      * handles @return
  2137.      * @tutorial tags.return.pkg
  2138.      */
  2139.     function returnTagHandler($word)
  2140.     {
  2141.         if ($word !== false)
  2142.         {
  2143.             if (!$this->p_vars['returntype']) $this->p_vars['returntype'] = trim($word);
  2144.             else
  2145.             {
  2146.                 if (strtolower($this->p_vars['returntype']) == 'object')
  2147.                 {
  2148.                     if (strlen(trim($word)))
  2149.                     $this->p_vars['returntype'] = trim($word);
  2150.                 } else $this->p_vars['tag_value']->add($word);
  2151.             }
  2152.         } else
  2153.         {
  2154.             $this->p_vars[$this->p_vars['docblock_type']]->addReturn($this->p_vars['returntype'],$this->p_vars['tag_value']);
  2155.             $this->p_vars['returntype'] = false;
  2156.         }
  2157.     }
  2158.     
  2159.     /**
  2160.      * handles @var
  2161.      * @tutorial tags.var.pkg
  2162.      */
  2163.     function varTagHandler($word)
  2164.     {
  2165.         if ($word)
  2166.         {
  2167.             if (!$this->p_vars['vartype']) $this->p_vars['vartype'] = trim($word);
  2168.             else
  2169.             {
  2170.                 if (strtolower($this->p_vars['vartype']) == 'object')
  2171.                 {
  2172.                     if (strlen(trim($word)))
  2173.                     $this->p_vars['vartype'] = trim($word);
  2174.                 }
  2175.                 else $this->p_vars['tag_value']->add($word);
  2176.             }
  2177.         } elseif ($word === false)
  2178.         {
  2179.             $this->p_vars[$this->p_vars['docblock_type']]->addVar($this->p_vars['vartype'],$this->p_vars['tag_value']);
  2180.             $this->p_vars['vartype'] = false;
  2181.         }
  2182.     }
  2183.     /**#@-*/
  2184.     /** @access private */
  2185.     function getSource()
  2186.     {
  2187.         $this->p_flags['get_source'] = true;
  2188.     }
  2189.     /**#@+
  2190.      * @access private
  2191.      * @param string token parsed from source
  2192.      * @param integer parser constant from {@link Parser.inc}
  2193.      */
  2194.     /**
  2195.      * handler for DOCKEYWORD_EMAIL.
  2196.      * this handler recognizes angle brackets < and > surrounding an email address in an @author tag,
  2197.      * and returns a mailto: hyperlink
  2198.      */
  2199.     
  2200.     function handleDockeywordEmail($word, $pevent)
  2201.     {
  2202.         //echo $this->wp->getPos() . ": |$word|\n";
  2203.         if (!$this->checkEventPop($word,$pevent) && $word != "<")
  2204.         {
  2205.             if (strstr($word,"@"))
  2206.             {
  2207.                 $this->p_vars['tag_value']->add('<');
  2208.                 $this->p_vars['tag_value']->add(new parserLinkInlineTag("mailto:$word",$word));
  2209.                 $this->p_vars['tag_value']->add('>');
  2210.             } else {
  2211.                 $this->p_vars['tag_value']->add("<$word>");
  2212.             }
  2213.         }
  2214.     }
  2215.  
  2216.     /**
  2217.      * handler for INLINE_DOCKEYWORD.
  2218.      * this handler recognizes {@inline tags} like link, and parses them, replacing them directly
  2219.      * in the text flow with their output.
  2220.      */
  2221.     
  2222.     function handleInlineDockeyword($word, $pevent)
  2223.     {
  2224.         //        echo $this->wp->getPos() . ": |$word|\n";
  2225.  
  2226.         //        echo "docktype: $this->p_vars['inline_dockeyword_type']\n";
  2227.         if (!isset($this->p_vars['inline_dockeyword_type'])) $this->p_vars['inline_dockeyword_type'] = false;
  2228.         if (!isset($this->p_vars['inline_dockeyword_data'])) $this->p_vars['inline_dockeyword_data'] = '';
  2229.         if (!$this->p_vars['inline_dockeyword_type'])
  2230.         {
  2231.             if (in_array($word,$this->allowableInlineTags))
  2232.             {
  2233.                 if ($word == '}')
  2234.                 $this->p_vars['inline_dockeyword_type'] = '';
  2235.                 else
  2236.                 $this->p_vars['inline_dockeyword_type'] = strtolower($word);
  2237.                 $this->p_vars['whitesp'] = $this->wp->returnWhiteSpace;
  2238.                 $this->wp->setWhiteSpace(true);
  2239.             } else {
  2240.                 if ($this->p_flags['in_desc'])
  2241.                 {
  2242.                     if ($word == '}')
  2243.                     $this->p_vars['line'][$this->p_vars['linecount']]->add('{@');
  2244.                     else
  2245.                     $this->p_vars['line'][$this->p_vars['linecount']]->add('{@'.$word);
  2246.                 } elseif($this->p_flags['in_tag'])
  2247.                 {
  2248.                     if ($word == '}')
  2249.                     $this->p_vars['tag_value']->add('{@'.$word);
  2250.                     else
  2251.                     $this->p_vars['tag_value']->add('{@'.$word);
  2252.                 }
  2253.                 $this->p_vars['event_stack']->popEvent();
  2254.                 $this->p_vars['inline_dockeyword_type'] = false;
  2255.                 $this->p_vars['inline_dockeyword_data'] = '';
  2256.                 return;
  2257.             }
  2258.         } else
  2259.         {
  2260.             if ($word != "}")
  2261.             {
  2262.                 $this->p_vars['inline_dockeyword_data'] .= $word;
  2263.             }
  2264.         }
  2265.         if ($this->checkEventPop($word,$pevent))
  2266.         {
  2267.             $this->wp->setWhiteSpace($this->p_vars['whitesp']);
  2268.             if ($this->p_vars['inline_dockeyword_type']=='link')
  2269.             {
  2270.                 // support hyperlinks of any protocol
  2271.                 if (is_numeric(strpos($this->p_vars['inline_dockeyword_data'],'://')) || (strpos(trim($this->p_vars['inline_dockeyword_data']),'mailto:') === 0))
  2272.                 {
  2273.                     // if there is more than 1 parameter, the stuff after the space is the hyperlink text
  2274.                     if (strpos(trim($this->p_vars['inline_dockeyword_data']),' '))
  2275.                     {
  2276.                         $i1 = strpos(trim($this->p_vars['inline_dockeyword_data']),' ') + 1;
  2277.                         $link = substr(trim($this->p_vars['inline_dockeyword_data']),0,$i1 - 1);
  2278.                         $text = substr(trim($this->p_vars['inline_dockeyword_data']),$i1);
  2279.                         $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($link,$text);
  2280. //                        '<a href="'.$link.'">'.$text.'</a>';
  2281.                     }
  2282.                     else
  2283.                     {
  2284.                         $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
  2285.                     }
  2286. //                    '<a href="'.$this->p_vars['inline_dockeyword_data'].'">'.$this->p_vars['inline_dockeyword_data'].'</a>';
  2287.                 } else
  2288.                 {
  2289.                     if (!strpos($this->p_vars['inline_dockeyword_data'],','))
  2290.                     {
  2291.                         $testp = explode('#',$this->p_vars['inline_dockeyword_data']);
  2292.                         if (count($testp) - 1)
  2293.                         $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$testp[1]);
  2294.                         else
  2295.                         $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
  2296.                     } else
  2297.                     $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
  2298.                 }
  2299.             }
  2300.             if ($this->p_vars['inline_dockeyword_type'] == 'tutorial')
  2301.             {
  2302.                 $this->p_vars['inline_dockeyword_data'] = new parserTutorialInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
  2303.             }
  2304.             if ($this->p_vars['inline_dockeyword_type'] == 'source')
  2305.             {
  2306.                 $this->getSource();
  2307.                 $this->p_vars['inline_dockeyword_data'] = new parserSourceInlineTag($this->p_vars['inline_dockeyword_data']);
  2308.             }
  2309.             if ($this->p_vars['inline_dockeyword_type'] == 'inheritdoc')
  2310.             {
  2311.                 $this->p_vars['inline_dockeyword_data'] = new parserInheritdocInlineTag();
  2312.             }
  2313.             if ($word == '*/')
  2314.             {
  2315.                 if (!isset($this->p_vars['inline_dockeyword_type'])) $this->p_vars['inline_dockeyword_type'] = '';
  2316.                 if (!isset($this->p_vars['tagname'])) $this->p_vars['tagname'] = '';
  2317.                 if (!isset($this->p_vars['tag_value']) || !is_object($this->p_vars['tag_value'])) $this->p_vars['tag_value'] = new parserStringWithInlineTags;
  2318.                 addError(PDERROR_UNTERMINATED_INLINE_TAG,$this->p_vars['inline_dockeyword_type'],$this->p_vars['tagname'],'@'.$this->p_vars['tagname'].' '.$this->p_vars['tag_value']->getString());
  2319.         // when we add the error class, raise error here: we reached the end of the docblock
  2320.                 $this->wp->backupPos($word); 
  2321.             }
  2322.             if ($this->p_flags['in_desc'])
  2323.             {
  2324.                 $this->p_vars['line'][$this->p_vars['linecount']]->add($this->p_vars['inline_dockeyword_data']);
  2325.                 $this->p_vars['inline_dockeyword_type'] = false;
  2326.                 $this->p_vars['inline_dockeyword_data'] = '';
  2327.             }
  2328.             elseif ($this->p_flags['in_tag'])
  2329.             {
  2330.                 $this->p_vars['tag_value']->add($this->p_vars['inline_dockeyword_data']);
  2331.                 $this->p_vars['inline_dockeyword_type'] = false;
  2332.                 $this->p_vars['inline_dockeyword_data'] = '';
  2333.             }
  2334.         }
  2335.     }
  2336.  
  2337.     /**
  2338.      * handler for INCLUDE.
  2339.      * this handler recognizes include/require/include_once/include_once statements, and publishes the
  2340.      * data to Render
  2341.      */
  2342.     
  2343.     function handleInclude($word, $pevent)
  2344.     {
  2345.         if (!$this->p_flags['in_include'])
  2346.         {
  2347.             $this->p_vars['linenum'] = $this->wp->linenum;
  2348.         }
  2349.         $this->p_flags['in_include'] = true;
  2350.         $a = $this->checkEventPush( $word, $pevent);
  2351.         if (!$this->p_flags['includename_isset'])
  2352.         {
  2353.             $this->p_flags['includename_isset'] = true;
  2354.             $this->p_vars['include_name'] = $this->p_vars['last_word'];
  2355.             if ($a)
  2356.             $this->p_vars['include_value'] = '';
  2357.             else
  2358.             $this->p_vars['include_value'] = $word;
  2359.             unset($this->p_vars['quote_data']);
  2360.         } else
  2361.         {
  2362.             if (!$a)
  2363.             {
  2364.                 if (empty($this->p_vars['include_params_data']))
  2365.                 {
  2366.                     if (isset($this->p_vars['quote_data']))
  2367.                     {
  2368.                         $this->p_vars['include_value'] .= '"'.$this->p_vars['quote_data'].'"';
  2369.                         unset($this->p_vars['quote_data']);
  2370.                     }
  2371.                     if ($word != ';')
  2372.                     $this->p_vars['include_value'] .= $word;
  2373.                 }
  2374.             } else
  2375.             {
  2376.                 $this->p_vars['include_params_data'] = '';
  2377.             }
  2378.         }
  2379.  
  2380.         if ($this->checkEventPop($word,$pevent))
  2381.         {
  2382.             $this->p_vars['include'] = new parserInclude;
  2383.             $this->p_vars['include']->setLineNumber($this->p_vars['linenum']);
  2384.             $this->p_flags['in_include'] = false;
  2385.             $this->p_vars['include']->setName($this->p_vars['include_name']);
  2386.             $this->p_vars['include']->setValue($this->p_vars['include_value']);
  2387.             $this->publishEvent(PHPDOCUMENTOR_EVENT_INCLUDE,$this->p_vars['include']);
  2388.             $this->p_flags['includename_isset'] = false;
  2389.             unset($this->p_vars['include']);
  2390.             unset($this->p_vars['include_name']);
  2391.             unset($this->p_vars['include_value']);
  2392.             unset($this->p_vars['include_params_data']);
  2393.         }
  2394.     }
  2395.     
  2396.     /**
  2397.      * handler for INCLUDE_PARAMS.
  2398.      * this handler parses the contents of ( ) in include/require/include_once/include_once statements
  2399.      */
  2400.     
  2401.     function handleIncludeParams($word, $pevent)
  2402.     {
  2403.         $this->checkEventPush( $word, $pevent);
  2404.         
  2405.         $this->p_flags['include_parens'] = true;
  2406.         if(!isset($this->p_vars['include_params_data'])) $this->p_vars['include_params_data'] = '';
  2407.         
  2408.         if ($this->checkEventPop($word,$pevent))
  2409.         {
  2410.             if (isset($this->p_vars['quote_data']))
  2411.             {
  2412.                 $this->p_vars['include_value'] = $this->p_vars['include_params_data'].'"'.$this->p_vars['quote_data'].'"';
  2413.                 unset($this->p_vars['quote_data']);
  2414.             } else {
  2415.                 if (!empty($this->p_vars['include_params_data']))
  2416.                 $this->p_vars['include_value'] = $this->p_vars['include_params_data'];
  2417.                 else
  2418.                 $this->p_vars['include_value'] = trim($this->p_vars['last_word']);
  2419.             }
  2420.         }
  2421.         if (isset($this->p_vars['quote_data']))
  2422.         {
  2423.             $this->p_vars['include_params_data'] .= '"'.$this->p_vars['quote_data'].'"';
  2424.             unset($this->p_vars['quote_data']);
  2425.         }
  2426.         if (($word != "'") && ($word != '"'))
  2427.         $this->p_vars['include_params_data'] .= $word;
  2428.     }
  2429.     
  2430.     /**
  2431.      * handler for INCLUDE_PARAMS_PARENTHESIS.
  2432.      * this handler takes all parenthetical statements within file in:
  2433.      * include statement include(file), and handles them properly
  2434.      */
  2435.     
  2436.     function handleIncludeParamsParenthesis($word, $pevent)
  2437.     {
  2438.         if (isset($this->p_vars['quote_data']))
  2439.         {
  2440.             $this->p_vars['include_params_data'] .= '"'.$this->p_vars['quote_data'].'"';
  2441.             unset($this->p_vars['quote_data']);
  2442.         }
  2443.         $this->p_vars['include_params_data'] .= $word;
  2444.         $this->checkEventPush( $word, $pevent);
  2445.         $this->checkEventPop( $word, $pevent);
  2446.     }
  2447.     /**#@-*/
  2448.     /**
  2449.      * this function checks whether parameter $word is a token for pushing a new event onto the Event Stack.
  2450.      * @return mixed    returns false, or the event number
  2451.      */
  2452.     
  2453.     function checkEventPush($word,$pevent)
  2454.     {
  2455.         $e = false;
  2456.         if (isset($this->pushEvent[$pevent]))
  2457.         {
  2458.             if (isset($this->pushEvent[$pevent][strtolower($word)]))
  2459.             $e = $this->pushEvent[$pevent][strtolower($word)];
  2460.         }
  2461.         if ($e)
  2462.         {
  2463.             $this->p_vars['event_stack']->pushEvent($e);
  2464.             return $e;
  2465.         } else {
  2466.             return false;
  2467.         }
  2468.     }
  2469.  
  2470.     /**
  2471.      * this function checks whether parameter $word is a token for popping the current event off of the Event Stack.
  2472.      * @return mixed    returns false, or the event number popped off of the stack
  2473.      */
  2474.     
  2475.     function checkEventPop($word,$pevent)
  2476.     {
  2477.         if (!isset($this->popEvent[$pevent])) return false;
  2478.         if (in_array(strtolower($word),$this->popEvent[$pevent]))
  2479.         {
  2480.             return $this->p_vars['event_stack']->popEvent();
  2481.         } else {
  2482.             return false;
  2483.         }
  2484.     }
  2485.  
  2486.     /**
  2487.      * setup the parser tokens, and the pushEvent/popEvent arrays
  2488.      * @see $tokens, $pushEvent, $popEvent
  2489.      */
  2490.     
  2491.     function setupStates()
  2492.     {
  2493.         $this->tokens[STATE_PHPCODE]            = array(" ", "\t",";","?>","</script>","/**#@+","/**#@-*/","/**", "//","/*","#","\r\n","\n","\r","(",'<<<','"',"'");
  2494.         $this->tokens[STATE_QUOTE]            = array("\\\"","\\\\","\"");
  2495.         $this->tokens[STATE_LOGICBLOCK]            = array("{","}","\"","'","/*","//","#","?>","</script>",'<<<','global','static');
  2496.         $this->tokens[STATE_FUNC_GLOBAL]        = array("\"","'","/*","//","#",";",",");
  2497.         $this->tokens[STATE_STATIC_VAR]        = array("\"","'","/*","//","#",";",",",'=','array');
  2498.         $this->tokens[STATE_STATIC_VAR_VALUE]        = array("/*","//","#"," ","\t",";","=","\"","'","array",",");
  2499.         $this->tokens[STATE_NOEVENTS]            = array("<?php","<?",'<script language="php">');
  2500.         $this->tokens[STATE_COMMENTBLOCK]        = array("*/","\n");
  2501.         $this->tokens[STATE_COMMENT]            = array("\r\n","\r","\n");
  2502.         $this->tokens[STATE_DEFINE]            = array(" ","(",";");
  2503.         $this->tokens[STATE_DEFINE_PARAMS]        = array("/*","//","#",",",")"," ","'","\"","(");
  2504.         $this->tokens[STATE_DEFINE_PARAMS_PARENTHESIS]    = array("(","'","\"",")");
  2505.         $this->tokens[STATE_FUNCTION_PARAMS]        = array("/*","//","#","\"",",",")","="," ","'","(");
  2506.         $this->tokens[STATE_SINGLEQUOTE]        = array("'","\\'","\\\\");
  2507.         $this->tokens[STATE_CLASS]            = array(" ","\t","?>","</script>",";","}","{","/**#@+","/**#@-*/","/**","//","/*","#","\r\n","\n","\r","(");
  2508.         $this->tokens[STATE_DOCBLOCK]            = array("*/","*","@","\r\n","\n","\r",". ",".\n",".\t",'{@');
  2509.         $this->tokens[STATE_DOCBLOCK_TEMPLATE]            = array("*/","*","@","\r\n","\n","\r",". ",".\n",".\t",'{@');
  2510.         $this->tokens[STATE_DOCKEYWORD]            = array("@","*/","*","\n","\r\n","\r","\t"," ","<",">",'{@');
  2511.         $this->tokens[STATE_INLINE_DOCKEYWORD]        = array("{@","}","\t"," ","*/");
  2512.         $this->tokens[STATE_DOCKEYWORD_EMAIL]        = array(">","\n","\r\n","\r");
  2513.         $this->tokens[STATE_VAR]            = array("/*","//","#"," ","\t",";","=",",","\"","'","array");
  2514.         $this->tokens[STATE_GLOBAL]            = array("/*","//","#"," ","\t",";","=","\"","'");
  2515.         $this->tokens[STATE_GLOBAL_VALUE]            = array("/*","//","#"," ","\t",";","=","\"","'","array");
  2516.         $this->tokens[STATE_ARRAY]            = array("/*","//","#","(",")","\"","'","array");
  2517.         $this->tokens[STATE_FUNCTION]            = array("(","{","}"," ","\t","&","/*","//","#");
  2518.         $this->tokens[STATE_OUTPHP]            = array("<?php","<?",'<script language="php">');
  2519.         $this->tokens[STATE_EOFQUOTE]            = array(" ","\t","\n");
  2520.         $this->tokens[STATE_ESCAPE]            = false;// this tells the word parser to just cycle
  2521.         $this->tokens[STATE_INCLUDE]            = array(" ","(",";","'",'"');
  2522.         $this->tokens[STATE_INCLUDE_PARAMS]        = array("/*",")"," ","'","\"","(");
  2523.         $this->tokens[STATE_INCLUDE_PARAMS_PARENTHESIS]    = array("(","'","\"",")");
  2524.  
  2525.         // For each event word to event mapings
  2526.         $this->pushEvent[PARSER_EVENT_QUOTE] = 
  2527.             array(
  2528.                 "\\"    => PARSER_EVENT_ESCAPE
  2529.             );
  2530.         $this->popEvent[PARSER_EVENT_QUOTE] = array("\"");
  2531. ##########################
  2532.          
  2533.         $this->pushEvent[PARSER_EVENT_LOGICBLOCK] = 
  2534.             array(
  2535.                 "\""    => PARSER_EVENT_QUOTE,
  2536.                 "'"    => PARSER_EVENT_SINGLEQUOTE,
  2537.                 "//"     => PARSER_EVENT_COMMENT,
  2538.                 "#"     => PARSER_EVENT_COMMENT,
  2539.                 "global"    => PARSER_EVENT_FUNC_GLOBAL,
  2540.                 "static"    => PARSER_EVENT_STATIC_VAR,
  2541.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2542.                 "{"    => PARSER_EVENT_LOGICBLOCK,
  2543.                 "?>"    => PARSER_EVENT_OUTPHP,
  2544.                 "</script>"    => PARSER_EVENT_OUTPHP,
  2545.                 "<<<"    => PARSER_EVENT_EOFQUOTE
  2546.             );
  2547.         $this->popEvent[PARSER_EVENT_LOGICBLOCK] = array("}");
  2548. ##########################
  2549.  
  2550.         $this->pushEvent[PARSER_EVENT_FUNC_GLOBAL] =
  2551.             array(
  2552.                 "\""    => PARSER_EVENT_QUOTE,
  2553.                 "'"    => PARSER_EVENT_SINGLEQUOTE,
  2554.                 "//"     => PARSER_EVENT_COMMENT,
  2555.                 "#"     => PARSER_EVENT_COMMENT,
  2556.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2557.             );
  2558.         $this->popEvent[PARSER_EVENT_FUNC_GLOBAL] = array(";");
  2559. ##########################
  2560.  
  2561.         $this->pushEvent[PARSER_EVENT_STATIC_VAR] =
  2562.             array(
  2563.                 "\""    => PARSER_EVENT_QUOTE,
  2564.                 "'"    => PARSER_EVENT_SINGLEQUOTE,
  2565.                 "//"     => PARSER_EVENT_COMMENT,
  2566.                 "#"     => PARSER_EVENT_COMMENT,
  2567.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2568.                 "="        => PARSER_EVENT_STATIC_VAR_VALUE,
  2569.             );
  2570.         $this->popEvent[PARSER_EVENT_STATIC_VAR] = array(";");
  2571. ##########################
  2572.  
  2573.         $this->pushEvent[PARSER_EVENT_STATIC_VAR_VALUE] = 
  2574.             array(
  2575.                 "\""    => PARSER_EVENT_QUOTE,
  2576.                 "'"    => PARSER_EVENT_SINGLEQUOTE,
  2577.                 "array" => PARSER_EVENT_ARRAY,
  2578.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2579.                 "//"     => PARSER_EVENT_COMMENT,
  2580.                 "#"     => PARSER_EVENT_COMMENT
  2581.             );
  2582.         $this->popEvent[PARSER_EVENT_STATIC_VAR_VALUE] = array(";",",");
  2583. ##########################
  2584.  
  2585.         $this->pushEvent[PARSER_EVENT_NOEVENTS] = 
  2586.             array(
  2587.                 "<?php" => PARSER_EVENT_PHPCODE,
  2588.                 "<?" => PARSER_EVENT_PHPCODE,
  2589.                 '<script language="php">' => PARSER_EVENT_PHPCODE,
  2590.             );
  2591. ##########################
  2592.  
  2593.         $this->pushEvent[PARSER_EVENT_PHPCODE] = 
  2594.             array(
  2595.                 "function"     => PARSER_EVENT_FUNCTION,
  2596.                 "class"     => PARSER_EVENT_CLASS,
  2597.                 "define"     => PARSER_EVENT_DEFINE,
  2598.                 "include_once" => PARSER_EVENT_INCLUDE,
  2599.                 "require_once" => PARSER_EVENT_INCLUDE,
  2600.                 "include"    => PARSER_EVENT_INCLUDE,
  2601.                 "require"    => PARSER_EVENT_INCLUDE,
  2602.                 "//"         => PARSER_EVENT_COMMENT,
  2603.                 "#"         => PARSER_EVENT_COMMENT,
  2604.                 "/*"         => PARSER_EVENT_COMMENTBLOCK,
  2605.                 "/**"         => PARSER_EVENT_DOCBLOCK,
  2606.                 "/**#@+"    => PARSER_EVENT_DOCBLOCK_TEMPLATE,
  2607.                 "/**#@-*/"    => PARSER_EVENT_END_DOCBLOCK_TEMPLATE,
  2608.                 "\""        => PARSER_EVENT_QUOTE,
  2609.                 "'"        => PARSER_EVENT_SINGLEQUOTE,
  2610.                 "<<<"        => PARSER_EVENT_EOFQUOTE,
  2611.                 "?>"         => PARSER_EVENT_OUTPHP,
  2612.                 "</script>"         => PARSER_EVENT_OUTPHP,
  2613.             );
  2614. ##########################
  2615.  
  2616.         $this->pushEvent[PARSER_EVENT_FUNCTION] = 
  2617.             array(
  2618.                 "("     => PARSER_EVENT_FUNCTION_PARAMS,
  2619.                 "//"     => PARSER_EVENT_COMMENT,
  2620.                 "#"     => PARSER_EVENT_COMMENT,
  2621.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2622.                 "{"     => PARSER_EVENT_LOGICBLOCK
  2623.             );
  2624.         $this->popEvent[PARSER_EVENT_FUNCTION] = array("}");
  2625. ##########################
  2626.  
  2627.         $this->pushEvent[PARSER_EVENT_DOCBLOCK] = 
  2628.             array(
  2629.                 "@"     => PARSER_EVENT_DOCKEYWORD,
  2630.                 "{@"    => PARSER_EVENT_INLINE_DOCKEYWORD
  2631.             );
  2632.         $this->popEvent[PARSER_EVENT_DOCBLOCK] = array("*/");
  2633. ##########################
  2634.  
  2635.         $this->pushEvent[PARSER_EVENT_DOCBLOCK_TEMPLATE] = 
  2636.             array(
  2637.                 "@"     => PARSER_EVENT_DOCKEYWORD,
  2638.                 "{@"    => PARSER_EVENT_INLINE_DOCKEYWORD
  2639.             );
  2640.         $this->popEvent[PARSER_EVENT_DOCBLOCK_TEMPLATE] = array("*/");
  2641. ##########################
  2642.  
  2643.         $this->pushEvent[PARSER_EVENT_CLASS] = 
  2644.             array(
  2645.                 "function"     => PARSER_EVENT_FUNCTION,
  2646.                 "var"         => PARSER_EVENT_VAR,
  2647.                 "/**"         => PARSER_EVENT_DOCBLOCK,
  2648.                 "/**#@+"    => PARSER_EVENT_DOCBLOCK_TEMPLATE,
  2649.                 "/**#@-*/"    => PARSER_EVENT_END_DOCBLOCK_TEMPLATE,
  2650.                 "//"         => PARSER_EVENT_COMMENT,
  2651.                 "/*"         => PARSER_EVENT_COMMENTBLOCK,
  2652.                 "#"         => PARSER_EVENT_COMMENT,
  2653.                 "?>"        => PARSER_EVENT_OUTPHP,
  2654.                 "</script>"    => PARSER_EVENT_OUTPHP,
  2655.             );
  2656.         $this->popEvent[PARSER_EVENT_CLASS] = array("}");
  2657. ##########################
  2658.  
  2659.         $this->pushEvent[PARSER_EVENT_DEFINE] = 
  2660.             array(
  2661.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2662.                 "("     => PARSER_EVENT_DEFINE_PARAMS
  2663.             );
  2664.         $this->popEvent[PARSER_EVENT_DEFINE] = array(";");
  2665. ##########################
  2666.  
  2667.         $this->pushEvent[PARSER_EVENT_INCLUDE] = 
  2668.             array(
  2669.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2670.                 "("     => PARSER_EVENT_INCLUDE_PARAMS,
  2671.                 "'"        => PARSER_EVENT_SINGLEQUOTE,
  2672.                 '"'        => PARSER_EVENT_QUOTE,
  2673.             );
  2674.         $this->popEvent[PARSER_EVENT_INCLUDE] = array(";");
  2675. ##########################
  2676.  
  2677.         $this->pushEvent[PARSER_EVENT_DEFINE_PARAMS] = 
  2678.             array(
  2679.                 "("    =>    PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
  2680.                 "'"        => PARSER_EVENT_SINGLEQUOTE,
  2681.                 '"' =>    PARSER_EVENT_QUOTE,
  2682.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2683.                 "//"     => PARSER_EVENT_COMMENT,
  2684.                 "#"     => PARSER_EVENT_COMMENT
  2685.             );
  2686.         $this->popEvent[PARSER_EVENT_DEFINE_PARAMS] = array(")");
  2687. ##########################
  2688.  
  2689.         $this->pushEvent[PARSER_EVENT_INCLUDE_PARAMS] = 
  2690.             array(
  2691.                 "("    =>    PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
  2692.                 "'" =>    PARSER_EVENT_SINGLEQUOTE,
  2693.                 '"' =>    PARSER_EVENT_QUOTE,
  2694.             );
  2695.         $this->popEvent[PARSER_EVENT_INCLUDE_PARAMS] = array(")");
  2696. ##########################
  2697.  
  2698.         $this->pushEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] =
  2699.             array(
  2700.                 "("    =>    PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
  2701.                 "'" =>    PARSER_EVENT_SINGLEQUOTE,
  2702.                 '"' =>    PARSER_EVENT_QUOTE,
  2703.             );
  2704.         $this->popEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] = array(")");
  2705. ##########################
  2706.  
  2707.         $this->pushEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] =
  2708.             array(
  2709.                 "("    =>    PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
  2710.                 "'" =>    PARSER_EVENT_SINGLEQUOTE,
  2711.                 '"' =>    PARSER_EVENT_QUOTE,
  2712.             );
  2713.         $this->popEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] = array(")");
  2714. ##########################
  2715.  
  2716.         $this->pushEvent[PARSER_EVENT_VAR] = 
  2717.             array(
  2718.                 "\""    => PARSER_EVENT_QUOTE,
  2719.                 "'"    => PARSER_EVENT_SINGLEQUOTE,
  2720.                 "array" => PARSER_EVENT_ARRAY,
  2721.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2722.                 "//"     => PARSER_EVENT_COMMENT,
  2723.                 "#"     => PARSER_EVENT_COMMENT
  2724.             );
  2725.         $this->popEvent[PARSER_EVENT_VAR] = array(";");
  2726. ##########################
  2727.  
  2728.         $this->pushEvent[PARSER_EVENT_DEFINE_GLOBAL] = 
  2729.             array(
  2730.                 "="    => PARSER_EVENT_GLOBAL_VALUE,
  2731.                 "\""    => PARSER_EVENT_QUOTE,
  2732.                 "'"    => PARSER_EVENT_SINGLEQUOTE,
  2733.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2734.                 "//"     => PARSER_EVENT_COMMENT,
  2735.                 "#"     => PARSER_EVENT_COMMENT
  2736.             );
  2737.         $this->popEvent[PARSER_EVENT_DEFINE_GLOBAL] = array(";");
  2738. ##########################
  2739.  
  2740.         $this->pushEvent[PARSER_EVENT_GLOBAL_VALUE] = 
  2741.             array(
  2742.                 "\""    => PARSER_EVENT_QUOTE,
  2743.                 "'"    => PARSER_EVENT_SINGLEQUOTE,
  2744.                 "array" => PARSER_EVENT_ARRAY,
  2745.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2746.                 "//"     => PARSER_EVENT_COMMENT,
  2747.                 "#"     => PARSER_EVENT_COMMENT
  2748.             );
  2749.         $this->popEvent[PARSER_EVENT_GLOBAL_VALUE] = array(";");
  2750. ##########################
  2751.  
  2752.         $this->pushEvent[PARSER_EVENT_COMMENT] = 
  2753.             array(
  2754.                 "\\"    => PARSER_EVENT_ESCAPE
  2755.             );
  2756.         $this->popEvent[PARSER_EVENT_COMMENT] = array("\n");
  2757. ##########################
  2758.  
  2759.         $this->popEvent[PARSER_EVENT_COMMENTBLOCK] = array("*/");
  2760. ##########################
  2761.         $this->pushEvent[PARSER_EVENT_SINGLEQUOTE] = 
  2762.             array(
  2763.                 "\\"    => PARSER_EVENT_ESCAPE
  2764.             );
  2765.  
  2766.         $this->popEvent[PARSER_EVENT_SINGLEQUOTE] = array("'");
  2767. ##########################
  2768.         $this->pushEvent[PARSER_EVENT_FUNCTION_PARAMS] = 
  2769.             array(
  2770.                 "\""    => PARSER_EVENT_QUOTE,
  2771.                 "'"    => PARSER_EVENT_SINGLEQUOTE,
  2772.                 "array" => PARSER_EVENT_ARRAY,
  2773.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2774.                 "//"     => PARSER_EVENT_COMMENT,
  2775.                 "#"     => PARSER_EVENT_COMMENT
  2776.             );
  2777.         $this->popEvent[PARSER_EVENT_FUNCTION_PARAMS] = array(")");
  2778. ##########################
  2779.         $this->pushEvent[PARSER_EVENT_DOCKEYWORD] = 
  2780.             array(
  2781. //                "<"    => PARSER_EVENT_DOCKEYWORD_EMAIL,
  2782.                 "{@" => PARSER_EVENT_INLINE_DOCKEYWORD,
  2783.             );
  2784.  
  2785.         $this->popEvent[PARSER_EVENT_DOCKEYWORD] = array("*/");
  2786. ##########################
  2787.  
  2788.         $this->popEvent[PARSER_EVENT_INLINE_DOCKEYWORD] = array("}","*/");
  2789. ##########################
  2790.  
  2791.         $this->popEvent[PARSER_EVENT_OUTPHP] = array("<?php","<?",'<script language="php">');
  2792. ##########################
  2793.  
  2794.         $this->popEvent[PARSER_EVENT_DOCKEYWORD_EMAIL] = array(">","\n");
  2795.  
  2796. ##########################
  2797.         $this->pushEvent[PARSER_EVENT_ARRAY] = 
  2798.             array(
  2799.                 "\""    => PARSER_EVENT_QUOTE,
  2800.                 "'"    => PARSER_EVENT_SINGLEQUOTE,
  2801.                 "array" => PARSER_EVENT_ARRAY,
  2802.                 "/*"     => PARSER_EVENT_COMMENTBLOCK,
  2803.                 "//"     => PARSER_EVENT_COMMENT,
  2804.                 "#"     => PARSER_EVENT_COMMENT
  2805.             );
  2806.         $this->popEvent[PARSER_EVENT_ARRAY] = array(")");
  2807. ##########################
  2808.     }
  2809.  
  2810.     /**
  2811.      * tell the parser's WordParser {@link $wp} to set up tokens to parse words by.
  2812.      * tokens are word separators.  In English, a space or punctuation are examples of tokens.
  2813.      * In PHP, a token can be a ;, a parenthesis, or even the word "function"
  2814.      * @param    $value integer an event number
  2815.      * @see WordParser
  2816.      */
  2817.     
  2818.     function configWordParser($e)
  2819.     {
  2820.         $this->wp->setSeperator($this->tokens[($e + 100)]);
  2821.     }
  2822.  
  2823.     /**
  2824.      * Debugging function, takes an event number and attempts to return its name
  2825.      * @param    $value integer an event number
  2826.      */
  2827.     
  2828.  
  2829.     function getParserEventName ($value)
  2830.     {    
  2831.         $lookup = array(
  2832.             PARSER_EVENT_NOEVENTS         => "PARSER_EVENT_NOEVENTS",
  2833.             PARSER_EVENT_PHPCODE        => "PARSER_EVENT_PHPCODE",
  2834.             PARSER_EVENT_DOCBLOCK        => "PARSER_EVENT_DOCBLOCK",
  2835.             PARSER_EVENT_FUNCTION        => "PARSER_EVENT_FUNCTION",
  2836.             PARSER_EVENT_CLASS        => "PARSER_EVENT_CLASS",
  2837.             PARSER_EVENT_DEFINE        => "PARSER_EVENT_DEFINE",
  2838.             PARSER_EVENT_DEFINE_PARAMS    => "PARSER_EVENT_DEFINE_PARAMS",
  2839.             PARSER_EVENT_COMMENT        => "PARSER_EVENT_COMMENT",
  2840.             PARSER_EVENT_COMMENTBLOCK    => "PARSER_EVENT_COMMENTBLOCK",
  2841.             PARSER_EVENT_ESCAPE        => "PARSER_EVENT_ESCAPE",
  2842.             PARSER_EVENT_QUOTE        => "PARSER_EVENT_QUOTE",
  2843.             PARSER_EVENT_FUNCTION_PARAMS    => "PARSER_EVENT_FUNCTION_PARAMS",
  2844.             PARSER_EVENT_SINGLEQUOTE    => "PARSER_EVENT_SINGLEQUOTE",
  2845.             PARSER_EVENT_VAR        => "PARSER_EVENT_VAR",
  2846.             PARSER_EVENT_LOGICBLOCK        => "PARSER_EVENT_LOGICBLOCK",
  2847.             PARSER_EVENT_OUTPHP        => "PARSER_EVENT_OUTPHP",
  2848.             PARSER_EVENT_DOCKEYWORD        => "PARSER_EVENT_DOCKEYWORD",
  2849.             PARSER_EVENT_DOCKEYWORD_EMAIL    => "PARSER_EVENT_DOCKEYWORD_EMAIL",
  2850.             PARSER_EVENT_ARRAY        => "PARSER_EVENT_ARRAY",
  2851.             PARSER_EVENT_INLINE_DOCKEYWORD    =>    "PARSER_EVENT_INLINE_DOCKEYWORD",
  2852.             PARSER_EVENT_EOFQUOTE    =>    "PARSER_EVENT_EOFQUOTE",
  2853.             PARSER_EVENT_INCLUDE    =>    "PARSER_EVENT_INCLUDE",
  2854.             PARSER_EVENT_INCLUDE_PARAMS    =>    "PARSER_EVENT_INCLUDE_PARAMS",
  2855.             PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS    => "PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS",
  2856.             PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS => "PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS",
  2857.             PARSER_EVENT_DEFINE_GLOBAL => "PARSER_EVENT_DEFINE_GLOBAL",
  2858.             PARSER_EVENT_GLOBAL_VALUE => "PARSER_EVENT_GLOBAL_VALUE",
  2859.             PARSER_EVENT_FUNC_GLOBAL => "PARSER_EVENT_FUNC_GLOBAL",
  2860.             PARSER_EVENT_STATIC_VAR => "PARSER_EVENT_STATIC_VAR",
  2861.             PARSER_EVENT_DOCBLOCK_TEMPLATE => "PARSER_EVENT_DOCBLOCK_TEMPLATE",
  2862.             PARSER_EVENT_END_DOCBLOCK_TEMPLATE => "PARSER_EVENT_END_DOCBLOCK_TEMPLATE",
  2863.             PARSER_EVENT_METHOD_LOGICBLOCK => 'PARSER_EVENT_METHOD_LOGICBLOCK',
  2864.             PARSER_EVENT_CLASS_MEMBER => 'PARSER_EVENT_CLASS_MEMBER',
  2865.             PARSER_EVENT_METHOD => 'PARSER_EVENT_METHOD',
  2866.             PARSER_EVENT_QUOTE_VAR => 'PARSER_EVENT_QUOTE_VAR',
  2867.         );
  2868.         if (isset($lookup[$value]))
  2869.         return $lookup[$value];
  2870.         else return $value;
  2871.     }
  2872. }
  2873.  
  2874. /**
  2875.  * Global package page parser
  2876.  *
  2877.  * @deprecated in favor of tutorials
  2878.  * @tutorial tutorials.pkg
  2879.  * @package phpDocumentor
  2880.  * @subpackage Parsers
  2881.  */
  2882. class ppageParser extends Parser
  2883. {
  2884.     /** @var string */
  2885.     var $package = false;
  2886.     /** @var string */
  2887.     var $subpackage = '';
  2888.     /**
  2889.      * set up invariant Parser variables
  2890.      */
  2891.     function ppageParser()
  2892.     {
  2893.         Parser::Parser();
  2894.         $this->allowableInlineTags = $GLOBALS['_phpDocumentor_inline_tutorial_tags_allowed'];
  2895.         $this->eventHandlers = array();
  2896.         $this->eventHandlers[PARSER_EVENT_NOEVENTS] = 'defaultHandler';
  2897.         $this->eventHandlers[PARSER_EVENT_INLINE_DOCKEYWORD] = 'handleInlineDocKeyword';
  2898.     }
  2899.     
  2900.     /**
  2901.      * set up invariant Parser variables
  2902.      */
  2903.     function setupStates()
  2904.     {
  2905.         $this->tokens[STATE_NOEVENTS]        = array("{@","}");
  2906.         $this->tokens[STATE_INLINE_DOCKEYWORD]        = array("{@","}","\t"," ");
  2907.  
  2908. ##########################
  2909.  
  2910.         $this->pushEvent[PARSER_EVENT_NOEVENTS] = 
  2911.             array(
  2912.                 "{@" => PARSER_EVENT_INLINE_DOCKEYWORD
  2913.             );
  2914. ##########################
  2915.  
  2916.         $this->popEvent[PARSER_EVENT_INLINE_DOCKEYWORD] = array("}");
  2917.     }
  2918.     
  2919.     /**
  2920.      * Parse a new file
  2921.      *
  2922.      * @param    string    $parse_data
  2923.      * @param    string    $package
  2924.      * @param    int    $subpackage
  2925.      * @return    mixed    false or parsed data
  2926.      */
  2927.     function parse (&$parse_data,$xml,$package = 'default',$subpackage = '',$tutorial = '',$category='default')
  2928.     {
  2929.         $this->setupStates();
  2930.         $this->p_vars['total'] = new parserPackagePage($package,$xml);
  2931.         $this->p_vars['tutorial'] = $tutorial;
  2932.         $this->category = $category;
  2933.         $this->package = $package;
  2934.         if (!isset($subpackage) || !$subpackage) $subpackage = '';
  2935.         $this->subpackage = $subpackage;
  2936.         if (strlen($parse_data) == 0)
  2937.         {
  2938.             return false;
  2939.         }
  2940.  
  2941.         // initialize variables so E_ALL error_reporting doesn't complain
  2942.         $pevent = 0;
  2943.         $word = 0;
  2944.         $this->p_vars['event_stack'] = new EventStack;
  2945.         // change this to a new ParserStringWithInlineTags, and change all $total .= blah to $total->add(blah)
  2946.         // then modify phpDocumentor_IntermediateParser->Convert to convert all package pages (the package page handler in phpDocumentor_IntermediateParser should
  2947.         // save them all in a variable) to perform the linking.  then, remove the legacy code from handleDocBlock
  2948.         // and handleClass in Render.inc, and do a loop that converts each package page, and passes it to handleEvent
  2949.         // just like Converter::walk does with the other elements.  The only other addition that might be good is a
  2950.         // new descendant of parserElement parserPackagePage that contains the data and stuff.  Hope this helps :)
  2951.         $total = '';
  2952.  
  2953.         $this->wp->setup($parse_data);
  2954.  
  2955.         $this->p_flags['reset_quote_data'] = true;
  2956.  
  2957.         do
  2958.         {
  2959.             $lpevent = $pevent;
  2960.             $pevent = $this->p_vars['event_stack']->getEvent();
  2961.             if ($lpevent != $pevent)
  2962.             {
  2963.                 $this->p_vars['last_pevent'] = $lpevent;
  2964.             }
  2965.  
  2966.             if ($this->p_vars['last_pevent'] != $pevent)
  2967.             {
  2968.                 // its a new event so the word parser needs to be reconfigured 
  2969.                 $this->configWordParser($pevent);
  2970.             }
  2971.  
  2972.             if (!$xml)
  2973.             $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,($pevent + 100));
  2974.  
  2975.  
  2976.             $this->p_vars['last_word'] = $word;
  2977.             $word = $this->wp->getWord();
  2978.  
  2979.             if (0)//PHPDOCUMENTOR_DEBUG == true)
  2980.             {
  2981.                 echo "LAST: |" . $this->p_vars['last_word'] . "|\n";
  2982.                 echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";
  2983.                 echo $this->wp->getPos() . ": |$word|\n";
  2984.             }
  2985.             if (isset($this->eventHandlers[$pevent]))
  2986.             {
  2987.                 $handle = $this->eventHandlers[$pevent];
  2988.                 $this->$handle($word, $pevent);
  2989.             }
  2990.         } while (!($word === false));
  2991.         if (!$xml)
  2992.         $this->PublishEvent(PHPDOCUMENTOR_EVENT_PACKAGEPAGE,$this->p_vars['total']);
  2993.         else
  2994.         return $this->p_vars['total']->value;
  2995.     }
  2996.     
  2997.     /**
  2998.      * Handles all non-inline tags
  2999.      * 
  3000.      * @param string token
  3001.      * @param integer parser event
  3002.      */
  3003.     function defaultHandler($word, $pevent)
  3004.     {
  3005.         if (!$this->checkEventPush( $word, $pevent))
  3006.         {
  3007.             if ($word) $this->p_vars['total']->add($word);
  3008.         }
  3009.     }
  3010.  
  3011.     /**
  3012.      * handler for INLINE_DOCKEYWORD.
  3013.      * this handler recognizes {@inline tags} like link, and parses them, replacing them directly
  3014.      * in the text flow with their output.
  3015.      * @param string token
  3016.      * @param integer parser event
  3017.      */
  3018.     
  3019.     function handleInlineDockeyword($word, $pevent)
  3020.     {
  3021.         //        echo $this->wp->getPos() . ": |$word|\n";
  3022.  
  3023.         //        echo "docktype: $this->p_vars['inline_dockeyword_type']\n";
  3024.         if (!isset($this->p_vars['inline_dockeyword_type'])) $this->p_vars['inline_dockeyword_type'] = false;
  3025.         if (!isset($this->p_vars['inline_dockeyword_data'])) $this->p_vars['inline_dockeyword_data'] = '';
  3026.         if (!$this->p_vars['inline_dockeyword_type'])
  3027.         {
  3028.             if (in_array($word,$this->allowableInlineTags))
  3029.             {
  3030.                 $this->p_vars['inline_dockeyword_type'] = strtolower($word);
  3031.                 $this->p_vars['whitesp'] = $this->wp->returnWhiteSpace;
  3032.                 $this->wp->setWhiteSpace(true);
  3033.             } else {
  3034.                 if ($word == '}')
  3035.                 $this->p_vars['total']->add('{@');
  3036.                 else
  3037.                 {
  3038.                     $this->p_vars['total']->add('{@'.$word);
  3039.                     $this->p_vars['event_stack']->popEvent();
  3040.                 }
  3041.                 $this->p_vars['inline_dockeyword_type'] = false;
  3042.                 $this->p_vars['inline_dockeyword_data'] = '';
  3043.             }
  3044.         } else
  3045.         {
  3046.             if ($word != "}")
  3047.             {
  3048.                 $this->p_vars['inline_dockeyword_data'] .= $word;
  3049.             }
  3050.         }
  3051.         if ($this->checkEventPop($word,$pevent))
  3052.         {
  3053.             $this->wp->setWhiteSpace($this->p_vars['whitesp']);
  3054.             if ($this->p_vars['inline_dockeyword_type']=='link')
  3055.             {
  3056.                 // support hyperlinks of any protocol
  3057.                 if (is_numeric(strpos($this->p_vars['inline_dockeyword_data'],'://')) || (strpos(trim($this->p_vars['inline_dockeyword_data']),'mailto:') === 0))
  3058.                 {
  3059.                     // if there is more than 1 parameter, the stuff after the space is the hyperlink text
  3060.                     if (strpos(trim($this->p_vars['inline_dockeyword_data']),' '))
  3061.                     {
  3062.                         $i1 = strpos(trim($this->p_vars['inline_dockeyword_data']),' ') + 1;
  3063.                         $link = substr(trim($this->p_vars['inline_dockeyword_data']),0,$i1 - 1);
  3064.                         $text = substr(trim($this->p_vars['inline_dockeyword_data']),$i1);
  3065.                         $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($link,$text);
  3066. //                        '<a href="'.$link.'">'.$text.'</a>';
  3067.                     }
  3068.                     else
  3069.                     {
  3070.                         $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
  3071.                     }
  3072. //                    '<a href="'.$this->p_vars['inline_dockeyword_data'].'">'.$this->p_vars['inline_dockeyword_data'].'</a>';
  3073.                 } else
  3074.                 {
  3075.                     $testp = explode('#',$this->p_vars['inline_dockeyword_data']);
  3076.                     if (count($testp) - 1) $this->p_vars['inline_dockeyword_data'] = $testp[1];
  3077.                     $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
  3078.                 }
  3079.             }
  3080.             if ($this->p_vars['inline_dockeyword_type']=='id')
  3081.             {
  3082.                 $this->p_vars['inline_dockeyword_data'] = new parserIdInlineTag($this->category,$this->package,$this->subpackage,$this->p_vars['tutorial'],trim($this->p_vars['inline_dockeyword_data']));
  3083.             }
  3084.             if ($this->p_vars['inline_dockeyword_type'] == 'tutorial')
  3085.             {
  3086.                 $this->p_vars['inline_dockeyword_data'] = new parserTutorialInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
  3087.             }
  3088.             if ($this->p_vars['inline_dockeyword_type'] == 'toc')
  3089.             {
  3090.                 $this->p_vars['inline_dockeyword_data'] = new parserTocInlineTag();
  3091.             }
  3092.             $this->p_vars['total']->add($this->p_vars['inline_dockeyword_data']);
  3093.             $this->p_vars['inline_dockeyword_type'] = false;
  3094.             $this->p_vars['inline_dockeyword_data'] = '';
  3095.         }
  3096.     }
  3097. }
  3098. ?>
  3099.