home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / PhpDocumentor / phpDocumentor / Parser.inc < prev    next >
Encoding:
Text File  |  2008-07-02  |  133.2 KB  |  3,253 lines

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