From 588727c7e2b8954ec3dbde293cf4c4d68b119f9b Mon Sep 17 00:00:00 2001 From: xue <> Date: Mon, 19 Jun 2006 18:38:29 +0000 Subject: Merge from 3.0 branch till 1185. --- .../PhpDocumentor/phpDocumentor/Parser.inc | 3185 ++++++++++++++++++++ 1 file changed, 3185 insertions(+) create mode 100644 buildscripts/PhpDocumentor/phpDocumentor/Parser.inc (limited to 'buildscripts/PhpDocumentor/phpDocumentor/Parser.inc') diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Parser.inc b/buildscripts/PhpDocumentor/phpDocumentor/Parser.inc new file mode 100644 index 00000000..55e67685 --- /dev/null +++ b/buildscripts/PhpDocumentor/phpDocumentor/Parser.inc @@ -0,0 +1,3185 @@ + is encountered in parsing an @author tag*/ +define("PARSER_EVENT_DOCKEYWORD_EMAIL" , 114); +/** currently parsing an email in brackets in an @author tag of a DocBlock */ +define("STATE_DOCKEYWORD_EMAIL" , 214); + +/** used when an array definition is encountered in parsing */ +define("PARSER_EVENT_ARRAY" , 115); +/** currently parsing an array */ +define("STATE_ARRAY" , 215); + +/** used when a var statement is encountered in parsing a class definition */ +define("PARSER_EVENT_VAR" , 116); +/** currently parsing a Class variable */ +define("STATE_VAR" , 216); + +/** used when a function definition is encountered in parsing */ +define("PARSER_EVENT_FUNCTION" , 117); +/** currently parsing a Function or Method */ +define("STATE_FUNCTION" , 217); + +/** used when a ? > (with no space) is encountered in parsing */ +define("PARSER_EVENT_OUTPHP" , 118); +/** currently out of php code */ +define("STATE_OUTPHP" , 218); + +/** used when an inline {@tag} is encountered in parsing a DocBlock */ +define("PARSER_EVENT_INLINE_DOCKEYWORD" , 119); +/** currently parsing an inline tag like { @link} in a DocBlock */ +define("STATE_INLINE_DOCKEYWORD" , 219); + +/** used when a define statement's opening parenthesis is encountered in parsing */ +define("PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS" , 120); +/** currently parsing an inner parenthetical statement of a define( ) */ +define("STATE_DEFINE_PARAMS_PARENTHESIS" , 220); + +define("PARSER_EVENT_END_STATEMENT", 121); + +/** used when a <<< is encountered in parsing */ +define("PARSER_EVENT_EOFQUOTE" , 122); +/** currently parsing a string defined using Perl <<< */ +define("STATE_EOFQUOTE" , 222); + +/** used when an include/require/include_once/include_once statement is encountered in parsing */ +define("PARSER_EVENT_INCLUDE" , 123); +/** currently parsing an include/require/include_once/include_once */ +define("STATE_INCLUDE" , 223); + +/** used when an opening parenthesis of an include/require/include_once/include_once statement is encountered in parsing */ +define("PARSER_EVENT_INCLUDE_PARAMS" , 124); +/** currently parsing the stuff in ( ) of a define statement */ +define("STATE_INCLUDE_PARAMS" , 224); + +/** used when an inner ( ) is encountered while parsing an include/require/include_once/include_once statement */ +define("PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS" , 125); +/** currently parsing an inner parenthetical statement of an include/includeonce/require/requireonce( ) */ +define("STATE_INCLUDE_PARAMS_PARENTHESIS" , 225); + +/** used when parsing the desc part of a docblock */ +define("PARSER_EVENT_DESC" , 126); +/** currently parsing the desc part of a docblock */ +define("STATE_DESC" , 226); + +/** used when parsing the @tag block of a docblock */ +define("PARSER_EVENT_TAGS" , 127); +/** currently parsing the @tag block of a docblock */ +define("STATE_TAGS" , 227); + +/** used when parsing a global variable declaration */ +define("PARSER_EVENT_DEFINE_GLOBAL" , 128); +/** currently parsing a global variable declaration */ +define("STATE_GLOBAL" , 228); + +/** used when parsing the default value in a global variable declaration */ +define("PARSER_EVENT_GLOBAL_VALUE" , 129); +/** currently parsing the default value in a global variable declaration */ +define("STATE_GLOBAL_VALUE" , 229); + +/** used when parsing a "global $var1, $var2;" declaration in a function */ +define("PARSER_EVENT_FUNC_GLOBAL" , 130); +/** currently parsing a "global $var1, $var2;" declaration in a function */ +define("STATE_FUNC_GLOBAL" , 230); + +/** used when parsing a "static $var1, $var2;" declaration in a function */ +define("PARSER_EVENT_STATIC_VAR" , 131); +/** currently parsing a "static $var1, $var2;" declaration in a function */ +define("STATE_STATIC_VAR" , 231); + +/** used when parsing the value in a "static $var1 = x" declaration in a function */ +define("PARSER_EVENT_STATIC_VAR_VALUE" , 132); +/** currently parsing the value in a "static $var1 = x" declaration in a function */ +define("STATE_STATIC_VAR_VALUE" , 232); + +/** used when encountering a /**#@+ comment marking a new docblock template */ +define("PARSER_EVENT_DOCBLOCK_TEMPLATE" , 133); +/** currently parsing the value in a "static $var1 = x" declaration in a function */ +define("STATE_DOCBLOCK_TEMPLATE" , 233); + +/** used when encountering a /**#@-* / comment (no space) marking the end of using a docblock template */ +define("PARSER_EVENT_END_DOCBLOCK_TEMPLATE" , 134); +/** currently parsing the value in a "static $var1 = x" declaration in a function */ +define("STATE_END_DOCBLOCK_TEMPLATE" , 234); + +/** used by the {@link HighlightParser} only, when a method starts */ +define("PARSER_EVENT_METHOD" , 135); +/** currently parsing a method using the {@link HighlightParser} */ +define("STATE_METHOD" , 235); + +/** used by the {@link HighlightParser} only, when a method body is parsed */ +define("PARSER_EVENT_METHOD_LOGICBLOCK" , 136); +/** currently parsing the method body using the {@link HighlightParser} */ +define("STATE_METHOD_LOGICBLOCK" , 236); + +/** used by the {@link HighlightParser} only, when ->var or ->function() is encountered in a method */ +define("PARSER_EVENT_CLASS_MEMBER" , 137); +/** currently parsing a class member using the {@link HighlightParser} */ +define("STATE_CLASS_MEMBER" , 237); + +/** used by the {@link HighlightParser} only, when {$var} is encountered in a string */ +define("PARSER_EVENT_QUOTE_VAR" , 138); +/** currently parsing a {$encapsed_var} using the {@link HighlightParser} */ +define("STATE_QUOTE_VAR" , 238); + +/** used when parsing an access modifier */ +define("PARSER_EVENT_ACCESS_MODIFIER" , 139); +/** currently parsing an access modifier */ +define("STATE_ACCESS_MODIFIER" , 239); + +/** used when a class implements interfaces */ +define("PARSER_EVENT_IMPLEMENTS" , 140); +/** currently parsing an implements clause */ +define("STATE_IMPLEMENTS" , 240); + +/** used when a class implements interfaces */ +define("PARSER_EVENT_CLASS_CONSTANT" , 141); +/** currently parsing a class constant */ +define("STATE_CLASS_CONSTANT" , 241); + +/** used when a variable value is an array */ +define("PARSER_EVENT_VAR_ARRAY" , 142); +/** currently parsing a variable value is an array */ +define("STATE_VAR_ARRAY" , 242); + +/** used when a comment is found in a variable array value */ +define("PARSER_EVENT_VAR_ARRAY_COMMENT" , 143); +/** currently parsing a comment in a variable array value */ +define("STATE_VAR_ARRAY_COMMENT" , 243); + +if (!defined('T_INTERFACE')) +{ + define('T_INTERFACE', 'foo'); + if (!defined('T_CONST')) { + define('T_CONST', 'foo'); + } + define('T_ABSTRACT', 'foo'); + define('T_PRIVATE', 'foo'); + define('T_PUBLIC', 'foo'); + define('T_PROTECTED', 'foo'); + define('T_FINAL', 'foo'); + define('T_IMPLEMENTS', 'foo'); +} +if (!defined('T_DOC_COMMENT')) +{ + define('T_DOC_COMMENT', T_ML_COMMENT); +} +/** + * PHP Parser for PHP 4.2.3- + * + * This parser is slower than the tokenizer-based parser, and is deprecated. + * @author Joshua Eichorn + * @author Gregory Beaver + * @version $Id: Parser.inc,v 1.1 2005/10/17 18:36:56 jeichorn Exp $ + * @package phpDocumentor + * @subpackage Parsers + * @deprecated in favor of {@link phpDocumentorTParser} + */ +class Parser extends Publisher +{ + /**#@+ + * @access private + */ + /** + * Word parser + * @see WordParser + */ + var $wp; + + /** + * temporary parser variables + */ + var $p_vars = array('func' => false, 'function_data' => '', 'quote_data' => '', 'event_stack' => false, 'last_pevent' => 0, + 'two_words_ago' => '', 'temp_word' => '', 'docblock' => false, 'line' => array(), 'linecount' => 0, 'startword' => '', + 'periodline' => 0, 'shortdesc' => '', 'docblock_desc' => '', 'class' => false, 'source_location' => '', + 'define_params_data' => '', 'define' => false, 'define_name' => '', 'define_value' => '', 'var' => false, + 'oldtoken' => false, 'comment_data' => '', 'function_param' => NULL, 'inline_dockeyword_type' => false, + 'inline_dockeyword_data' => false, 'dockeyword_type' => false, 'dockeyword_data' =>false, 'param_var' => false, + 'include_name' => '', 'include_value' => '','include' => false, 'return_type' => '', 'cur_class' => '', + 'function_data' => false, 'varname' => '', 'returntype' => false, 'vartype' => false, 'paramtype' => false, + 'tagname' => '', 'find_global' => '', 'global_type' => '', 'paramname' => false, 'statics' => array(), + 'static_count' => 0, 'static_val' => array(), 'docblock_type' => 'docblock', 'seelement' => false); + + /** + * parser flags, for states that don't warrant a new event (like new line in a docblock) + */ + var $p_flags = array('docblocknewline' => false, 'docblockintags' => false, 'useperiod' => false, + 'definename_isset' => false, 'define_parens' => false, 'reset_quote_data' => false, + 'in_desc' => true, 'in_tag' => false, 'newline' => true, 'tempnewline' => false, + 'start_docblock' => false, 'includename_isset' => false, 'return_isset' => false, + 'is_return' => false, 'in_class' => false, 'asterisk' => false, 'var_equals' => false, + 'arrayinvarname' => false, 'valid_newline' => true, 'startline' => false, + 'function_global' => false, 'define_global' => false, 'static_value' => false,'funcparam_val' => false, + 'get_source' => false, 'getting_source' => false); + + /** + * lookup table for event handler methods + * @see Parser::parse() + */ + var $eventHandlers = array( + 'handleArray' => PARSER_EVENT_ARRAY, + 'handleClass' => PARSER_EVENT_CLASS, + 'handleComment' => PARSER_EVENT_COMMENT, + 'handleDocBlockTemplate' => PARSER_EVENT_DOCBLOCK_TEMPLATE, + 'handleEndDocBlockTemplate' => PARSER_EVENT_END_DOCBLOCK_TEMPLATE, + 'handleEscape' => PARSER_EVENT_ESCAPE, + 'handleLogicBlock' => PARSER_EVENT_LOGICBLOCK, + 'defaultHandler' => PARSER_EVENT_NOEVENTS, +// 'defaultHandler' => PARSER_EVENT_COMMENTBLOCK, (set in constructor below) +// 'defaultHandler' => PARSER_EVENT_OUTPHP, + 'handleDefine' => PARSER_EVENT_DEFINE, + 'handleDefineParams' => PARSER_EVENT_DEFINE_PARAMS, + 'handleDefineParamsParenthesis' => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS, + 'handleIncludeParamsParenthesis' => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS, +// 'handleDocBlock' => PARSER_EVENT_DOCBLOCK, + 'BetterhandleDocBlock' => PARSER_EVENT_DOCBLOCK, + 'handleTags' => PARSER_EVENT_TAGS, + 'handleDesc' => PARSER_EVENT_DESC, +// 'handleDockeyword' => PARSER_EVENT_DOCKEYWORD, + 'handleTag' => PARSER_EVENT_DOCKEYWORD, + 'handleDockeywordEmail' => PARSER_EVENT_DOCKEYWORD_EMAIL, + 'handleEOFQuote' => PARSER_EVENT_EOFQUOTE, + 'handleFunction' => PARSER_EVENT_FUNCTION, + 'handleFunctionParams' => PARSER_EVENT_FUNCTION_PARAMS, + 'handleFuncGlobal' => PARSER_EVENT_FUNC_GLOBAL, + 'handleGlobal' => PARSER_EVENT_DEFINE_GLOBAL, + 'handleGlobalValue' => PARSER_EVENT_GLOBAL_VALUE, + 'handleInlineDockeyword' => PARSER_EVENT_INLINE_DOCKEYWORD, + 'handleInclude' => PARSER_EVENT_INCLUDE, + 'handleIncludeParams' => PARSER_EVENT_INCLUDE_PARAMS, + 'handleQuote' => PARSER_EVENT_QUOTE, + 'handlePhpCode' => PARSER_EVENT_PHPCODE, + 'handleSingleQuote' => PARSER_EVENT_SINGLEQUOTE, + 'handleStaticVar' => PARSER_EVENT_STATIC_VAR, + 'handleStaticValue' => PARSER_EVENT_STATIC_VAR_VALUE, + 'handleVar' => PARSER_EVENT_VAR, + ); + + /** + * event handlers for @tags + * @tutorial tags.pkg + */ + var $tagHandlers = array( + '*' => 'defaultTagHandler', + 'category' => 'categoryTagHandler', + 'example' => 'exampleTagHandler', + 'filesource' => 'invalidTagHandler', + 'return' => 'returnTagHandler', + 'returns' => 'returnTagHandler', + 'var' => 'varTagHandler', + 'package' => 'packageTagHandler', + 'param' => 'paramTagHandler', + 'parameter' => 'paramTagHandler', + 'global' => 'globalTagHandler', + 'staticvar' => 'staticvarTagHandler', + 'uses' => 'usesTagHandler' + ); + + var $laststart = false; + + /** + * An array of allowable @tags + */ + var $allowableTags; + + + /** + * An array of allowed inline @tags + */ + var $allowableInlineTags; + + /** + * Sets the states up, and creates a new WordParser + */ + + /** + * an array of parsing tokens organized by event number. + * A token is defined as the smallest group of characters that separates or + * defines a new parser element. In English, a space or punctuation are + * tokens that separate words. in PHP, tokens may be //, or even " + * Format: array(eventnum =>array(token1, token2, token3, ...),...) + * @var array + */ + var $tokens; + + /** + * array of events that are raised, organized by the tokens that raise them. + * Format: array(eventnum => array(token => neweventnum, token2 => neweventnum2,...),...) + * @var array + */ + var $pushEvent; + + /** + * array of tokens that end an event, organized by event + * Format: array(eventnum => array(token => neweventnum, token2 => neweventnum2,...),...) + * @var array + */ + var $popEvent; + /**#@-*/ + + /** + * Set up invariant parsing variables + */ + function Parser() + { + $this->allowableTags = $GLOBALS['_phpDocumentor_tags_allowed']; + $this->allowableInlineTags = $GLOBALS['_phpDocumentor_inline_doc_tags_allowed']; + $this->wp = new WordParser; + // strange PHP 4.0.6 behavior: it converts constants to strings without warning if it's an array index + $this->eventHandlers = array_flip($this->eventHandlers); + $this->eventHandlers[PARSER_EVENT_COMMENTBLOCK] = 'defaultHandler'; + $this->eventHandlers[PARSER_EVENT_OUTPHP] = 'defaultHandler'; + $this->subscribe(PHPDOCUMENTOR_EVENT_NEWLINENUM,$GLOBALS['phpDocumentor_errors']); + $this->subscribe(PHPDOCUMENTOR_EVENT_NEWFILE,$GLOBALS['phpDocumentor_errors']); + } + + /** + * Parse a new file + * + * @param string $parse_data + * @param string $path + * @param int $base number of directories to drop off the bottom when creating names using path + * @staticvar integer used for recursion limiting if a handler for an event is not found + * @return bool + */ + function parse (&$parse_data, $path, $base = 0, $packages = false) + { + global $_phpDocumentor_options; + static $endrecur = 0; + $this->p_vars = array('func' => false, 'function_data' => '', 'quote_data' => '', 'event_stack' => false, 'last_pevent' => 0, + 'two_words_ago' => '', 'temp_word' => '', 'docblock' => false, 'line' => array(), 'linecount' => 0, 'startword' => '', + 'periodline' => 0, 'shortdesc' => '', 'docblock_desc' => '', 'class' => false, 'source_location' => '', + 'define_params_data' => '', 'define' => false, 'define_name' => '', 'define_value' => '', 'var' => false, + 'oldtoken' => false, 'comment_data' => '', 'function_param' => NULL, 'inline_dockeyword_type' => false, + 'inline_dockeyword_data' => false, 'dockeyword_type' => false, 'dockeyword_data' =>false, 'param_var' => false, + 'include_name' => '', 'include_value' => '','include' => false, 'return_type' => '', 'cur_class' => '', + 'function_data' => false, 'varname' => '', 'returntype' => false, 'vartype' => false, 'paramtype' => false, + 'tagname' => '', 'find_global' => '', 'global_type' => '', 'paramname' => false, 'statics' => array(), + 'static_count' => 0, 'static_val' => array(), 'docblock_type' => 'docblock', 'linenum' => false, + 'seelement' => false); + + $this->p_flags = array('docblocknewline' => false, 'docblockintags' => false, 'useperiod' => false, + 'definename_isset' => false, 'define_parens' => false, 'reset_quote_data' => false, + 'in_desc' => true, 'in_tag' => false, 'newline' => true, 'tempnewline' => false, + 'start_docblock' => false, 'includename_isset' => false, 'return_isset' => false, + 'is_return' => false, 'in_class' => false, 'asterisk' => false, 'var_equals' => false, + 'arrayinvarname' => false, 'valid_newline' => true, 'startline' => false, + 'function_global' => false, 'define_global' => false, 'static_value' => false,'funcparam_val' => false, + 'get_source' => false, 'getting_source' => false, 'in_define' => false, 'in_include' => false, + 'in_var' => false, 'in_global' => false); + $this->p_vars['parsepath'] = $path; + $this->setupStates(); + if (strlen($parse_data) == 0) + { + return false; + } + + // initialize variables so E_ALL error_reporting doesn't complain + $pevent = 0; + $word = 0; + $this->p_vars['event_stack'] = new EventStack; + + $this->wp->setup($parse_data); + + + $page = new ParserPage; + $page->setPath($path); + $page->setPackageOutput($packages); + $page->setFile(basename($path)); + $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWFILE,basename($path)); + //$name = str_replace("/","_",dirname($path)) . "_" . array_shift(explode(".",$page->getFile())); + // fc@fc.clever-soft.com 11/29/2001 + $name = str_replace(PATH_DELIMITER,"_",dirname($path)) . "_" . str_replace(".","_",$page->getFile()); + $tmp = explode("_",$name); + $name = str_replace(':','_',implode("_",array_slice($tmp,$base))); + // if base is '', drive letter is present in windows + + $page->setName($name); + $temploc = $_phpDocumentor_options['Program_Root'] . PATH_DELIMITER. implode(PATH_DELIMITER, + array_slice(explode(PATH_DELIMITER,$path),$base)); + + if ($temploc == $_phpDocumentor_options['Program_Root'] . PATH_DELIMITER) $temploc .= $path; + + $this->p_vars['source_location'] = $source_location = $temploc; + $page->setSourceLocation($source_location); + + $this->publishEvent(PHPDOCUMENTOR_EVENT_PAGE,$page); + unset($page); + $this->p_flags['reset_quote_data'] = true; + + do + { + $lpevent = $pevent; + $pevent = $this->p_vars['event_stack']->getEvent(); + if ($lpevent != $pevent) + { + $this->p_vars['last_pevent'] = $lpevent; + } + + if ($this->p_vars['last_pevent'] != $pevent) + { + // its a new event so the word parser needs to be reconfigured + $this->configWordParser($pevent); + } + + $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,($pevent + 100)); + + if ($pevent == PARSER_EVENT_GLOBAL_VALUE || $pevent == PARSER_EVENT_DOCBLOCK || $pevent == PARSER_EVENT_DOCBLOCK_TEMPLATE) + { + $this->wp->setWhitespace(true); + } + + $this->p_vars['last_word'] = $word; + $word = $this->wp->getWord(); + // in wordparser, have to keep track of lines + $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWLINENUM, $this->wp->linenum); + + if (0)//PHPDOCUMENTOR_DEBUG == true) + { + echo "\nLAST: |" . $this->p_vars['last_word'] . "|\n"; + echo "PEVENT: " . $this->getParserEventName($pevent) . "\n"; + echo "LASTPEVENT: " . $this->getParserEventName($this->p_vars['last_pevent']) . "\n"; + echo $this->wp->getPos() . ": |$word|\n--------------------------\n\n"; + } + if ($this->p_flags['get_source']) + { + if ($pevent == PARSER_EVENT_FUNCTION) + { + $this->wp->retrievesource("function $word"); + $this->p_flags['get_source'] = false; + $this->p_flags['getting_source'] = true; + } + } + if (false)//$this->p_flags['getting_source'] && ($pevent == PARSER_EVENT_DOCBLOCK) || ($pevent == PARSER_EVENT_NOEVENTS)) + { + addError(PDERROR_SOURCE_TAG_FUNCTION_NOT_FOUND); + // throw away source + $this->wp->getSource(); + } + if (isset($this->eventHandlers[$pevent])) + { + $handle = $this->eventHandlers[$pevent]; + $this->$handle($word, $pevent); + } else + { + debug('WARNING: possible error, no handler for event number '.$pevent); + if ($endrecur++ == 25) + { + die("FATAL ERROR, recursion limit reached"); + } + } + } while (!($word === false)); + $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,PHPDOCUMENTOR_EVENT_END_PAGE); + } + + /**#@+ + * @access private + * @param string token parsed from source + * @param integer parser constant from {@link Parser.inc} + */ + /** + * handler for NOEVENTS, OUTPHP, COMMENTBLOCK + */ + + function defaultHandler($word, $pevent) + { + $this->checkEventPush( $word, $pevent); + $this->checkEventPop($word,$pevent); + } + + /** + * handler for LOGICBLOCK + * + * Logic Blocks are the stuff between { and } in a function/method. A + * logic block can clearly contain other logic blocks, as in: + * + * + * function test($a) + * { + * if (testcondition) + * { // nested logic block + * } + * } + * + * + * So, the exit portion of the logic block handler must check to see if the + * logic block being exited is the top-level, and it does this by retrieving + * the last event from the stack. If it is a function (and not a logic block) + * then it backs up the word parser so that the function will exit properly. + * + * {@source 11} + */ + + function handleLogicBlock($word, $pevent) + { + $a = $this->checkEventPush( $word, $pevent); + if ($a == PARSER_EVENT_FUNC_GLOBAL || $a == PARSER_EVENT_STATIC_VAR) + { + 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) != "{") + { + $this->p_vars['event_stack']->popEvent(); + } + } + if ($this->checkEventPop($word,$pevent)) + { + $e = $this->p_vars['event_stack']->popEvent(); + $this->p_vars['event_stack']->pushEvent($e); + if ($e == PARSER_EVENT_FUNCTION) + { + $this->wp->backupPos($word); + } + } + } + + /** + * handler for ESCAPE. + * this event handler parses "this string \"with its escape backslashes\"" and returns: + * this string "with its escape backslashes" + * to make it human-readable + */ + + function handleEscape($word, $pevent) + { + $this->p_vars['event_stack']->popEvent(); + } + + /** + * handler for COMMENT. + * this event handler parses single-line comments like: + * // this one + */ + + function handleComment($word, $pevent) + { + $this->checkEventPush( $word, $pevent); + + if (!isset($this->p_vars['comment_data'])) $this->p_vars['comment_data'] = ''; + $this->p_vars['comment_data'] .= $word; + + $this->checkEventPop($word,$pevent); + } + + /** + * handler for ARRAY. + * this event handler parses arrays in default values of function and var definitions + */ + + function handleArray($word, $pevent) + { + $e = $this->checkEventPush( $word, $pevent); + if (($e == PARSER_EVENT_COMMENTBLOCK) || + ($e == PARSER_EVENT_COMMENT)) return; + + if (!isset($this->p_vars['function_data']) || (isset($this->p_vars['function_data']) && empty($this->p_vars['function_data']))) + { + $this->p_vars['function_data'] = "array"; + } + + if ( ($this->p_vars['last_word'] == "'")) + { + $this->p_vars['function_data'] .= $this->p_vars['quote_data']."'"; + } + if ( ($this->p_vars['last_word'] == "\"")) + { + $this->p_vars['function_data'] .= $this->p_vars['quote_data']."\""; + } + + $this->p_vars['function_data'] .= $word; + //echo "function_data = |$this->p_vars['function_data']|\n"; + + if ($this->checkEventPop($word,$pevent)) + { + } + } + + /** + * handler for DEFINE. + * handles define(constant, value); statements + */ + + function handleDefine($word, $pevent) + { + if (!$this->p_flags['in_define']) + { + $this->p_vars['linenum'] = $this->wp->linenum; + } + $this->p_flags['in_define'] = true; + $this->checkEventPush( $word, $pevent); + + $this->p_flags['definename_isset'] = false; + $this->p_vars['define_params_data'] = ''; + unset($this->p_vars['quote_data']); + if ($this->checkEventPop($word,$pevent)) + { + $this->p_flags['in_define'] = false; + $this->p_vars['define'] = new parserDefine; + $this->p_vars['define']->setLineNumber($this->p_vars['linenum']); + $this->p_vars['define']->setName($this->p_vars['define_name']); + $this->p_vars['define']->setValue($this->p_vars['define_value']); + $this->publishEvent(PHPDOCUMENTOR_EVENT_DEFINE,$this->p_vars['define']); + $this->p_flags['definename_isset'] = false; + unset($this->p_vars['define']); + unset($this->p_vars['define_name']); + unset($this->p_vars['define_value']); + $this->p_flags['in_define'] = false; + $this->p_vars['define_params_data'] = ''; + } + } + + /** + * handler for DEFINE_PARAMS. + * handles the parsing of constant and value in define(constant, value); + */ + + function handleDefineParams($word, $pevent) + { + if ($this->checkEventPush( $word, $pevent)) + { + if ($word == '(') + { + $this->p_vars['define_params_data'] .= $word; + } + return; + } + + $this->p_flags['define_parens'] = true; + if(!isset($this->p_vars['define_params_data'])) $this->p_vars['define_params_data'] = ''; + + if ($this->checkEventPop($word,$pevent)) + { + if (!empty($this->p_vars['quote_data'])) + { + $this->p_vars['define_params_data'] .= $this->p_vars['quote_data']; + } + if (!empty($this->p_vars['define_params_data'])) + { + //echo $this->p_vars['define_params_data']."\n"; + $this->p_vars['define_value'] = $this->p_vars['define_params_data']; + } + else + { + if ( $this->p_vars['last_word'] != "/*" && + $this->p_vars['last_word'] != "//" && $this->p_vars['last_word'] != "#") + { + $this->p_vars['define_value'] = trim($this->p_vars['last_word']); + } + else + { + $this->p_vars['define_value'] = ""; + } + } + } + if ($this->p_flags['definename_isset']) + { + if (isset($this->p_vars['quote_data'])) + { + $this->p_vars['define_params_data'] .= '"'.$this->p_vars['quote_data'].'"'; + unset($this->p_vars['quote_data']); + } + $this->p_vars['define_params_data'] .= $word; + } else + { + if ($word != ",") + { + if (isset($this->p_vars['quote_data'])) + { + $this->p_vars['define_params_data'] .= $this->p_vars['quote_data']; + unset($this->p_vars['quote_data']); + } + $this->p_vars['define_params_data'] .= $word; + } else + { + if (isset($this->p_vars['quote_data']) && !$this->p_flags['definename_isset']) + { + $this->p_vars['define_params_data'] .= $this->p_vars['quote_data']; + unset($this->p_vars['quote_data']); + } + $this->p_flags['definename_isset'] = true; + $this->p_vars['define_name'] = $this->p_vars['define_params_data']; + unset($this->p_vars['quote_data']); + $this->p_vars['define_params_data'] = ''; + } + } + } + + /** + * handler for DEFINE_PARAMS_PARENTHESIS. + * this handler takes all parenthetical statements within constant or value in: + * define(constant, value) of a define statement, and handles them properly + */ + + function handleDefineParamsParenthesis($word, $pevent) + { + if (isset($this->p_vars['quote_data'])) + { + $this->p_vars['define_params_data'] .= '"'.$this->p_vars['quote_data'].'"'; + unset($this->p_vars['quote_data']); + } + $this->p_vars['define_params_data'] .= $word; + $this->checkEventPush( $word, $pevent); + $this->checkEventPop( $word, $pevent); + } + + /** + * handler for CLASS. + * this handler parses a class statement + */ + + function handleClass($word, $pevent) + { + $this->p_flags['in_class'] = true; + $a = $this->checkEventPush( $word, $pevent); + if ($a == PARSER_EVENT_DOCBLOCK || $a == PARSER_EVENT_DOCBLOCK_TEMPLATE) + { + $this->wp->setWhitespace(true); + } + + if (!isset($this->p_vars['class'])) $this->p_vars['class'] = false; + if (!is_subclass_of($this->p_vars['class'],"parserBase")) + { + $this->p_vars['class'] = new parserClass; + $this->p_vars['class']->setLineNumber($this->wp->linenum); + $this->p_vars['class']->setname($word); + $this->p_vars['cur_class'] = $word; + $this->p_vars['class']->setSourceLocation($this->p_vars['source_location']); + } + + if (strtolower($this->p_vars['last_word']) == "extends") + { + $this->p_vars['class']->setExtends($word); + } + + if ($word == "{") + { + $this->publishEvent(PHPDOCUMENTOR_EVENT_CLASS,$this->p_vars['class']); + } + //echo $this->wp->getPos() . ": |$word|\n"; + if ($this->checkEventPop($word,$pevent)) + { + $this->p_flags['in_class'] = false; + // throw an event when class is done + $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,STATE_END_CLASS); + $this->p_vars['class'] = false; + } + } + + /** + * handler for VAR. + * handle a var $varname = default_value; or var $varname; statement in a class definition + */ + + function handleVar($word, $pevent) + { + if (!$this->p_flags['in_var']) + { + $this->p_vars['linenum'] = $this->wp->linenum; + } + $this->p_flags['in_var'] = true; + //echo $word."\n"; + $e = $this->checkEventPush( $word, $pevent); + + if (!isset($this->p_vars['var'])) $this->p_vars['var'] = false; + if ($word == '=' || $word == ';') $this->p_flags['var_equals'] = true; + if (!$this->p_flags['var_equals']) + { + // if we haven't parsed the = yet, no arrays are possible! + if ($e == PARSER_EVENT_ARRAY) + { + $this->p_flags['arrayinvarname'] = true; + $this->p_vars['event_stack']->popEvent(); + } + if (!$e || ($e == PARSER_EVENT_ARRAY)) + $this->p_vars['varname'] .= $word; + } + + if (!$this->p_flags['var_equals']) + { + if ($word != "/*" && $word != "//" && $word != "#") + { + $this->p_vars['var'] = new parserVar($this->p_vars['cur_class']); + $this->p_vars['var']->setName($this->p_vars['varname']); + } + } + if ($this->p_vars['last_word'] == "=") + { + if ($word != "/*" && $word != "//" && $word != "#") + { + $this->p_vars['var']->setValue($word); + } + } + // fix 1202772 + if (isset($this->p_vars['quote_data']) && ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE || $this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE)) + { + $this->p_vars['var']->setValue($this->p_vars['quote_data']); + unset($this->p_vars['quote_data']); + } + if ($this->p_vars['last_pevent'] == PARSER_EVENT_ARRAY) + { + $this->p_vars['var']->setValue($this->p_vars['function_data']); + $this->p_vars['function_data'] = false; + } + + if ($this->checkEventPop($word,$pevent)) + { + $this->p_vars['var']->setLineNumber($this->p_vars['linenum']); + $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR,$this->p_vars['var']); + unset($this->p_vars['var']); + $this->p_flags['in_var'] = false; + $this->p_flags['var_equals'] = false; + $this->p_flags['arrayinvarname'] = false; + $this->p_vars['varname'] = ''; + } + } + + /** + * handler for QUOTE. + * this handler recognizes strings defined with double quotation marks (") and handles them correctly + * in any place that they legally appear in php code + */ + + function handleQuote($word, $pevent) + { + if ($this->p_flags['reset_quote_data'] === true) + { + $this->p_flags['reset_quote_data'] = false; + $this->p_vars['quote_data'] = ""; + } + $this->checkEventPush( $word, $pevent); + if ($word != "\"") + { + $this->p_vars['quote_data'] .= $word; + } + if ($this->checkEventPop($word,$pevent)) + { + $this->p_flags['reset_quote_data'] = true; + } + } + + /** + * handler for SINGLEQUOTE. + * this handler recognizes strings defined with single quotation marks (') and handles them correctly + * in any place that they legally appear in php code + */ + + function handleSingleQuote($word, $pevent) + { + $this->checkEventPush( $word, $pevent); + if ($this->checkEventPop($word,$pevent)) + { + if ($this->p_vars['last_word'] != "'") + { + $this->p_vars['quote_data'] = $this->p_vars['last_word']; + } else { + $this->p_vars['quote_data'] = ""; + } + } + } + + /** + * handler for EOFQUOTE. + * this handler recognizes strings defined with perl-style <<< EOF quotes, and handles them correctly + * in any place that they legally appear in php code + * + * an example: + * $var <<< EOF + * blah blah blah + * EOF; + */ + + function handleEOFQuote($word, $pevent) + { + // echo $this->wp->getPos() . ": word=|$word|\t\t\tlastword=|$this->p_vars['last_word']|\n"; + if (trim($this->p_vars['last_word']) == "<<<") + { + // ok we found the keyword + //echo "Keyword == $word\n"; + $this->p_vars['oldtoken'] = $this->tokens[STATE_EOFQUOTE]; + $this->tokens[STATE_EOFQUOTE] = array($word); + } + else if ($this->p_vars['last_pevent'] || PARSER_EVENT_EOFQUOTE) + { + // i don't think anything will ever use this so were not going to set it + //$this->p_vars['quote_data'] = $this->p_vars['last_word']; + $this->p_vars['event_stack']->popEvent(); + $this->tokens[STATE_EOFQUOTE] = $this->p_vars['oldtoken']; + } + } + /**#@-*/ + + /** + * Tells the parser to search for a global variable definition as + * defined by a @global type $name tag. + * + * The parser is fooled into looking for the entire global variable as a + * single token by amending the {@link $tokens} array. + * + * {@source} + * @access private + * @param string name of global variable as it appears in the source code + */ + function findGlobal($name) + { + if (!isset($this->p_vars['globaltofind'])) + { + $this->p_vars['globaltofind'] = $name; + $this->pushEvent[PARSER_EVENT_PHPCODE][strtolower($name)] = PARSER_EVENT_DEFINE_GLOBAL; + $this->tokens[STATE_PHPCODE][] = $name; + } else + { + addError(PDERROR_MULTIPLE_GLOBAL_TAGS,$this->p_vars['globaltofind'],$name); + } + } + + /**#@+ + * @access private + * @param string token parsed from source + * @param integer parser constant from {@link Parser.inc} + */ + /** + * handler for PHPCODE. + * this handler recognizes the php processor directive, and begins parsing php code + */ + + function handlePhpCode($word, $pevent) + { + $e = $this->checkEventPush( $word, $pevent); + if ($e == PARSER_EVENT_DOCBLOCK || $e == PARSER_EVENT_DOCBLOCK_TEMPLATE) + { + $this->wp->setWhitespace(true); + } + if (isset($this->p_vars['globaltofind']) && $e) + { + 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) + { + addError(PDERROR_GLOBAL_NOT_FOUND,$this->p_vars['globaltofind']); + unset($this->pushEvent[PARSER_EVENT_PHPCODE][strtolower($this->p_vars['globaltofind'])]); + foreach($this->tokens[STATE_PHPCODE] as $i => $notme) + if ($this->tokens[STATE_PHPCODE][$i] == $this->p_vars['globaltofind']) + unset($this->tokens[STATE_PHPCODE][$i]); + unset($this->p_vars['globaltofind']); + } + } + } + + /** + * handler for global variables + */ + function handleGlobal($word, $pevent) + { + if (!$this->p_flags['in_global']) + { + $this->p_vars['linenum'] = $this->wp->linenum; + } + $this->p_flags['in_global'] = true; + $e = $this->checkEventPush($word, $pevent); + if ($this->checkEventPop($word, $pevent)) + { + $this->p_flags['in_global'] = false; + $a = new parserGlobal; + $a->setDataType($this->p_vars['global_type']); + $this->p_vars['global_type'] = ''; + $a->setLineNumber($this->p_vars['linenum']); + $a->setName($this->p_vars['globaltofind']); + if (isset($this->p_vars['global_val'])) + $a->setValue(trim($this->p_vars['global_val'])); + unset($this->p_vars['global_val']); + $this->publishEvent(PHPDOCUMENTOR_EVENT_GLOBAL,$a); + unset($this->pushEvent[PARSER_EVENT_PHPCODE][strtolower($this->p_vars['globaltofind'])]); + foreach($this->tokens[STATE_PHPCODE] as $i => $notme) + if ($this->tokens[STATE_PHPCODE][$i] == $this->p_vars['globaltofind']) + unset($this->tokens[STATE_PHPCODE][$i]); + unset($this->p_vars['globaltofind']); + } + } + + /** + * Handles the stuff after the = in $globalvar = value + */ + function handleGlobalValue($word, $pevent) + { + if ($this->checkEventPush($word, $pevent)) + { + $this->wp->setWhitespace(false); + return; + } + if (!isset($this->p_vars['global_val'])) $this->p_vars['global_val'] = ''; + if ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE || $this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE) + { + if (!isset($this->p_vars['quote_data'])) $this->p_vars['quote_data'] = ''; + $this->p_vars['global_val'] .= '"'.$this->p_vars['quote_data'].'"'; + unset($this->p_vars['quote_data']); + $this->p_vars['last_pevent'] = PARSER_EVENT_GLOBAL_VALUE; + } + if ($this->p_vars['last_pevent'] == PARSER_EVENT_ARRAY) + { + $this->p_vars['global_val'] .= $this->p_vars['function_data']; + $this->p_vars['function_data'] = false; + } + if ($word != ';') + $this->p_vars['global_val'] .= $word; + if ($this->checkEventPop($word, $pevent)) + { + $this->wp->setWhitespace(false); + $this->wp->backupPos($word); + } + } + + /** + * handler for FUNC_GLOBAL. + * this handler recognizes "global $var1, $var2" declarations in a function, and parses them + */ + + function handleFuncGlobal($word, $pevent) + { + if ((substr(trim($word),0,1) != '$') && ($word != ',') && ($word != ';')) + { // not a global declaration, using a variable named "$global" + $this->p_vars['event_stack']->popEvent(); + return; + } + if ($this->checkEventPop($word, $pevent)) + { + return; + } + if (!$this->checkEventPush($word, $pevent)) + { + if ($word == ',') + { // another variable + $this->p_vars['global_count']++; + } else + { + if (!isset($this->p_vars['globals'][$this->p_vars['global_count']])) + $this->p_vars['globals'][$this->p_vars['global_count']] = ''; + if (!empty($this->p_vars['globals'][$this->p_vars['global_count']])) $this->p_vars['global_count']++; + $this->p_vars['globals'][$this->p_vars['global_count']] = trim($word); + } + } + } + + /** + * handler for STATIC_VAR. + * this handler recognizes "static $var1, $var2 = 6" declarations in a function, and parses them + */ + + function handleStaticVar($word, $pevent) + { + if ($this->checkEventPop($word, $pevent)) + { + $this->p_vars['static_count']++; + return; + } + if (!$this->checkEventPush($word, $pevent)) + { + if ($word == ',') + { + $this->p_vars['static_count']++; + return; + } + if (!isset($this->p_vars['statics'][$this->p_vars['static_count']])) + $this->p_vars['statics'][$this->p_vars['static_count']] = ''; + if (!empty($this->p_vars['statics'][$this->p_vars['static_count']])) $this->p_vars['static_count']++; + $this->p_vars['statics'][$this->p_vars['static_count']] = trim($word); + } + } + + /** + * handler for STATIC_VAR_VALUE. + * this handler parses the 6 in "static $var1, $var2 = 6" + */ + + function handleStaticValue($word, $pevent) + { + if ($this->checkEventPush($word, $pevent)) + { + return; + } + if (!isset($this->p_vars['static_val'][$this->p_vars['static_count']])) $this->p_vars['static_val'][$this->p_vars['static_count']] = ''; + if ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE || $this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE) + { + $this->p_vars['static_val'][$this->p_vars['static_count']] .= '"'.$this->p_vars['quote_data'].'"'; + unset($this->p_vars['quote_data']); + } + if ($this->p_vars['last_pevent'] == PARSER_EVENT_ARRAY) + { + $this->p_vars['static_val'][$this->p_vars['static_count']] .= $this->p_vars['function_data']; + $this->p_vars['function_data'] = false; + } + if ($this->checkEventPop($word, $pevent)) + { + $this->p_vars['static_val'][$this->p_vars['static_count']] = trim($this->p_vars['static_val'][$this->p_vars['static_count']]); + $this->wp->backupPos($word); + return; + } else $this->p_vars['static_val'][$this->p_vars['static_count']] .= $word; + } + + /** + * handler for FUNCTION. + * this handler recognizes function declarations, and parses them. The body + * of the function is parsed by handleLogicBlock() + * @see handleLogicBlock() + */ + + function handleFunction($word, $pevent) + { + if ($e = $this->checkEventPush( $word, $pevent)) + { + if ($e == PARSER_EVENT_COMMENT || $e == PARSER_EVENT_COMMENTBLOCK) return; + } + + if (!isset($this->p_vars['func'])) $this->p_vars['func'] = false; + if (! is_subclass_of($this->p_vars['func'],"parserBase")) + { + $this->p_vars['globals'] = array(); + $this->p_vars['global_count'] = 0; + if ($this->p_flags['in_class']) + $this->p_vars['func'] = new parserMethod($this->p_vars['cur_class']); + else + $this->p_vars['func'] = new parserFunction; + $this->p_vars['func']->setLineNumber($this->wp->linenum); + if (trim($word) != '&') + $this->p_vars['func']->setName(trim($word)); + else + $this->p_vars['func']->setReturnsReference(); + } else + { + if ($this->p_vars['func']->getReturnsReference()) + { + if ($this->p_vars['last_word'] == '&') + { + $this->p_vars['func']->setName(trim($word)); + } + } + } + if ($this->checkEventPop($word,$pevent)) + { + $this->p_vars['func']->addGlobals($this->p_vars['globals']); + $this->p_vars['func']->addStatics($this->p_vars['statics'],$this->p_vars['static_val']); + $this->p_vars['globals'] = array(); + $this->p_vars['global_count'] = 0; + if ($this->p_flags['getting_source']) + { + $x = $this->wp->getSource(); + $this->p_vars['func']->addSource($x); + $this->p_flags['get_source'] = false; + $this->p_flags['getting_source'] = false; + } + $this->publishEvent(PHPDOCUMENTOR_EVENT_FUNCTION,$this->p_vars['func']); + $this->p_vars['func'] = false; + } + } + + /**#@-*/ + /** + * Helper function for {@link handleFunctionParams()} + * + * This function adds a new parameter to the parameter list + * @access private + * @param string + */ + function endFunctionParam($word) + { + if (isset($this->p_vars['quote_data']) && ($this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE)) + { + $this->p_vars['function_data'] .= "'".$this->p_vars['quote_data']."'"; + unset($this->p_vars['quote_data']); + } + if (isset($this->p_vars['quote_data']) && ($this->p_vars['quote_data'] != '') && ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE)) + { + $this->p_vars['function_data'] .= '"'.$this->p_vars['quote_data'].'"'; + unset($this->p_vars['quote_data']); + } + if (isset($this->p_vars['function_param'])) + { + $this->p_vars['func']->addParam($this->p_vars['function_param'],$this->p_vars['function_data'], $this->p_flags['funcparam_val']); + unset($this->p_vars['function_param']); + $this->p_vars['function_data'] = ''; + $this->p_flags['funcparam_val'] = false; + } + } + /**#@+ + * @access private + * @param string token parsed from source + * @param integer parser constant from {@link Parser.inc} + */ + /** + * handler for FUNCTION_PARAMS. + * this handler recognizes the parameters of a function within parentheses like function(param, param = default_value) + * and parses them + * @see endFunctionParam() + */ + + function handleFunctionParams($word, $pevent) + { + //echo $this->wp->getPos() . ": word=|$word|\t\t\tlastword=|".$this->p_vars['last_word']."|\n"; + //echo "function_param = '".$this->p_vars['function_param']."'\n"; + //echo "function_data = '".$this->p_vars['function_data']."'\n"; + $e1 = $this->checkEventPush( $word, $pevent); + + if (!$e1) + { + if ($word == ',' || $this->checkEventPop($word,$pevent)) + { + $this->endFunctionParam($word); + } elseif ($word == '=') + { + $this->p_flags['funcparam_val'] = true; + } else + { + if ($this->p_flags['funcparam_val']) + { + if (isset($this->p_vars['quote_data']) && ($this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE)) + { + $this->p_vars['function_data'] .= "'".$this->p_vars['quote_data']."'"; + unset($this->p_vars['quote_data']); + } + if (isset($this->p_vars['quote_data']) && ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE)) + { + $this->p_vars['function_data'] .= '"'.$this->p_vars['quote_data'].'"'; + unset($this->p_vars['quote_data']); + } + $this->p_vars['function_data'] .= $word; + } else + { + $this->p_vars['function_param'] = $word; + } + } + } + } + + + /** + * javadoc-desc-compliant handler for DOCBLOCK. + * this handler recognizes @tags in DocBlocks and parses them for display. + * It also parses out unknown tags into their own array for use by the docblock + */ + + function JavaDochandleDocblock($word, $pevent) + { + $e1 = $this->checkEventPush( $word, $pevent); + if (!isset($this->p_vars[$this->p_vars['docblock_type']]) || !$this->p_vars[$this->p_vars['docblock_type']]) + { + $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock(); + $this->p_vars['returntype'] = false; + $this->p_vars['vartype'] = false; + $this->p_flags['startdocblock'] = true; + $this->p_flags['valid_newline'] = true; + $this->p_flags['startline'] = true; + $this->p_flags['newline'] = true; + $this->p_flags['in_desc'] = true; + $this->p_flags['in_tag'] = false; + $this->p_flags['useperiod'] = false; + $this->p_vars['line'] = array(); + $this->p_vars['linecount'] = 0; + } + $e = $this->checkEventPop( $word, $pevent); + if (!$e1 && !$e) + { + if ($this->p_flags['in_desc']) $this->JavaDochandleDesc($word, $pevent); + else $this->handleTags($word, $pevent); + } + if ($e) + { + if (!isset($this->p_vars['periodline'])) $this->p_vars['periodline'] = 0; + if ($this->p_vars['periodline'] > 3) + { + $this->p_flags['useperiod'] = false; + } + + $this->p_vars['docblock_desc'] = new parserDesc; +// echo "i = ".$this->p_vars['periodline']."; i < " . count($this->p_vars['line']) . "\n"; + if ($this->p_vars['docblock_type'] == 'docblock') + { + if (isset($this->p_vars['docblock_template'])) + { + // copy template values if not overridden + if (!$this->p_vars['docblock']->getExplicitPackage()) + { + if ($p = $this->p_vars['docblock_template']->getKeyword('package')) + { + $this->p_vars['docblock']->addKeyword('package',$p); + $this->p_vars['docblock']->setExplicitPackage(); + } + if ($p = $this->p_vars['docblock_template']->getKeyword('category')) + { + $this->p_vars['docblock']->addKeyword('category',$p); + $this->p_vars['docblock']->setExplicitCategory(); + } + if ($p = $this->p_vars['docblock_template']->getKeyword('subpackage')) + { + $this->p_vars['docblock']->addKeyword('subpackage',$p); + } + } + $tags = $this->p_vars['docblock_template']->listTags(); + foreach($tags as $tag) + { + $this->p_vars['docblock']->addKeyword($tag->keyword,$tag->value); + } + $this->p_vars['docblock_desc']->add($this->p_vars['docblock_template']->desc); + if (!count($this->p_vars['docblock']->params)) $this->p_vars['docblock']->params = $this->p_vars['docblock_template']->params; + } + if ($a = strpos(trim($this->p_vars['shortdesc']),'

') === 0) + $this->p_vars['shortdesc'] = substr($this->p_vars['shortdesc'],strpos($this->p_vars['shortdesc'],'

') + 4); + $this->p_vars[$this->p_vars['docblock_type']]->setShortDesc($this->p_vars['shortdesc']); + } + for($i = 0; $i < count($this->p_vars['line']); $i++) + { + // the line will not be set if it doesn't start with a * + if (isset($this->p_vars['line'][$i])) + $this->p_vars['docblock_desc']->add($this->p_vars['line'][$i]); + } + + + $this->p_vars[$this->p_vars['docblock_type']]->setDesc($this->p_vars['docblock_desc']); + unset($this->p_vars['docblock_desc']); +// var_dump($this->p_vars[$this->p_vars['docblock_type']]); +// exit; + if ($this->p_vars['docblock_type'] == 'docblock') + { + $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK,$this->p_vars[$this->p_vars['docblock_type']]); + unset($this->p_vars[$this->p_vars['docblock_type']]); + $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock(); + } + $this->p_flags['in_desc'] = true; + $this->p_flags['in_tag'] = false; + $this->p_flags['useperiod'] = false; + $this->p_vars['line'] = array(); + $this->p_vars['linecount'] = 0; + $this->p_flags['start_docblock'] = true; + $this->p_flags['valid_newline'] = true; + $this->wp->setWhitespace(false); + } + } + + /** + * handler for DOCKEYWORD_DESC. + * this handler parses the short and long description of a dockeyword + */ + + function JavaDochandleDesc($word, $pevent) + { + if ($this->p_flags['valid_newline']) + { + if ($word == '@' && $this->p_flags['startline']) + { + return $this->handleTag($word, $pevent); + } + if (!isset($this->p_vars['line'][$this->p_vars['linecount']])) + { + $this->p_vars['line'][$this->p_vars['linecount']] = new parserStringWithInlineTags; + } + if ($this->p_vars['last_word'] == "." && $this->p_flags['useperiod'] == false) + { + $this->p_vars['periodline'] = $this->p_vars['linecount']; + $this->p_vars['shortdesc'] = new parserDesc; + for($i = 0; ($i <= $this->p_vars['periodline']) && ($i < count($this->p_vars['line'])); $i++) + { + if (isset($this->p_vars['line'][$i])) + $this->p_vars['shortdesc']->add($this->p_vars['line'][$i]); + } + $this->p_flags['useperiod'] = true; + } + $this->p_vars['line'][$this->p_vars['linecount']]->add($word); +// debug("DESC $word"); + } + $this->handleCR($word); + } + + /** + * handler for DOCBLOCK. + * this handler recognizes @tags in DocBlocks and parses them for display. + * It also parses out unknown tags into their own array for use by the docblock + */ + + function BetterhandleDocblock($word, $pevent) + { + $e1 = $this->checkEventPush( $word, $pevent); + if (!$this->wp->returnWhiteSpace) + { + addErrorDie(PDERROR_NEED_WHITESPACE); + } + if (!isset($this->p_vars[$this->p_vars['docblock_type']]) || !$this->p_vars[$this->p_vars['docblock_type']]) + { + $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock(); + $this->p_vars['returntype'] = false; + $this->p_vars['vartype'] = false; + $this->p_flags['startdocblock'] = true; + $this->p_flags['valid_newline'] = true; + $this->p_flags['startline'] = true; + $this->p_flags['newline'] = true; + $this->p_flags['in_desc'] = true; + $this->p_flags['in_tag'] = false; + $this->p_flags['useperiod'] = false; + $this->p_vars['line'] = array(); + $this->p_vars['linecount'] = 0; + } + $e = $this->checkEventPop( $word, $pevent); + if (!$e1 && !$e) + { + if ($this->p_flags['in_desc']) $this->handleDesc($word, $pevent); + else $this->handleTags($word, $pevent); + } + if ($e) + { + if (!isset($this->p_vars['periodline'])) $this->p_vars['periodline'] = 0; + if ($this->p_vars['periodline'] > 3) + { + $this->p_flags['useperiod'] = false; + } else + { + for($i = 0; $i < $this->p_vars['periodline']; $i++) + { + if (isset($this->p_vars['line'][$i])) + { + if ($this->p_vars['line'][$i]->trimmedStrlen() == 0 && isset($this->p_vars['line'][$i - 1]) && $this->p_vars['line'][$i - 1]->trimmedStrlen()) + { + $this->p_vars['periodline'] = $i; + } + } + } + } + // figure out the shortdesc + if ($this->p_flags['useperiod'] === false) + { + // use the first non blank line for short desc + for($i = 0; $i < count($this->p_vars['line']); $i++) + { + if (!isset($this->p_vars['line'][$i])) + $this->p_vars['line'][$i] = new parserStringWithInlineTags; + if ($this->p_vars['line'][$i]->trimmedStrlen() > 0) + { + $this->p_vars['periodline'] = $i; + $i = count($this->p_vars['line']); + } + } + + // check to see if we are going to use a blank line to end the shortdesc + // this can only be in the first 4 lines + if (count($this->p_vars['line']) > 4) + { + $max = 4; + } else { + $max = count($this->p_vars['line']); + } + + for($i = $this->p_vars['periodline']; $i < $max; $i++) + { + if (isset($this->p_vars['line'][$i])) + if ($this->p_vars['line'][$i]->trimmedStrlen() == 0) + { + $this->p_vars['periodline'] = $i; + $i = $max; + } + } + } + + if ($this->p_vars['docblock_type'] == 'docblock') + { + $this->p_vars['shortdesc'] = new parserDesc; + for($i = 0; ($i <= $this->p_vars['periodline']) && ($i < count($this->p_vars['line'])); $i++) + { + if (isset($this->p_vars['line'][$i])) + $this->p_vars['shortdesc']->add($this->p_vars['line'][$i]); + } + $this->p_vars['periodline']++; + + $this->p_vars['docblock_desc'] = new parserDesc; + if (isset($this->p_vars['docblock_template'])) + { + // copy template values if not overridden + if (!$this->p_vars['docblock']->getExplicitPackage()) + { + if ($p = $this->p_vars['docblock_template']->getKeyword('package')) + { + $this->p_vars['docblock']->addKeyword('package',$p); + $this->p_vars['docblock']->setExplicitPackage(); + } + if ($p = $this->p_vars['docblock_template']->getKeyword('category')) + { + $this->p_vars['docblock']->addKeyword('category',$p); + $this->p_vars['docblock']->setExplicitCategory(); + } + if ($p = $this->p_vars['docblock_template']->getKeyword('subpackage')) + { + $this->p_vars['docblock']->addKeyword('subpackage',$p); + } + } + $tags = $this->p_vars['docblock_template']->listTags(); + foreach($tags as $tag) + { + $this->p_vars['docblock']->addKeyword($tag->keyword,$tag->value); + } + if (!count($this->p_vars['docblock']->params)) $this->p_vars['docblock']->params = $this->p_vars['docblock_template']->params; + $this->p_vars['docblock_desc']->add($this->p_vars['docblock_template']->desc); + } + // echo "i = ".$this->p_vars['periodline']."; i < " . count($this->p_vars['line']) . "\n"; + for($i = $this->p_vars['periodline']; $i < count($this->p_vars['line']); $i++) + { + // the line will not be set if it doesn't start with a * + if (isset($this->p_vars['line'][$i])) + $this->p_vars['docblock_desc']->add($this->p_vars['line'][$i]); + } + } else + { + $this->p_vars['shortdesc'] = new parserDesc; + for($i = 0; ($i <= $this->p_vars['periodline']) && ($i < count($this->p_vars['line'])); $i++) + { + if (isset($this->p_vars['line'][$i])) + $this->p_vars['shortdesc']->add($this->p_vars['line'][$i]); + } + $this->p_vars['periodline']++; + + $this->p_vars['docblock_desc'] = new parserDesc; + for($i=$this->p_vars['periodline']; $i < count($this->p_vars['line']); $i++) + { + if (isset($this->p_vars['line'][$i])) + $this->p_vars['docblock_desc']->add($this->p_vars['line'][$i]); + } + } + + + $this->p_vars[$this->p_vars['docblock_type']]->setShortDesc($this->p_vars['shortdesc']); + $this->p_vars[$this->p_vars['docblock_type']]->setDesc($this->p_vars['docblock_desc']); + unset($this->p_vars['docblock_desc']); +// var_dump($this->p_vars[$this->p_vars['docblock_type']]); +// exit; + if ($this->p_vars['docblock_type'] == 'docblock') + { + $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK,$this->p_vars[$this->p_vars['docblock_type']]); + unset($this->p_vars[$this->p_vars['docblock_type']]); + $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock(); + } else + { + $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK_TEMPLATE,$this->p_vars[$this->p_vars['docblock_type']]); + } + $this->p_flags['in_desc'] = true; + $this->p_flags['in_tag'] = false; + $this->p_flags['useperiod'] = false; + $this->p_vars['line'] = array(); + $this->p_vars['linecount'] = 0; + $this->p_flags['start_docblock'] = true; + $this->p_flags['valid_newline'] = true; + $this->wp->setWhitespace(false); + $this->p_vars['docblock_type'] = 'docblock'; + } + } + + /** + * Handles docblock templates + * @tutorial phpDocumentor.howto.pkg#basics.docblocktemplate + */ + function handleDocBlockTemplate($word, $pevent) + { + $this->p_vars['docblock_type'] = 'docblock_template'; + $this->p_vars['event_stack']->popEvent(); + $this->p_vars['event_stack']->pushEvent(PARSER_EVENT_DOCBLOCK); + // fool the docblock handler into thinking everything is totally normal + $this->p_vars['last_word'] = '/**'; + $pevent = PARSER_EVENT_DOCBLOCK; + $this->BetterhandleDocBlock($word, $pevent); + } + + /** + * Handles closing docblock templates /**#@-* / + * @tutorial phpDocumentor.howto.pkg#basics.docblocktemplate + */ + function handleEndDocBlockTemplate($word, $pevent) + { + unset($this->p_vars['docblock_template']); + $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,PHPDOCUMENTOR_EVENT_END_DOCBLOCK_TEMPLATE); + $this->p_vars['event_stack']->popEvent(); + } + /**#@-*/ + /** + * Handles a new line in a DocBlock + * @param string token containing a newline \n + * @access private + */ + function handleCR($word) + { + $this->laststart = $this->p_flags['startline']; + if ($word == "\n" || $word == ".\n") + { + $this->p_flags['start_docblock'] = false; + $this->p_flags['newline'] = true; + $this->p_flags['valid_newline'] = false; + if ($this->p_flags['in_desc'] && !$this->p_flags['useperiod']) + { + if ($word == ".\n") + { + $this->p_flags['useperiod'] = true; + $this->p_vars['periodline'] = $this->p_vars['linecount']; + } + } + } else + { + if ($this->p_flags['valid_newline'] && strlen(trim($word))) + { + $this->p_flags['startline'] = false; + } + if ($this->p_flags['newline'] && ($word == '*' || $this->p_flags['start_docblock'])) + { + $this->p_flags['newline'] = false; + $this->p_flags['valid_newline'] = true; + if (!$this->p_flags['start_docblock']) + $this->p_vars['linecount']++; + $this->p_flags['startline'] = true; + $justset = true; +// debug('valid newline'); + } + } + } + + /** + * handler for DOCKEYWORD_DESC. + * this handler parses the short and long description of a dockeyword + * @access private + */ + + function handleDesc($word, $pevent) + { +// echo "|$word|\n"; + if ($this->p_flags['valid_newline']) + { + if ($word == '@' && $this->p_flags['startline']) + { + return $this->handleTag($word, $pevent); + } + if ($this->p_vars['last_word'] == ". " || $this->p_vars['last_word'] == ".\t") + { + $this->p_flags['useperiod'] = true; + $this->p_vars['periodline'] = $this->p_vars['linecount']; + $this->p_vars['linecount']++; + } + if (!isset($this->p_vars['line'][$this->p_vars['linecount']])) + { + $this->p_vars['line'][$this->p_vars['linecount']] = new parserStringWithInlineTags; + } + if ($this->p_flags['startline']) + { + if ($word[0] == ' ') $word = substr($word,1); +// $word = ltrim($word," \t"); + } + if ($word != '') $this->p_vars['line'][$this->p_vars['linecount']]->add($word); +// debug("DESC $word"); + } + $this->handleCR($word); + } + + /**#@+ + * @access private + * @param string token parsed from source + * @param integer parser constant from {@link Parser.inc} + */ + /** + * handler for DOCKEYWORD_TAGS. + * this handler recognizes @tags in DocBlocks and parses them for display + * I think this may be unused. We'll delete from 1.1 if so + */ + function handleTags($word, $pevent) + { + if ($this->p_flags['valid_newline']) + { +// debug("TAGS $word"); + } + $this->handleCR($word); + } + + /** + * handler for DOCKEYWORD. + * this handler recognizes @tags in DocBlocks and parses them for display + */ + function handleTag($word, $pevent) + { + if ($this->p_flags['in_desc'] && !$this->p_flags['valid_newline']) + { + $this->p_vars['event_stack']->popEvent(); + return $this->handleDesc($word, $pevent); + } +// if ($this->p_vars['last_word'] == '@') fancy_debug('here'.$word,$this->p_flags['startline'],$this->p_flags['in_tag']); + if ($this->p_vars['tagname'] == 'author') + { + if ($word == '<') + { + $this->p_vars['event_stack']->pushEvent(PARSER_EVENT_DOCKEYWORD_EMAIL); + return $this->handleDockeywordEmail($word, $pevent); + } + } + if ($this->checkEventPush( $word, $pevent)) return; + if ($this->p_vars['last_word'] == '@' && !$this->p_flags['startline'] && $this->p_flags['in_desc']) + { + // fix 1203445 + if (!isset($this->p_vars['line'][$this->p_vars['linecount']])) + { + $this->p_vars['line'][$this->p_vars['linecount']] = new parserStringWithInlineTags; + } + $this->p_vars['event_stack']->popEvent(); + $this->p_vars['line'][$this->p_vars['linecount']]->add('@'); + return $this->handleDesc($word, $pevent); + } elseif($this->p_vars['last_word'] == '@' && !strlen(trim($word)) && empty($this->p_vars['tagname']) && $this->p_flags['in_desc']) + { + // fix 1203445 + if (!isset($this->p_vars['line'][$this->p_vars['linecount']])) + { + $this->p_vars['line'][$this->p_vars['linecount']] = new parserStringWithInlineTags; + } + $pevent = $this->p_vars['event_stack']->popEvent(); + $this->p_vars['line'][$this->p_vars['linecount']]->add('@'); + return $this->handleDesc($word, $pevent); + } + if ($word == '@' && $this->p_flags['startline'] && $this->p_flags['in_tag']) + { + $this->wp->backupPos($word); + $white = $this->wp->returnWhiteSpace; + $this->wp->setWhitespace(true); + $word1 = $this->wp->getWord(); + $this->wp->backupPos($word1); + if (strlen(trim($word1))) + { + $this->endTag(); + } + $this->wp->getWord(); + $this->wp->setWhitespace($white); + } + $this->p_flags['in_tag'] = true; + $e = $this->checkEventPop($word, $pevent); + if (!$e) + { + if ($this->p_flags['valid_newline']) + { + if (($this->p_flags['startline'] || $this->laststart) && $word != '@') + { + if ($this->p_vars['last_word'] == '@') + { +// debug("TAGSTART $word"); + $this->p_flags['in_tag'] = true; + $this->p_vars['tagname'] = $word; + $this->p_flags['startline'] = false; + $this->p_vars['tag_value'] = new parserStringWithInlineTags; + } else + { +// debug("TAG1 $word"); + if (isset($this->tagHandlers[$this->p_vars['tagname']])) + $handler = $this->tagHandlers[$this->p_vars['tagname']]; + else $handler = $this->tagHandlers['*']; + $this->$handler($word); + } + } else + { + if (empty($this->p_vars['tagname'])) + { + if ($this->p_flags['in_desc']) + { + $this->p_flags['in_tag'] = false; + // fix 1203445 + if (!isset($this->p_vars['line'][$this->p_vars['linecount']])) + { + $this->p_vars['line'][$this->p_vars['linecount']] = + new parserStringWithInlineTags; + } + $this->p_vars['line'][$this->p_vars['linecount']]->add('@'); + $this->p_vars['event_stack']->popEvent(); + $this->handleCR($word); + return $this->handleDesc($word, $pevent); + } + } +// debug("TAG2 $word"); + if (isset($this->tagHandlers[$this->p_vars['tagname']])) + $handler = $this->tagHandlers[$this->p_vars['tagname']]; + else $handler = $this->tagHandlers['*']; + $this->$handler($word); + } + } + $this->handleCR($word); + } + $this->p_flags['in_desc'] = false; + if ($e) + { + $this->endTag(); + $this->wp->setWhitespace(false); + // walk back a word + $this->wp->backupPos($word); + $this->wp->setWhitespace(true); + } + } + /**#@-*/ + /** + * Called to clean up at the end of parsing a @tag in a docblock + */ + function endTag() + { + if (isset($this->tagHandlers[$this->p_vars['tagname']])) + $handler = $this->tagHandlers[$this->p_vars['tagname']]; + else $handler = $this->tagHandlers['*']; + $this->$handler(false); + $this->p_vars['tagname'] = ''; + $this->p_flags['startline'] = true; +// debug("ENDTAG"); + } + + /**#@+ + * Tag Handlers + * @param string + */ + /** + * Handles all standard tags that only have a description + */ + function defaultTagHandler($word) + { + if ($word !== false) + { + $this->p_vars['tag_value']->add($word); + } else + { + $this->p_vars[$this->p_vars['docblock_type']]->addKeyword($this->p_vars['tagname'],$this->p_vars['tag_value']); + } + } + + /** + * Handles tags like '@filesource' that only work in PHP 4.3.0+ + */ + function invalidTagHandler($word) + { + if ($word === false) + { + addError(PDERROR_TAG_NOT_HANDLED,$this->p_vars['tagname']); + } + } + + /** + * handles @package + * @tutorial tags.package.pkg + */ + function packageTagHandler($word) + { + if ($word !== false) + { + $this->p_vars['tag_value']->add($word); + } else + { + $this->p_vars[$this->p_vars['docblock_type']]->addKeyword($this->p_vars['tagname'],$this->p_vars['tag_value']); + $this->p_vars[$this->p_vars['docblock_type']]->setExplicitPackage(); + } + } + + /** + * handles @example + * @tutorial tags.example.pkg + */ + function exampleTagHandler($word) + { + if ($word !== false) + { + $this->p_vars['tag_value']->add($word); + } else + { + $this->p_vars[$this->p_vars['docblock_type']]->addExample($this->p_vars['tag_value'], $this->p_vars['parsepath']); + } + } + + /** + * handles @category + * @tutorial tags.category.pkg + */ + function categoryTagHandler($word) + { + if ($word !== false) + { + $this->p_vars['tag_value']->add($word); + } else + { + $this->p_vars[$this->p_vars['docblock_type']]->addKeyword($this->p_vars['tagname'],$this->p_vars['tag_value']); + $this->p_vars[$this->p_vars['docblock_type']]->setExplicitCategory(); + } + } + + /** + * handles @global + * @tutorial tags.global.pkg + */ + function globalTagHandler($word) + { + if ($word !== false) + { + // no data yet + $a = trim($this->p_vars['tag_value']->getString()); + if (empty($a)) + { + // not an empty word + if (trim($word) != '') + { + if (!empty($this->p_vars['global_type'])) + { + if (!$this->p_flags['define_global'] && !$this->p_flags['function_global']) + { + // @global type $GLOBALVARNAME ? + if (substr($word,0,1) == '$') + { + $this->p_flags['define_global'] = true; + $this->p_flags['function_global'] = false; + $this->p_vars['find_global'] = $word; + } else + { // function @global type description + $this->p_flags['function_global'] = true; + $this->p_flags['define_global'] = false; + $this->p_vars['tag_value']->add($word); + } + } else + { + if ($this->p_flags['define_global']) + { + $this->p_vars['find_global'] .= $word; + } elseif($this->p_flags['function_global']) + { + // description, to be added to the tag + $this->p_vars['tag_value']->add($word); + } + } + } else + { + $this->p_vars['global_type'] = $word; + } + } else $this->p_vars['tag_value']->add($word); // add whitespace to the tag description + } else + { // tag_value has data, must be a function @global + $this->p_vars['tag_value']->add($word); + } + } else + { // endtag + if ($this->p_flags['define_global']) + { + $this->findGlobal($this->p_vars['find_global']); + } + elseif ($this->p_flags['function_global']) + { + $this->p_vars[$this->p_vars['docblock_type']]->addFuncGlobal($this->p_vars['global_type'],$this->p_vars['tag_value']); + $this->p_vars['global_type'] = ''; + } + else + { + addError(PDERROR_MALFORMED_GLOBAL_TAG); + } + $this->p_vars['find_global'] = ''; + $this->p_flags['define_global'] = false; + $this->p_flags['function_global'] = false; + } + } + + /** + * handles @staticvar + * @tutorial tags.staticvar.pkg + */ + function staticvarTagHandler($word) + { + if ($word !== false) + { + if (!$this->p_vars['returntype']) $this->p_vars['returntype'] = trim($word); + else + { + if (!$this->p_vars['paramname']) + { + if (substr(trim($word),0,1) == "$") + $this->p_vars['paramname'] = trim($word); + else $this->p_vars['tag_value']->add($word); + } else + { + if (0)//strtolower($this->p_vars['paramtype']) == 'object') + { + if (strlen(trim($word))) + $this->p_vars['paramname'] = trim($word); + } else $this->p_vars['tag_value']->add($word); + } + } + } else + { + if (!$this->p_vars['paramname']) + $this->p_vars[$this->p_vars['docblock_type']]->addStaticVar(null,$this->p_vars['returntype'],$this->p_vars['tag_value']); + else + $this->p_vars[$this->p_vars['docblock_type']]->addStaticVar($this->p_vars['paramname'],$this->p_vars['returntype'],$this->p_vars['tag_value']); + $this->p_vars['paramname'] = false; + $this->p_vars['returntype'] = false; + } + } + + /** + * handles @uses + * @tutorial tags.uses.pkg + */ + function usesTagHandler($word) + { + if ($word !== false) + { + if (!$this->p_vars['seelement']) $this->p_vars['seelement'] = trim($word); + else + { + $this->p_vars['tag_value']->add($word); + } + } else + { + $see = new parserStringWithInlineTags; + $see->add($this->p_vars['seelement']); + $this->p_vars[$this->p_vars['docblock_type']]->addUses($see,$this->p_vars['tag_value']); + $this->p_vars['seelement'] = false; + } + } + + /** + * handles @param + * @tutorial tags.param.pkg + */ + function paramTagHandler($word) + { + if ($word !== false) + { + if (!$this->p_vars['returntype']) $this->p_vars['returntype'] = trim($word); + else + { + if (!$this->p_vars['paramname']) + { + if (substr(trim($word),0,1) == "$" || substr(trim($word),0,2) == "&$") + $this->p_vars['paramname'] = trim($word); + else $this->p_vars['tag_value']->add($word); + } else + { + if (0)//strtolower($this->p_vars['paramtype']) == 'object') + { + if (strlen(trim($word))) + $this->p_vars['paramname'] = trim($word); + } else $this->p_vars['tag_value']->add($word); + } + } + } else + { + if (!$this->p_vars['paramname']) + $this->p_vars[$this->p_vars['docblock_type']]->addParam(null,$this->p_vars['returntype'],$this->p_vars['tag_value']); + else + $this->p_vars[$this->p_vars['docblock_type']]->addParam($this->p_vars['paramname'],$this->p_vars['returntype'],$this->p_vars['tag_value']); + $this->p_vars['paramname'] = false; + $this->p_vars['returntype'] = false; + } + } + + /** + * handles @return + * @tutorial tags.return.pkg + */ + function returnTagHandler($word) + { + if ($word !== false) + { + if (!$this->p_vars['returntype']) $this->p_vars['returntype'] = trim($word); + else + { + if (strtolower($this->p_vars['returntype']) == 'object') + { + if (strlen(trim($word))) + $this->p_vars['returntype'] = trim($word); + } else $this->p_vars['tag_value']->add($word); + } + } else + { + $this->p_vars[$this->p_vars['docblock_type']]->addReturn($this->p_vars['returntype'],$this->p_vars['tag_value']); + $this->p_vars['returntype'] = false; + } + } + + /** + * handles @var + * @tutorial tags.var.pkg + */ + function varTagHandler($word) + { + if ($word) + { + if (!$this->p_vars['vartype']) $this->p_vars['vartype'] = trim($word); + else + { + if (strtolower($this->p_vars['vartype']) == 'object') + { + if (strlen(trim($word))) + $this->p_vars['vartype'] = trim($word); + } + else $this->p_vars['tag_value']->add($word); + } + } elseif ($word === false) + { + $this->p_vars[$this->p_vars['docblock_type']]->addVar($this->p_vars['vartype'],$this->p_vars['tag_value']); + $this->p_vars['vartype'] = false; + } + } + /**#@-*/ + /** @access private */ + function getSource() + { + $this->p_flags['get_source'] = true; + } + /**#@+ + * @access private + * @param string token parsed from source + * @param integer parser constant from {@link Parser.inc} + */ + /** + * handler for DOCKEYWORD_EMAIL. + * this handler recognizes angle brackets < and > surrounding an email address in an @author tag, + * and returns a mailto: hyperlink + */ + + function handleDockeywordEmail($word, $pevent) + { + //echo $this->wp->getPos() . ": |$word|\n"; + if (!$this->checkEventPop($word,$pevent) && $word != "<") + { + if (strstr($word,"@")) + { + $this->p_vars['tag_value']->add('<'); + $this->p_vars['tag_value']->add(new parserLinkInlineTag("mailto:$word",$word)); + $this->p_vars['tag_value']->add('>'); + } else { + $this->p_vars['tag_value']->add("<$word>"); + } + } + } + + /** + * handler for INLINE_DOCKEYWORD. + * this handler recognizes {@inline tags} like link, and parses them, replacing them directly + * in the text flow with their output. + */ + + function handleInlineDockeyword($word, $pevent) + { + // echo $this->wp->getPos() . ": |$word|\n"; + + // echo "docktype: $this->p_vars['inline_dockeyword_type']\n"; + if (!isset($this->p_vars['inline_dockeyword_type'])) $this->p_vars['inline_dockeyword_type'] = false; + if (!isset($this->p_vars['inline_dockeyword_data'])) $this->p_vars['inline_dockeyword_data'] = ''; + if (!$this->p_vars['inline_dockeyword_type']) + { + if (in_array($word,$this->allowableInlineTags)) + { + if ($word == '}') + $this->p_vars['inline_dockeyword_type'] = ''; + else + $this->p_vars['inline_dockeyword_type'] = strtolower($word); + $this->p_vars['whitesp'] = $this->wp->returnWhiteSpace; + $this->wp->setWhiteSpace(true); + } else { + if ($this->p_flags['in_desc']) + { + // fix 1203445 + if (!isset($this->p_vars['line'][$this->p_vars['linecount']])) + { + $this->p_vars['line'][$this->p_vars['linecount']] = + new parserStringWithInlineTags; + } + if ($word == '}') + { + $this->p_vars['line'][$this->p_vars['linecount']]->add('{@'); + } else + { + $this->p_vars['line'][$this->p_vars['linecount']]->add('{@'.$word); + } + } elseif($this->p_flags['in_tag']) + { + if ($word == '}') + $this->p_vars['tag_value']->add('{@'.$word); + else + $this->p_vars['tag_value']->add('{@'.$word); + } + $this->p_vars['event_stack']->popEvent(); + $this->p_vars['inline_dockeyword_type'] = false; + $this->p_vars['inline_dockeyword_data'] = ''; + return; + } + } else + { + if ($word != "}") + { + $this->p_vars['inline_dockeyword_data'] .= $word; + } + } + if ($this->checkEventPop($word,$pevent)) + { + $this->wp->setWhiteSpace($this->p_vars['whitesp']); + if ($this->p_vars['inline_dockeyword_type']=='link') + { + // support hyperlinks of any protocol + if (is_numeric(strpos($this->p_vars['inline_dockeyword_data'],'://')) || (strpos(trim($this->p_vars['inline_dockeyword_data']),'mailto:') === 0)) + { + // if there is more than 1 parameter, the stuff after the space is the hyperlink text + if (strpos(trim($this->p_vars['inline_dockeyword_data']),' ')) + { + $i1 = strpos(trim($this->p_vars['inline_dockeyword_data']),' ') + 1; + $link = substr(trim($this->p_vars['inline_dockeyword_data']),0,$i1 - 1); + $text = substr(trim($this->p_vars['inline_dockeyword_data']),$i1); + $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($link,$text); +// ''.$text.''; + } + else + { + $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']); + } +// ''.$this->p_vars['inline_dockeyword_data'].''; + } else + { + if (!strpos($this->p_vars['inline_dockeyword_data'],',')) + { + $testp = explode('#',$this->p_vars['inline_dockeyword_data']); + if (count($testp) - 1) + $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$testp[1]); + else + $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']); + } else + $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']); + } + } + if ($this->p_vars['inline_dockeyword_type'] == 'tutorial') + { + $this->p_vars['inline_dockeyword_data'] = new parserTutorialInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']); + } + if ($this->p_vars['inline_dockeyword_type'] == 'source') + { + $this->getSource(); + $this->p_vars['inline_dockeyword_data'] = new parserSourceInlineTag($this->p_vars['inline_dockeyword_data']); + } + if ($this->p_vars['inline_dockeyword_type'] == 'inheritdoc') + { + $this->p_vars['inline_dockeyword_data'] = new parserInheritdocInlineTag(); + } + if ($word == '*/') + { + if (!isset($this->p_vars['inline_dockeyword_type'])) $this->p_vars['inline_dockeyword_type'] = ''; + if (!isset($this->p_vars['tagname'])) $this->p_vars['tagname'] = ''; + if (!isset($this->p_vars['tag_value']) || !is_object($this->p_vars['tag_value'])) $this->p_vars['tag_value'] = new parserStringWithInlineTags; + 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()); + // when we add the error class, raise error here: we reached the end of the docblock + $this->wp->backupPos($word); + } + if ($this->p_flags['in_desc']) + { + $this->p_vars['line'][$this->p_vars['linecount']]->add($this->p_vars['inline_dockeyword_data']); + $this->p_vars['inline_dockeyword_type'] = false; + $this->p_vars['inline_dockeyword_data'] = ''; + } + elseif ($this->p_flags['in_tag']) + { + $this->p_vars['tag_value']->add($this->p_vars['inline_dockeyword_data']); + $this->p_vars['inline_dockeyword_type'] = false; + $this->p_vars['inline_dockeyword_data'] = ''; + } + } + } + + /** + * handler for INCLUDE. + * this handler recognizes include/require/include_once/include_once statements, and publishes the + * data to Render + */ + + function handleInclude($word, $pevent) + { + if (!$this->p_flags['in_include']) + { + $this->p_vars['linenum'] = $this->wp->linenum; + } + $this->p_flags['in_include'] = true; + $a = $this->checkEventPush( $word, $pevent); + if (!$this->p_flags['includename_isset']) + { + $this->p_flags['includename_isset'] = true; + $this->p_vars['include_name'] = $this->p_vars['last_word']; + if ($a) + $this->p_vars['include_value'] = ''; + else + $this->p_vars['include_value'] = $word; + unset($this->p_vars['quote_data']); + } else + { + if (!$a) + { + if (empty($this->p_vars['include_params_data'])) + { + if (isset($this->p_vars['quote_data'])) + { + $this->p_vars['include_value'] .= '"'.$this->p_vars['quote_data'].'"'; + unset($this->p_vars['quote_data']); + } + if ($word != ';') + $this->p_vars['include_value'] .= $word; + } + } else + { + $this->p_vars['include_params_data'] = ''; + } + } + + if ($this->checkEventPop($word,$pevent)) + { + $this->p_vars['include'] = new parserInclude; + $this->p_vars['include']->setLineNumber($this->p_vars['linenum']); + $this->p_flags['in_include'] = false; + $this->p_vars['include']->setName($this->p_vars['include_name']); + $this->p_vars['include']->setValue($this->p_vars['include_value']); + $this->publishEvent(PHPDOCUMENTOR_EVENT_INCLUDE,$this->p_vars['include']); + $this->p_flags['includename_isset'] = false; + unset($this->p_vars['include']); + unset($this->p_vars['include_name']); + unset($this->p_vars['include_value']); + unset($this->p_vars['include_params_data']); + } + } + + /** + * handler for INCLUDE_PARAMS. + * this handler parses the contents of ( ) in include/require/include_once/include_once statements + */ + + function handleIncludeParams($word, $pevent) + { + $this->checkEventPush( $word, $pevent); + + $this->p_flags['include_parens'] = true; + if(!isset($this->p_vars['include_params_data'])) $this->p_vars['include_params_data'] = ''; + + if ($this->checkEventPop($word,$pevent)) + { + if (isset($this->p_vars['quote_data'])) + { + $this->p_vars['include_value'] = $this->p_vars['include_params_data'].'"'.$this->p_vars['quote_data'].'"'; + unset($this->p_vars['quote_data']); + } else { + if (!empty($this->p_vars['include_params_data'])) + $this->p_vars['include_value'] = $this->p_vars['include_params_data']; + else + $this->p_vars['include_value'] = trim($this->p_vars['last_word']); + } + } + if (isset($this->p_vars['quote_data'])) + { + $this->p_vars['include_params_data'] .= '"'.$this->p_vars['quote_data'].'"'; + unset($this->p_vars['quote_data']); + } + if (($word != "'") && ($word != '"')) + $this->p_vars['include_params_data'] .= $word; + } + + /** + * handler for INCLUDE_PARAMS_PARENTHESIS. + * this handler takes all parenthetical statements within file in: + * include statement include(file), and handles them properly + */ + + function handleIncludeParamsParenthesis($word, $pevent) + { + if (isset($this->p_vars['quote_data'])) + { + $this->p_vars['include_params_data'] .= '"'.$this->p_vars['quote_data'].'"'; + unset($this->p_vars['quote_data']); + } + $this->p_vars['include_params_data'] .= $word; + $this->checkEventPush( $word, $pevent); + $this->checkEventPop( $word, $pevent); + } + /**#@-*/ + /** + * this function checks whether parameter $word is a token for pushing a new event onto the Event Stack. + * @return mixed returns false, or the event number + */ + + function checkEventPush($word,$pevent) + { + $e = false; + if (isset($this->pushEvent[$pevent])) + { + if (isset($this->pushEvent[$pevent][strtolower($word)])) + $e = $this->pushEvent[$pevent][strtolower($word)]; + } + if ($e) + { + $this->p_vars['event_stack']->pushEvent($e); + return $e; + } else { + return false; + } + } + + /** + * this function checks whether parameter $word is a token for popping the current event off of the Event Stack. + * @return mixed returns false, or the event number popped off of the stack + */ + + function checkEventPop($word,$pevent) + { + if (!isset($this->popEvent[$pevent])) return false; + if (in_array(strtolower($word),$this->popEvent[$pevent])) + { + return $this->p_vars['event_stack']->popEvent(); + } else { + return false; + } + } + + /** + * setup the parser tokens, and the pushEvent/popEvent arrays + * @see $tokens, $pushEvent, $popEvent + */ + + function setupStates() + { + $this->tokens[STATE_PHPCODE] = array(" ", "\t",";","?>","","/**#@+","/**#@-*/","/**", "//","/*","#","\r\n","\n","\r","(",'<<<','"',"'"); + $this->tokens[STATE_QUOTE] = array("\\\"","\\\\","\""); + $this->tokens[STATE_LOGICBLOCK] = array("{","}","\"","'","/*","//","#","?>","",'<<<','global','static'); + $this->tokens[STATE_FUNC_GLOBAL] = array("\"","'","/*","//","#",";",","); + $this->tokens[STATE_STATIC_VAR] = array("\"","'","/*","//","#",";",",",'=','array'); + $this->tokens[STATE_STATIC_VAR_VALUE] = array("/*","//","#"," ","\t",";","=","\"","'","array",","); + $this->tokens[STATE_NOEVENTS] = array("'); + $this->tokens[STATE_COMMENTBLOCK] = array("*/","\n"); + $this->tokens[STATE_COMMENT] = array("\r\n","\r","\n"); + $this->tokens[STATE_DEFINE] = array(" ","(",";"); + $this->tokens[STATE_DEFINE_PARAMS] = array("/*","//","#",",",")"," ","'","\"","("); + $this->tokens[STATE_DEFINE_PARAMS_PARENTHESIS] = array("(","'","\"",")"); + $this->tokens[STATE_FUNCTION_PARAMS] = array("/*","//","#","\"",",",")","="," ","'","("); + $this->tokens[STATE_SINGLEQUOTE] = array("'","\\'","\\\\"); + $this->tokens[STATE_CLASS] = array(" ", "\t", "?>", "", ";", "}", "{", + "/**#@+", "/**#@-*/", "/**", "//", "/*", "#", + "\r\n", "\n", "\r","("); + $this->tokens[STATE_DOCBLOCK] = array("*/","*","@","\r\n","\n","\r",". ",".\n",".\t",'{@'); + $this->tokens[STATE_DOCBLOCK_TEMPLATE] = array("*/","*","@","\r\n","\n","\r",". ",".\n",".\t",'{@'); + $this->tokens[STATE_DOCKEYWORD] = array("@","*/","*","\n","\r\n","\r","\t"," ","<",">",'{@'); + $this->tokens[STATE_INLINE_DOCKEYWORD] = array("{@","}","\t"," ","*/"); + $this->tokens[STATE_DOCKEYWORD_EMAIL] = array(">","\n","\r\n","\r"); + $this->tokens[STATE_VAR] = array("/*","//","#"," ","\t",";","=",",","\"","'","array"); + $this->tokens[STATE_GLOBAL] = array("/*","//","#"," ","\t",";","=","\"","'"); + $this->tokens[STATE_GLOBAL_VALUE] = array("/*","//","#"," ","\t",";","=","\"","'","array"); + $this->tokens[STATE_ARRAY] = array("/*","//","#","(",")","\"","'","array"); + $this->tokens[STATE_FUNCTION] = array("(","{","}"," ","\t","&","/*","//","#"); + $this->tokens[STATE_OUTPHP] = array("'); + $this->tokens[STATE_EOFQUOTE] = array(" ","\t","\n"); + $this->tokens[STATE_ESCAPE] = false;// this tells the word parser to just cycle + $this->tokens[STATE_INCLUDE] = array(" ","(",";","'",'"'); + $this->tokens[STATE_INCLUDE_PARAMS] = array("/*",")"," ","'","\"","("); + $this->tokens[STATE_INCLUDE_PARAMS_PARENTHESIS] = array("(","'","\"",")"); + + // For each event word to event mapings + $this->pushEvent[PARSER_EVENT_QUOTE] = + array( + "\\" => PARSER_EVENT_ESCAPE + ); + $this->popEvent[PARSER_EVENT_QUOTE] = array("\""); +########################## + + $this->pushEvent[PARSER_EVENT_LOGICBLOCK] = + array( + "\"" => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_SINGLEQUOTE, + "//" => PARSER_EVENT_COMMENT, + "#" => PARSER_EVENT_COMMENT, + "global" => PARSER_EVENT_FUNC_GLOBAL, + "static" => PARSER_EVENT_STATIC_VAR, + "/*" => PARSER_EVENT_COMMENTBLOCK, + "{" => PARSER_EVENT_LOGICBLOCK, + "?>" => PARSER_EVENT_OUTPHP, + "" => PARSER_EVENT_OUTPHP, + "<<<" => PARSER_EVENT_EOFQUOTE + ); + $this->popEvent[PARSER_EVENT_LOGICBLOCK] = array("}"); +########################## + + $this->pushEvent[PARSER_EVENT_FUNC_GLOBAL] = + array( + "\"" => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_SINGLEQUOTE, + "//" => PARSER_EVENT_COMMENT, + "#" => PARSER_EVENT_COMMENT, + "/*" => PARSER_EVENT_COMMENTBLOCK, + ); + $this->popEvent[PARSER_EVENT_FUNC_GLOBAL] = array(";"); +########################## + + $this->pushEvent[PARSER_EVENT_STATIC_VAR] = + array( + "\"" => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_SINGLEQUOTE, + "//" => PARSER_EVENT_COMMENT, + "#" => PARSER_EVENT_COMMENT, + "/*" => PARSER_EVENT_COMMENTBLOCK, + "=" => PARSER_EVENT_STATIC_VAR_VALUE, + ); + $this->popEvent[PARSER_EVENT_STATIC_VAR] = array(";"); +########################## + + $this->pushEvent[PARSER_EVENT_STATIC_VAR_VALUE] = + array( + "\"" => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_SINGLEQUOTE, + "array" => PARSER_EVENT_ARRAY, + "/*" => PARSER_EVENT_COMMENTBLOCK, + "//" => PARSER_EVENT_COMMENT, + "#" => PARSER_EVENT_COMMENT + ); + $this->popEvent[PARSER_EVENT_STATIC_VAR_VALUE] = array(";",","); +########################## + + $this->pushEvent[PARSER_EVENT_NOEVENTS] = + array( + " PARSER_EVENT_PHPCODE, + " PARSER_EVENT_PHPCODE, + '" => PARSER_EVENT_OUTPHP, + ); +########################## + + $this->pushEvent[PARSER_EVENT_FUNCTION] = + array( + "(" => PARSER_EVENT_FUNCTION_PARAMS, + "//" => PARSER_EVENT_COMMENT, + "#" => PARSER_EVENT_COMMENT, + "/*" => PARSER_EVENT_COMMENTBLOCK, + "{" => PARSER_EVENT_LOGICBLOCK + ); + $this->popEvent[PARSER_EVENT_FUNCTION] = array("}"); +########################## + + $this->pushEvent[PARSER_EVENT_DOCBLOCK] = + array( + "@" => PARSER_EVENT_DOCKEYWORD, + "{@" => PARSER_EVENT_INLINE_DOCKEYWORD + ); + $this->popEvent[PARSER_EVENT_DOCBLOCK] = array("*/"); +########################## + + $this->pushEvent[PARSER_EVENT_DOCBLOCK_TEMPLATE] = + array( + "@" => PARSER_EVENT_DOCKEYWORD, + "{@" => PARSER_EVENT_INLINE_DOCKEYWORD + ); + $this->popEvent[PARSER_EVENT_DOCBLOCK_TEMPLATE] = array("*/"); +########################## + + $this->pushEvent[PARSER_EVENT_CLASS] = + array( + "function" => PARSER_EVENT_FUNCTION, + "var" => PARSER_EVENT_VAR, + "/**" => PARSER_EVENT_DOCBLOCK, + "/**#@+" => PARSER_EVENT_DOCBLOCK_TEMPLATE, + "/**#@-*/" => PARSER_EVENT_END_DOCBLOCK_TEMPLATE, + "//" => PARSER_EVENT_COMMENT, + "/*" => PARSER_EVENT_COMMENTBLOCK, + "#" => PARSER_EVENT_COMMENT, + "?>" => PARSER_EVENT_OUTPHP, + "" => PARSER_EVENT_OUTPHP, + ); + $this->popEvent[PARSER_EVENT_CLASS] = array("}"); +########################## + + $this->pushEvent[PARSER_EVENT_DEFINE] = + array( + "/*" => PARSER_EVENT_COMMENTBLOCK, + "(" => PARSER_EVENT_DEFINE_PARAMS + ); + $this->popEvent[PARSER_EVENT_DEFINE] = array(";"); +########################## + + $this->pushEvent[PARSER_EVENT_INCLUDE] = + array( + "/*" => PARSER_EVENT_COMMENTBLOCK, + "(" => PARSER_EVENT_INCLUDE_PARAMS, + "'" => PARSER_EVENT_SINGLEQUOTE, + '"' => PARSER_EVENT_QUOTE, + ); + $this->popEvent[PARSER_EVENT_INCLUDE] = array(";"); +########################## + + $this->pushEvent[PARSER_EVENT_DEFINE_PARAMS] = + array( + "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS, + "'" => PARSER_EVENT_SINGLEQUOTE, + '"' => PARSER_EVENT_QUOTE, + "/*" => PARSER_EVENT_COMMENTBLOCK, + "//" => PARSER_EVENT_COMMENT, + "#" => PARSER_EVENT_COMMENT + ); + $this->popEvent[PARSER_EVENT_DEFINE_PARAMS] = array(")"); +########################## + + $this->pushEvent[PARSER_EVENT_INCLUDE_PARAMS] = + array( + "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS, + "'" => PARSER_EVENT_SINGLEQUOTE, + '"' => PARSER_EVENT_QUOTE, + ); + $this->popEvent[PARSER_EVENT_INCLUDE_PARAMS] = array(")"); +########################## + + $this->pushEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] = + array( + "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS, + "'" => PARSER_EVENT_SINGLEQUOTE, + '"' => PARSER_EVENT_QUOTE, + ); + $this->popEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] = array(")"); +########################## + + $this->pushEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] = + array( + "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS, + "'" => PARSER_EVENT_SINGLEQUOTE, + '"' => PARSER_EVENT_QUOTE, + ); + $this->popEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] = array(")"); +########################## + + $this->pushEvent[PARSER_EVENT_VAR] = + array( + "\"" => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_SINGLEQUOTE, + "array" => PARSER_EVENT_ARRAY, + "/*" => PARSER_EVENT_COMMENTBLOCK, + "//" => PARSER_EVENT_COMMENT, + "#" => PARSER_EVENT_COMMENT + ); + $this->popEvent[PARSER_EVENT_VAR] = array(";"); +########################## + + $this->pushEvent[PARSER_EVENT_DEFINE_GLOBAL] = + array( + "=" => PARSER_EVENT_GLOBAL_VALUE, + "\"" => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_SINGLEQUOTE, + "/*" => PARSER_EVENT_COMMENTBLOCK, + "//" => PARSER_EVENT_COMMENT, + "#" => PARSER_EVENT_COMMENT + ); + $this->popEvent[PARSER_EVENT_DEFINE_GLOBAL] = array(";"); +########################## + + $this->pushEvent[PARSER_EVENT_GLOBAL_VALUE] = + array( + "\"" => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_SINGLEQUOTE, + "array" => PARSER_EVENT_ARRAY, + "/*" => PARSER_EVENT_COMMENTBLOCK, + "//" => PARSER_EVENT_COMMENT, + "#" => PARSER_EVENT_COMMENT + ); + $this->popEvent[PARSER_EVENT_GLOBAL_VALUE] = array(";"); +########################## + + $this->pushEvent[PARSER_EVENT_COMMENT] = + array( + "\\" => PARSER_EVENT_ESCAPE + ); + $this->popEvent[PARSER_EVENT_COMMENT] = array("\n"); +########################## + + $this->popEvent[PARSER_EVENT_COMMENTBLOCK] = array("*/"); +########################## + $this->pushEvent[PARSER_EVENT_SINGLEQUOTE] = + array( + "\\" => PARSER_EVENT_ESCAPE + ); + + $this->popEvent[PARSER_EVENT_SINGLEQUOTE] = array("'"); +########################## + $this->pushEvent[PARSER_EVENT_FUNCTION_PARAMS] = + array( + "\"" => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_SINGLEQUOTE, + "array" => PARSER_EVENT_ARRAY, + "/*" => PARSER_EVENT_COMMENTBLOCK, + "//" => PARSER_EVENT_COMMENT, + "#" => PARSER_EVENT_COMMENT + ); + $this->popEvent[PARSER_EVENT_FUNCTION_PARAMS] = array(")"); +########################## + $this->pushEvent[PARSER_EVENT_DOCKEYWORD] = + array( +// "<" => PARSER_EVENT_DOCKEYWORD_EMAIL, + "{@" => PARSER_EVENT_INLINE_DOCKEYWORD, + ); + + $this->popEvent[PARSER_EVENT_DOCKEYWORD] = array("*/"); +########################## + + $this->popEvent[PARSER_EVENT_INLINE_DOCKEYWORD] = array("}","*/"); +########################## + + $this->popEvent[PARSER_EVENT_OUTPHP] = array("'); +########################## + + $this->popEvent[PARSER_EVENT_DOCKEYWORD_EMAIL] = array(">","\n"); + +########################## + $this->pushEvent[PARSER_EVENT_ARRAY] = + array( + "\"" => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_SINGLEQUOTE, + "array" => PARSER_EVENT_ARRAY, + "/*" => PARSER_EVENT_COMMENTBLOCK, + "//" => PARSER_EVENT_COMMENT, + "#" => PARSER_EVENT_COMMENT + ); + $this->popEvent[PARSER_EVENT_ARRAY] = array(")"); +########################## + } + + /** + * tell the parser's WordParser {@link $wp} to set up tokens to parse words by. + * tokens are word separators. In English, a space or punctuation are examples of tokens. + * In PHP, a token can be a ;, a parenthesis, or even the word "function" + * @param $value integer an event number + * @see WordParser + */ + + function configWordParser($e) + { + $this->wp->setSeperator($this->tokens[($e + 100)]); + } + + /** + * Debugging function, takes an event number and attempts to return its name + * @param $value integer an event number + */ + + + function getParserEventName ($value) + { + $lookup = array( + PARSER_EVENT_NOEVENTS => "PARSER_EVENT_NOEVENTS", + PARSER_EVENT_PHPCODE => "PARSER_EVENT_PHPCODE", + PARSER_EVENT_DOCBLOCK => "PARSER_EVENT_DOCBLOCK", + PARSER_EVENT_FUNCTION => "PARSER_EVENT_FUNCTION", + PARSER_EVENT_CLASS => "PARSER_EVENT_CLASS", + PARSER_EVENT_DEFINE => "PARSER_EVENT_DEFINE", + PARSER_EVENT_DEFINE_PARAMS => "PARSER_EVENT_DEFINE_PARAMS", + PARSER_EVENT_COMMENT => "PARSER_EVENT_COMMENT", + PARSER_EVENT_COMMENTBLOCK => "PARSER_EVENT_COMMENTBLOCK", + PARSER_EVENT_ESCAPE => "PARSER_EVENT_ESCAPE", + PARSER_EVENT_QUOTE => "PARSER_EVENT_QUOTE", + PARSER_EVENT_FUNCTION_PARAMS => "PARSER_EVENT_FUNCTION_PARAMS", + PARSER_EVENT_SINGLEQUOTE => "PARSER_EVENT_SINGLEQUOTE", + PARSER_EVENT_VAR => "PARSER_EVENT_VAR", + PARSER_EVENT_LOGICBLOCK => "PARSER_EVENT_LOGICBLOCK", + PARSER_EVENT_OUTPHP => "PARSER_EVENT_OUTPHP", + PARSER_EVENT_DOCKEYWORD => "PARSER_EVENT_DOCKEYWORD", + PARSER_EVENT_DOCKEYWORD_EMAIL => "PARSER_EVENT_DOCKEYWORD_EMAIL", + PARSER_EVENT_ARRAY => "PARSER_EVENT_ARRAY", + PARSER_EVENT_INLINE_DOCKEYWORD => "PARSER_EVENT_INLINE_DOCKEYWORD", + PARSER_EVENT_EOFQUOTE => "PARSER_EVENT_EOFQUOTE", + PARSER_EVENT_INCLUDE => "PARSER_EVENT_INCLUDE", + PARSER_EVENT_INCLUDE_PARAMS => "PARSER_EVENT_INCLUDE_PARAMS", + PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS => "PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS", + PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS => "PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS", + PARSER_EVENT_DEFINE_GLOBAL => "PARSER_EVENT_DEFINE_GLOBAL", + PARSER_EVENT_GLOBAL_VALUE => "PARSER_EVENT_GLOBAL_VALUE", + PARSER_EVENT_FUNC_GLOBAL => "PARSER_EVENT_FUNC_GLOBAL", + PARSER_EVENT_STATIC_VAR => "PARSER_EVENT_STATIC_VAR", + PARSER_EVENT_DOCBLOCK_TEMPLATE => "PARSER_EVENT_DOCBLOCK_TEMPLATE", + PARSER_EVENT_END_DOCBLOCK_TEMPLATE => "PARSER_EVENT_END_DOCBLOCK_TEMPLATE", + PARSER_EVENT_METHOD_LOGICBLOCK => 'PARSER_EVENT_METHOD_LOGICBLOCK', + PARSER_EVENT_CLASS_MEMBER => 'PARSER_EVENT_CLASS_MEMBER', + PARSER_EVENT_METHOD => 'PARSER_EVENT_METHOD', + PARSER_EVENT_QUOTE_VAR => 'PARSER_EVENT_QUOTE_VAR', + PARSER_EVENT_ACCESS_MODIFIER => 'PARSER_EVENT_ACCESS_MODIFIER', + PARSER_EVENT_IMPLEMENTS => 'PARSER_EVENT_IMPLEMENTS', + PARSER_EVENT_CLASS_CONSTANT => 'PARSER_EVENT_CLASS_CONSTANT', + PARSER_EVENT_VAR_ARRAY => 'PARSER_EVENT_VAR_ARRAY', + PARSER_EVENT_VAR_ARRAY_COMMENT =>'PARSER_EVENT_VAR_ARRAY_COMMENT', + ); + if (isset($lookup[$value])) + return $lookup[$value]; + else return $value; + } +} + +/** + * Global package page parser + * + * @deprecated in favor of tutorials + * @tutorial tutorials.pkg + * @package phpDocumentor + * @subpackage Parsers + */ +class ppageParser extends Parser +{ + /** @var string */ + var $package = false; + /** @var string */ + var $subpackage = ''; + /** + * set up invariant Parser variables + */ + function ppageParser() + { + Parser::Parser(); + $this->allowableInlineTags = $GLOBALS['_phpDocumentor_inline_tutorial_tags_allowed']; + $this->eventHandlers = array(); + $this->eventHandlers[PARSER_EVENT_NOEVENTS] = 'defaultHandler'; + $this->eventHandlers[PARSER_EVENT_INLINE_DOCKEYWORD] = 'handleInlineDocKeyword'; + } + + /** + * set up invariant Parser variables + */ + function setupStates() + { + $this->tokens[STATE_NOEVENTS] = array("{@","}"); + $this->tokens[STATE_INLINE_DOCKEYWORD] = array("{@","}","\t"," "); + +########################## + + $this->pushEvent[PARSER_EVENT_NOEVENTS] = + array( + "{@" => PARSER_EVENT_INLINE_DOCKEYWORD + ); +########################## + + $this->popEvent[PARSER_EVENT_INLINE_DOCKEYWORD] = array("}"); + } + + /** + * Parse a new file + * + * @param string $parse_data + * @param string $package + * @param int $subpackage + * @return mixed false or parsed data + */ + function parse (&$parse_data,$xml,$package = 'default',$subpackage = '',$tutorial = '', + $category='default', $path='') + { + $this->setupStates(); + $this->p_vars['total'] = new parserPackagePage($package,$xml); + $this->p_vars['tutorial'] = $tutorial; + $this->_path = $path; + $this->category = $category; + $this->package = $package; + if (!isset($subpackage) || !$subpackage) $subpackage = ''; + $this->subpackage = $subpackage; + if (strlen($parse_data) == 0) + { + return false; + } + + // initialize variables so E_ALL error_reporting doesn't complain + $pevent = 0; + $word = 0; + $this->p_vars['event_stack'] = new EventStack; + // change this to a new ParserStringWithInlineTags, and change all $total .= blah to $total->add(blah) + // then modify phpDocumentor_IntermediateParser->Convert to convert all package pages (the package page handler in phpDocumentor_IntermediateParser should + // save them all in a variable) to perform the linking. then, remove the legacy code from handleDocBlock + // and handleClass in Render.inc, and do a loop that converts each package page, and passes it to handleEvent + // just like Converter::walk does with the other elements. The only other addition that might be good is a + // new descendant of parserElement parserPackagePage that contains the data and stuff. Hope this helps :) + $total = ''; + + $this->wp->setup($parse_data); + + $this->p_flags['reset_quote_data'] = true; + + do + { + $lpevent = $pevent; + $pevent = $this->p_vars['event_stack']->getEvent(); + if ($lpevent != $pevent) + { + $this->p_vars['last_pevent'] = $lpevent; + } + + if ($this->p_vars['last_pevent'] != $pevent) + { + // its a new event so the word parser needs to be reconfigured + $this->configWordParser($pevent); + } + + if (!$xml) + $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,($pevent + 100)); + + + $this->p_vars['last_word'] = $word; + $word = $this->wp->getWord(); + + if (0)//PHPDOCUMENTOR_DEBUG == true) + { + echo "LAST: |" . $this->p_vars['last_word'] . "|\n"; + echo "PEVENT: " . $this->getParserEventName($pevent) . "\n"; + echo $this->wp->getPos() . ": |$word|\n"; + } + if (isset($this->eventHandlers[$pevent])) + { + $handle = $this->eventHandlers[$pevent]; + $this->$handle($word, $pevent); + } + } while (!($word === false)); + if (!$xml) + $this->PublishEvent(PHPDOCUMENTOR_EVENT_PACKAGEPAGE,$this->p_vars['total']); + else + return $this->p_vars['total']->value; + } + + /** + * Handles all non-inline tags + * + * @param string token + * @param integer parser event + */ + function defaultHandler($word, $pevent) + { + if (!$this->checkEventPush( $word, $pevent)) + { + if ($word) $this->p_vars['total']->add($word); + } + } + + /** + * handler for INLINE_DOCKEYWORD. + * this handler recognizes {@inline tags} like link, and parses them, replacing them directly + * in the text flow with their output. + * @param string token + * @param integer parser event + */ + + function handleInlineDockeyword($word, $pevent) + { + // echo $this->wp->getPos() . ": |$word|\n"; + + // echo "docktype: $this->p_vars['inline_dockeyword_type']\n"; + if (!isset($this->p_vars['inline_dockeyword_type'])) $this->p_vars['inline_dockeyword_type'] = false; + if (!isset($this->p_vars['inline_dockeyword_data'])) $this->p_vars['inline_dockeyword_data'] = ''; + if (!$this->p_vars['inline_dockeyword_type']) + { + if (in_array($word,$this->allowableInlineTags)) + { + $this->p_vars['inline_dockeyword_type'] = strtolower($word); + $this->p_vars['whitesp'] = $this->wp->returnWhiteSpace; + $this->wp->setWhiteSpace(true); + } else { + if ($word == '}') + $this->p_vars['total']->add('{@'); + else + { + $this->p_vars['total']->add('{@'.$word); + $this->p_vars['event_stack']->popEvent(); + } + $this->p_vars['inline_dockeyword_type'] = false; + $this->p_vars['inline_dockeyword_data'] = ''; + } + } else + { + if ($word != "}") + { + $this->p_vars['inline_dockeyword_data'] .= $word; + } + } + if ($this->checkEventPop($word,$pevent)) + { + $this->wp->setWhiteSpace($this->p_vars['whitesp']); + if ($this->p_vars['inline_dockeyword_type']=='link') + { + // support hyperlinks of any protocol + if (is_numeric(strpos($this->p_vars['inline_dockeyword_data'],'://')) || (strpos(trim($this->p_vars['inline_dockeyword_data']),'mailto:') === 0)) + { + // if there is more than 1 parameter, the stuff after the space is the hyperlink text + if (strpos(trim($this->p_vars['inline_dockeyword_data']),' ')) + { + $i1 = strpos(trim($this->p_vars['inline_dockeyword_data']),' ') + 1; + $link = substr(trim($this->p_vars['inline_dockeyword_data']),0,$i1 - 1); + $text = substr(trim($this->p_vars['inline_dockeyword_data']),$i1); + $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($link,$text); +// ''.$text.''; + } + else + { + $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']); + } +// ''.$this->p_vars['inline_dockeyword_data'].''; + } else + { + $testp = explode('#',$this->p_vars['inline_dockeyword_data']); + if (count($testp) - 1) $this->p_vars['inline_dockeyword_data'] = $testp[1]; + $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']); + } + } + if ($this->p_vars['inline_dockeyword_type']=='id') + { + $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'])); + } + if ($this->p_vars['inline_dockeyword_type'] == 'tutorial') + { + $this->p_vars['inline_dockeyword_data'] = new parserTutorialInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']); + } + if ($this->p_vars['inline_dockeyword_type'] == 'toc') + { + $this->p_vars['inline_dockeyword_data'] = new parserTocInlineTag(); + } + if ($this->p_vars['inline_dockeyword_type'] == 'example') + { + $example = + new parserExampleInlineTag($this->p_vars['inline_dockeyword_data'], $this->_path, true); + $this->p_vars['total']->add($example->getProgramListing()); + } else + { + $this->p_vars['total']->add($this->p_vars['inline_dockeyword_data']); + } + $this->p_vars['inline_dockeyword_type'] = false; + $this->p_vars['inline_dockeyword_data'] = ''; + } + } +} +?> -- cgit v1.2.3