diff options
Diffstat (limited to 'buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTParser.inc')
-rwxr-xr-x | buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTParser.inc | 2946 |
1 files changed, 2946 insertions, 0 deletions
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTParser.inc b/buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTParser.inc new file mode 100755 index 00000000..5f901232 --- /dev/null +++ b/buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTParser.inc @@ -0,0 +1,2946 @@ +<?php +/** + * tokenizer extension-based parser for PHP code + * + * phpDocumentor :: automatic documentation generator + * + * PHP versions 4 and 5 + * + * Copyright (c) 2002-2008 Gregory Beaver + * + * LICENSE: + * + * This library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation; + * either version 2.1 of the License, or (at your option) any + * later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * @category ToolsAndUtilities + * @package phpDocumentor + * @subpackage Parsers + * @author Gregory Beaver <cellog@php.net> + * @copyright 2002-2008 Gregory Beaver + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version CVS: $Id: phpDocumentorTParser.inc 286921 2009-08-08 05:01:24Z ashnazg $ + * @link http://www.phpdoc.org + * @link http://pear.php.net/PhpDocumentor + * @since 1.2 + * @todo CS cleanup - change package to PhpDocumentor + */ + +/** + * Tokenizer-based parser for PHP source code + * + * @category ToolsAndUtilities + * @package phpDocumentor + * @subpackage Parsers + * @author Gregory Beaver <cellog@php.net> + * @copyright 2002-2008 Gregory Beaver + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @version Release: 1.4.3 + * @link http://www.phpdoc.org + * @link http://pear.php.net/PhpDocumentor + * @todo CS cleanup - change package to PhpDocumentor + * @todo CS cleanup - change classname to PhpDocumentor_* + */ +class phpDocumentorTParser extends Parser +{ + /**#@+ + * @access private + */ + /** + * @var EventStack + */ + var $_event_stack; + /** + * last event triggered before the current event + * @var integer + */ + var $_last_pevent; + /** + * last word parsed + * @var integer + */ + var $_last_word; + /** + * full path of the currently parsed file + * @var string + */ + var $_path; + /**#@-*/ + + /**#@+ + * Parser Variables + * @access private + */ + var $_pv_class; + var $_pv_cur_class; + var $_pv_define; + var $_pv_define_name; + var $_pv_define_value; + var $_pv_define_params_data; + var $_pv_dtype; + var $_pv_docblock; + var $_pv_dtemplate; + var $_pv_func; + var $_pv_func_param; + var $_pv_findglobal; + var $_pv_global_name; + var $_pv_global_val; + var $_pv_globals; + var $_pv_global_count; + var $_pv_include_params_data; + var $_pv_include_name; + var $_pv_include_value; + var $_pv_linenum; + var $_pv_periodline; + var $_pv_paren_count = 0; + var $_pv_statics; + var $_pv_static_count; + var $_pv_static_val; + var $_pv_quote_data; + var $_pv_function_data; + var $_pv_var; + var $_pv_varname; + var $_pv_var_value; + /**#@-*/ + + /**#@+ + * Parser Flags + * @access private + */ + var $_pf_definename_isset = false; + var $_pf_includename_isset = false; + var $_pf_get_source = false; + var $_pf_getting_source = false; + var $_pf_internal = false; + var $_pf_in_class = false; + var $_pf_in_define = false; + var $_pf_in_global = false; + var $_pf_in_include = false; + var $_pf_in_include_value = false; + var $_pf_in_var = false; + var $_pf_interface = false; + var $_pf_funcparam_val = false; + var $_pf_quote_active = false; + var $_pf_reset_quote_data = true; + var $_pf_useperiod = false; + var $_pf_set_var_value = false; + var $_pf_var_equals = false; + /**#@-*/ + + /** + * relative path of the parsed file from the base parse directory + * @var string + */ + var $source_location; + var $eventHandlers = array( + PARSER_EVENT_ARRAY => 'handleArray', + PARSER_EVENT_VAR_ARRAY => 'handleArray', + PARSER_EVENT_VAR_ARRAY_COMMENT => 'handleVarArrayComment', + PARSER_EVENT_CLASS => 'handleClass', + PARSER_EVENT_COMMENT => 'handleComment', + PARSER_EVENT_DOCBLOCK_TEMPLATE => 'handleDocBlockTemplate', + PARSER_EVENT_END_DOCBLOCK_TEMPLATE => 'handleEndDocBlockTemplate', + PARSER_EVENT_LOGICBLOCK => 'handleLogicBlock', + PARSER_EVENT_NOEVENTS => 'defaultHandler', + PARSER_EVENT_OUTPHP => 'defaultHandler', + PARSER_EVENT_DEFINE => 'handleDefine', + PARSER_EVENT_DEFINE_PARAMS => 'handleDefineParams', + PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS => 'handleDefineParamsParenthesis', + PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS => 'handleIncludeParamsParenthesis', + PARSER_EVENT_DOCBLOCK => 'handleDocBlock', + PARSER_EVENT_TAGS => 'handleTags', + PARSER_EVENT_DESC => 'handleDesc', + PARSER_EVENT_DOCKEYWORD => 'handleTag', + PARSER_EVENT_DOCKEYWORD_EMAIL => 'handleDockeywordEmail', + PARSER_EVENT_EOFQUOTE => 'handleHereDoc', + PARSER_EVENT_FUNCTION => 'handleFunction', + PARSER_EVENT_FUNCTION_PARAMS => 'handleFunctionParams', + PARSER_EVENT_FUNCTION_PARAM_VAR => 'handleFunctionParams', + PARSER_EVENT_FUNC_GLOBAL => 'handleFuncGlobal', + PARSER_EVENT_DEFINE_GLOBAL => 'handleGlobal', + PARSER_EVENT_GLOBAL_VALUE => 'handleGlobalValue', + PARSER_EVENT_INLINE_DOCKEYWORD => 'handleInlineDockeyword', + PARSER_EVENT_INCLUDE => 'handleInclude', + PARSER_EVENT_INCLUDE_PARAMS => 'handleIncludeParams', + PARSER_EVENT_QUOTE => 'handleQuote', + PARSER_EVENT_PHPCODE => 'handlePhpCode', + PARSER_EVENT_SINGLEQUOTE => 'handleSingleQuote', + PARSER_EVENT_STATIC_VAR => 'handleStaticVar', + PARSER_EVENT_STATIC_VAR_VALUE => 'handleStaticValue', + PARSER_EVENT_VAR => 'handleVar', + PARSER_EVENT_ACCESS_MODIFIER => 'handleAccessModifier', + PARSER_EVENT_IMPLEMENTS => 'handleImplements', + PARSER_EVENT_CLASS_CONSTANT => 'handleClassConstant', + ); + + var $inlineTagHandlers = array( + '*' => 'handleDefaultInlineTag', + 'link' => 'handleLinkInlineTag', + ); + + /** + * Constructor + * + */ + function phpDocumentorTParser() + { + $this->allowableTags + = $GLOBALS['_phpDocumentor_tags_allowed']; + $this->allowableInlineTags + = $GLOBALS['_phpDocumentor_inline_doc_tags_allowed']; + $this->subscribe(PHPDOCUMENTOR_EVENT_NEWLINENUM, + $GLOBALS['phpDocumentor_errors']); + $this->subscribe(PHPDOCUMENTOR_EVENT_NEWFILE, + $GLOBALS['phpDocumentor_errors']); + $this->tagHandlers['author'] = 'authorTagHandler'; + $this->tagHandlers['filesource'] = 'filesourceTagHandler'; + $this->setupEventStates(); + } + + /** + * Parse a new file + * + * @param string &$parse_data the parse data + * @param string $path the path + * @param int $base number of directories to drop off the bottom + * when creating names using path + * @param bool $packages ??? + * + * @staticvar int 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->setupStates(); + if (strlen($parse_data) == 0) { + return false; + } + + $this->configWordParser($parse_data); + // initialize variables so E_ALL error_reporting doesn't complain + $pevent = 0; + $word = 0; + + $page = new ParserPage; + $page->setSource($this->_wp->getFileSource()); + $page->setPath($path); + $this->_path = $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(':', '', dirname($path) + . PATH_DELIMITER . $page->getFile()); + $tmp = explode(PATH_DELIMITER, $name); + $name = 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->source_location = $source_location = $temploc; + $page->setSourceLocation($source_location); + + $this->publishEvent(PHPDOCUMENTOR_EVENT_PAGE, $page); + unset($page); + do { + $lpevent = $pevent; + $pevent = $this->_event_stack->getEvent(); + if ($lpevent != $pevent) { + $this->_last_pevent = $lpevent; + } + + $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE, ($pevent + 100)); + + $this->_pv_last_word = $word; + + $word = $this->_wp->getWord(); + if (isset($this->_pv_findglobal) && $word == $this->_pv_findglobal) { + $this->_last_pevent = $pevent; + + $this->_event_stack->pushEvent($pevent = PARSER_EVENT_DEFINE_GLOBAL); + } + // in wordparser, have to keep track of lines + $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWLINENUM, $this->_wp->linenum); + if ($this->_pf_get_source) { + if ($word[0] == T_FUNCTION) { + $this->_wp->retrievesource($word); + $this->_pf_get_source = false; + $this->_pf_getting_source = true; + } + } + + if (PHPDOCUMENTOR_DEBUG == true) { + echo "LAST: "; + if (is_array($this->_pv_last_word)) { + echo token_name($this->_pv_last_word[0]) . ' => |' + . htmlspecialchars($this->_pv_last_word[1]); + } else { + echo "|" . $this->_pv_last_word; + } + echo "|\n"; + echo "PEVENT: " . $this->getParserEventName($pevent) . "\n"; + echo "LASTPEVENT: " + . $this->getParserEventName($this->_last_pevent) . "\n"; + echo $this->_wp->getPos() . ": "; + if (is_array($word)) { + echo token_name($word[0]) . ' => |' + . htmlspecialchars($word[1]); + } else { + echo '|' . htmlspecialchars($word); + } + echo "|\n-------------------\n\n\n"; + } + + // $this->_pf_getting_source && + // ($pevent == PARSER_EVENT_DOCBLOCK) || + // ($pevent == PARSER_EVENT_NOEVENTS)) + if (0) { + 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); + } + + /**#@+ + * @param string $word the string word + * @param int $pevent the token constant + * @access private + * @return void + */ + + /** + * handler for COMMENT + */ + function handleComment($word, $pevent) + { + $this->_wp->backupPos(); + $this->_event_stack->popEvent(); + } + + /** + * handler for PHPCODE. + * + * this handler recognizes the <code><?</code> php processor directive, + * and begins parsing php code + */ + function handlePhpCode($word, $pevent) + { + $e = $this->checkEventPush($word, $pevent); + if (isset($this->_pv_findglobal) && $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->_pv_findglobal); + $this->_wp->findGlobal(false); + unset($this->_pv_findglobal); + } + } + } + + /** + * handler for FUNC_GLOBAL. + * + * this handler recognizes "global $var1, $var2" declarations in a function, + * and parses them + */ + function handleFuncGlobal($word, $pevent) + { + if ($this->checkEventPop($word, $pevent)) { + return; + } + if (!$this->checkEventPush($word, $pevent)) { + if ($word == ',') { + // another variable + $this->_pv_global_count++; + } else { + if (!isset($this->_pv_globals[$this->_pv_global_count])) { + $this->_pv_globals[$this->_pv_global_count] = ''; + } + + // if (!empty($this->_pv_globals[$this->_pv_global_count])) { + // $this->_pv_global_count++; + // } + + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_globals[$this->_pv_global_count] .= $word; + } + } + } + + /** + * handler for DEFINE_GLOBAL + */ + function handleGlobal($word, $pevent) + { + if (isset($this->_pv_findglobal)) { + $this->_pv_global_name = $this->_pv_findglobal; + unset($this->_pv_findglobal); + } + if (!$this->_pf_in_global) { + $this->_pv_linenum = $this->_wp->linenum + 1; + } + $this->_pf_in_global = true; + if ($this->checkEventPush($word, $pevent)) { + $this->_wp->setWhitespace(true); + } + if ($this->checkEventPop($word, $pevent)) { + $this->_pf_in_global = false; + $a = new parserGlobal; + $a->setDataType($this->_pv_global_type); + $this->_pv_global_type = ''; + $a->setLineNumber($this->_pv_linenum); + $a->setName($this->_pv_global_name); + if (isset($this->_pv_global_val)) { + $a->setValue(trim($this->_pv_global_val)); + } + $this->publishEvent(PHPDOCUMENTOR_EVENT_GLOBAL, $a); + unset($this->_pv_global_val); + unset($this->_pv_global_type); + } + } + + /** + * handler for GLOBAL_VALUE + */ + function handleGlobalValue($word, $pevent) + { + if ($this->checkEventPush($word, $pevent)) { + return; + } + $this->_wp->setWhitespace(true); + if (!isset($this->_pv_global_val)) { + $this->_pv_global_val = ''; + } + if ($this->_last_pevent == PARSER_EVENT_ARRAY) { + $this->_pv_global_val .= $this->_pv_function_data; + $this->_pv_function_data = ''; + } + if ($this->_last_pevent == PARSER_EVENT_QUOTE || + $this->_last_pevent == PARSER_EVENT_EOFQUOTE + ) { + $this->_pv_global_val .= $this->_pv_quote_data; + unset($this->_pv_quote_data); + } + if ($this->checkEventPop($word, $pevent)) { + $this->_wp->setWhitespace(false); + $this->_wp->backupPos(); + return; + } + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_global_val .= $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->_pv_static_count++; + return; + } + if (!$this->checkEventPush($word, $pevent)) { + if ($word == ',') { + $this->_pv_static_count++; + return; + } + if (!isset($this->_pv_statics[$this->_pv_static_count])) { + $this->_pv_statics[$this->_pv_static_count] = ''; + } + if (!empty($this->_pv_statics[$this->_pv_static_count])) { + $this->_pv_static_count++; + } + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_statics[$this->_pv_static_count] = $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->_pv_static_val[$this->_pv_static_count])) { + $this->_pv_static_val[$this->_pv_static_count] = ''; + } + if ($this->_last_pevent == PARSER_EVENT_QUOTE) { + $this->_pv_static_val[$this->_pv_static_count] + .= $this->_pv_quote_data; + unset($this->_pv_quote_data); + } + if ($this->_last_pevent == PARSER_EVENT_ARRAY) { + $this->_pv_static_val[$this->_pv_static_count] + .= $this->_pv_function_data; + $this->_pv_function_data = ''; + } + if ($this->checkEventPop($word, $pevent)) { + $this->_pv_static_val[$this->_pv_static_count] + = trim($this->_pv_static_val[$this->_pv_static_count]); + $this->_wp->backupPos($word); + return; + } else { + if (is_array($word)) $word = $word[1]; + $this->_pv_static_val[$this->_pv_static_count] .= $word; + } + } + + /** + * 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: + * + * <code> + * function test($a) + * { + * if (testcondition) + * { // nested logic block + * } + * } + * </code> + * + * 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 ($this->checkEventPop($word, $pevent)) { + $e = $this->_event_stack->popEvent(); + $this->_event_stack->pushEvent($e); + if ($e == PARSER_EVENT_FUNCTION) { + $this->_wp->backupPos(); + } + } + } + + /** + * 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)) { + $this->_pv_function_data = ''; + if ($e == PARSER_EVENT_FUNCTION_PARAMS && !is_object($this->_pv_func) + ) { + addErrorDie(PDERROR_FUNCTION_HAS_NONAME); + } + if ($e == PARSER_EVENT_COMMENT || $e == PARSER_EVENT_COMMENTBLOCK || + $e == PARSER_EVENT_FUNCTION_PARAMS || $e == PARSER_EVENT_LOGICBLOCK + ) { + return; + } + } + + if (!isset($this->_pv_func)) { + $this->_pv_func = false; + } + if (! is_object($this->_pv_func)) { + $this->_pv_globals = array(); + $this->_pv_global_count = $this->_pv_static_count = 0; + if ($this->_pf_in_class) { + $this->_pv_func = new parserMethod($this->_pv_cur_class); + } else { + $this->_pv_func = new parserFunction; + unset($this->_accessModifiers); + } + if (isset($this->_accessModifiers)) { + $this->_pv_func->setModifiers($this->_accessModifiers); + unset($this->_accessModifiers); + } + $this->_pv_func->setLineNumber($this->_wp->linenum + 1); + if (is_string($word) && $word == '&') { + $this->_pv_func->setReturnsReference(); + } + if (is_array($word) && $word[0] == T_STRING) { + $this->_pv_func->setName($word[1]); + } + } else { + if ($this->_pv_func->getReturnsReference()) { + if (is_array($word) && $word[0] == T_STRING) { + $this->_pv_func->setName($word[1]); + } + } + } + if ($this->checkEventPop($word, $pevent)) { + $this->_pv_func->setEndLineNumber($this->_wp->linenum + 1); + $this->_pv_func->addGlobals($this->_pv_globals); + $this->_pv_func->addStatics($this->_pv_statics, $this->_pv_static_val); + $this->_pv_globals = array(); + $this->_pv_global_count = 0; + if ($this->_pf_getting_source) { + $x = $this->_wp->getSource(); + $this->_pv_func->addSource($x); + $this->_pf_get_source = false; + $this->_pf_getting_source = false; + } + $this->publishEvent(PHPDOCUMENTOR_EVENT_FUNCTION, $this->_pv_func); + $this->_pv_func = false; + + // subtle bug fixed by this, sometimes string from function body + unset($this->_pv_quote_data); // was picked up by the next function + // as a default value for a parameter! + } + } + + /** + * 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->_pv_last_word."|\n"; + //echo "function_param = '".$this->_pv_function_param."'\n"; + //echo "function_data = '".$this->_pv_function_data."'\n"; + $e1 = $this->checkEventPush($word, $pevent); + + if (!$e1) { + if (($pop = $this->checkEventPop($word, $pevent)) && + $pevent == PARSER_EVENT_FUNCTION_PARAM_VAR + ) { + // end of [typehint ]$param[= defaultval] + if (is_string($word) && $word == ')') { + $this->_wp->backupPos(); + } + $this->endFunctionParam($word); + } elseif ($word == '=') { + // about to parse the default value + $this->_pf_funcparam_val = true; + } else { + if ($this->_pf_funcparam_val) { + // parsing default value + if (isset($this->_pv_quote_data)) { + $this->_pv_function_data .= $this->_pv_quote_data; + unset($this->_pv_quote_data); + } + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_function_data .= $word; + } else { + // pre-param + if ($pop) { + return; + } + if (!isset($this->_pv_function_param)) { + $this->_pv_function_param = ''; + } + if (is_array($word) && $pevent == PARSER_EVENT_FUNCTION_PARAMS + ) { + if ($word[0] == T_STRING || $word[0] == T_ARRAY) { + // object or array type hint + $this->_pv_function_param_type = $word[1]; + return; + } + $word = $word[1]; + } + $this->_pv_function_param .= $word; + } + } + } elseif ($e1 == PARSER_EVENT_ARRAY) { + $this->_wp->setWhiteSpace(true); + } elseif ($e1 == PARSER_EVENT_FUNCTION_PARAM_VAR) { + if (!isset($this->_pv_function_param)) { + $this->_pv_function_param = ''; + } + // we just got the $var part of the param + $this->_pv_function_param .= $word[1]; + } + } + + /** + * 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) { + return; + } + + if (!isset($this->_pv_function_data) || + (isset($this->_pv_function_data) && empty($this->_pv_function_data)) + ) { + $this->_pv_function_data = "array"; + } + + if ($word == '(' && $this->_pv_paren_count++) { + // need extra parentheses help + $this->_event_stack->pushEvent($pevent); + } + if (is_array($word)) { + $this->_pv_function_data .= $word[1]; + } else { + $this->_pv_function_data .= $word; + } + //echo "function_data = |$this->_pv_function_data|\n"; + + if ($this->checkEventPop($word, $pevent)) { + $this->_pv_paren_count--; + $this->_wp->setWhiteSpace(false); + } + } + + /** + * handler for HEREDOC in a function logic block. + * + * this handler recognizes function declarations, and parses them. The body + * of the function is parsed by handleLogicBlock() + * + * @see handleLogicBlock() + */ + function handleHereDoc($word, $pevent) + { + if (is_array($this->_pv_last_word) && + $this->_pv_last_word[0] == T_START_HEREDOC + ) { + $save = $word; + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_quote_data = $this->_pv_last_word[1] . $word; + $this->_pf_quote_active = true; + } elseif (!$this->_pf_quote_active) { + $this->_pv_quote_data = $this->_pv_last_word[1]; + $this->_event_stack->popEvent(); + $this->_wp->backupPos(); + return; + } + $save = $word; + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_quote_data .= $word; + if ($this->checkEventPop($save, $pevent)) { + $this->_pf_quote_active = false; + } + } + + /** + * handler for QUOTE. + * + * this handler recognizes strings defined with double quotation marks (") + * and single quotation marks and handles them correctly + * in any place that they legally appear in php code + */ + function handleQuote($word, $pevent) + { + if ($this->_pv_last_word == '"' || $this->_pv_last_word == "'" && + $this->_last_pevent != PARSER_EVENT_QUOTE + ) { + $save = $word; + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_quote_data = $this->_pv_last_word . $word; + $this->_pf_quote_active = true; + $this->checkEventPop($save, $pevent); + } elseif (!$this->_pf_quote_active) { + $this->_pv_quote_data = $this->_pv_last_word[1]; + $this->_event_stack->popEvent(); + $this->_wp->backupPos(); + return; + } + $save = $word; + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_quote_data .= $word; + if ($this->checkEventPop($save, $pevent)) { + $this->_pf_quote_active = false; + } + } + + /** + * 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->_pf_in_include) { + $this->_pv_linenum = $this->_wp->linenum; + } + $this->_pf_in_include = true; + + $a = $this->checkEventPush($word, $pevent); + if (!$this->_pf_includename_isset) { + $this->_pf_includename_isset = true; + + $w = $this->_pv_last_word; + if (is_array($w)) { + $w = $w[1]; + } + $this->_pv_include_name = $w; + if ($a) { + $this->_pv_include_value = ''; + } else { + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_include_value = $word; + } + unset($this->_pv_quote_data); + } else { + if (!$a) { + if (empty($this->_pv_include_params_data)) { + if ($word != ';') { + if (is_array($word)) $word = $word[1]; + $this->_pv_include_value .= $word; + } + } + } else { + if ($this->_pf_in_include_value && $a == PARSER_EVENT_INCLUDE_PARAMS + ) { + /* we're already inside the include value, + * so an open paren does NOT mean the beginning + * of "include parameters"... + * it's just a part of the include's value string... + * but we've already pushed PARSER_EVENT_INCLUDE_PARAMS + * onto the stack... + * we need to pop it off + * before handleIncludeParams gets called... + */ + $this->_event_stack->popEvent(); + // also need to keep that open parens... + $this->_pv_include_value .= $word; + } + $this->_pv_include_params_data = ''; + } + } + + if (!empty($this->_pv_include_value)) { + $this->_pf_in_include_value = true; + } + + if ($this->checkEventPop($word, $pevent)) { + $this->_pv_include = new parserInclude; + $this->_pv_include->setLineNumber($this->_pv_linenum + 1); + $this->_pf_in_include = false; + $this->_pv_include->setName($this->_pv_include_name); + $this->_pv_include->setValue($this->_pv_include_value); + $this->publishEvent(PHPDOCUMENTOR_EVENT_INCLUDE, $this->_pv_include); + $this->_pf_includename_isset = false; + $this->_pf_in_include_value = false; + unset($this->_pv_include); + unset($this->_pv_include_name); + unset($this->_pv_include_value); + unset($this->_pv_include_params_data); + } elseif ($this->_last_pevent == PARSER_EVENT_INCLUDE_PARAMS) { + // include is part of a larger statement + // force ending of include + $this->_event_stack->popEvent(); + $this->_pv_include = new parserInclude; + $this->_pv_include->setLineNumber($this->_pv_linenum + 1); + $this->_pf_in_include = false; + $this->_pv_include->setName($this->_pv_include_name); + $this->_pv_include->setValue($this->_pv_include_value); + $this->publishEvent(PHPDOCUMENTOR_EVENT_INCLUDE, $this->_pv_include); + $this->_pf_includename_isset = false; + $this->_pf_in_include_value = false; + unset($this->_pv_include); + unset($this->_pv_include_name); + unset($this->_pv_include_value); + unset($this->_pv_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) + { + $e = $this->checkEventPush($word, $pevent); + if ($e == PARSER_EVENT_COMMENT) { + return; + } + + if (!isset($this->_pv_include_params_data)) { + $this->_pv_include_params_data = ''; + } + + if ($this->checkEventPop($word, $pevent)) { + if (!empty($this->_pv_include_params_data)) { + $this->_pv_include_value = $this->_pv_include_params_data; + } else { + $w = $this->_pv_last_word; + if (is_array($w)) { + $w = $w[1]; + } + $this->_pv_include_value = $w; + } + } + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_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) + { + $this->checkEventPush($word, $pevent); + $this->checkEventPop($word, $pevent); + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_include_params_data .= $word; + } + + /** + * handler for DEFINE. + * + * handles define(constant, value); statements + */ + function handleDefine($word, $pevent) + { + if (!$this->_pf_in_define) { + $this->_pv_linenum = $this->_wp->linenum + 1; + } + $this->_pf_in_define = true; + $this->checkEventPush($word, $pevent); + + $this->_pf_definename_isset = false; + $this->_pv_define_params_data = ''; + unset($this->_pv_quote_data); + if ($this->checkEventPop($word, $pevent)) { + $this->_pf_in_define = false; + $this->_pv_define = new parserDefine; + $this->_pv_define->setLineNumber($this->_pv_linenum); + $this->_pv_define->setName($this->_pv_define_name); + $this->_pv_define->setValue($this->_pv_define_value); + $this->publishEvent(PHPDOCUMENTOR_EVENT_DEFINE, $this->_pv_define); + $this->_pf_definename_isset = false; + unset($this->_pv_define); + unset($this->_pv_define_name); + unset($this->_pv_define_value); + $this->_pf_in_define = false; + $this->_pv_define_params_data = ''; + } + } + + /** + * handler for DEFINE_PARAMS. + * + * handles the parsing of constant and value in define(constant, value); + */ + function handleDefineParams($word, $pevent) + { + $e = $this->checkEventPush($word, $pevent); + if ($e && $e != PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS) { + return; + } + + if (!isset($this->_pv_define_params_data)) { + $this->_pv_define_params_data = ''; + } + + if ($this->checkEventPop($word, $pevent)) { + if ($this->_last_pevent == PARSER_EVENT_QUOTE || + $this->_last_pevent == PARSER_EVENT_EOFQUOTE + ) { + $this->_pv_define_params_data .= $this->_pv_quote_data; + unset($this->_pv_quote_data); + } + if (is_array($word)) { + $word = $word[1]; + } + if (!empty($this->_pv_define_params_data)) { + //echo $this->_pv_define_params_data."\n"; + $this->_pv_define_value = $this->_pv_define_params_data; + } else { + $w = $this->_pv_last_word; + if (is_array($this->_pv_last_word)) { + $w = $this->_pv_last_word[1]; + } + if (!empty($w)) { + $this->_pv_define_value = $w; + } else { + $this->_pv_define_value = ""; + switch ($w) { + case 0: + $this->_pv_define_value = "0"; + break; + case null: + $this->_pv_define_value = "null"; + break; + case "": + $this->_pv_define_value = ""; + break; + } + } + } + } + if ($this->_pf_definename_isset) { + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_define_params_data .= $word; + } else { + if ($word != ",") { + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_define_params_data .= $word; + } else { + if (substr($this->_pv_define_params_data, 0, 1) == + substr($this->_pv_define_params_data, + strlen($this->_pv_define_params_data) - 1) && + in_array(substr($this->_pv_define_params_data, + 0, 1), array('"', "'")) + ) { + // remove leading and ending quotation marks + // if there are only two + $a = substr($this->_pv_define_params_data, 0, 1); + $b = substr($this->_pv_define_params_data, 1, + strlen($this->_pv_define_params_data) - 2); + if (strpos($b, $a) === false) { + $this->_pv_define_params_data = $b; + } + } + $this->_pf_definename_isset = true; + $this->_pv_define_name = $this->_pv_define_params_data; + $this->_pv_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) + { + $e = $this->checkEventPush($word, $pevent); + $this->checkEventPop($word, $pevent); + if ($this->_last_pevent == PARSER_EVENT_QUOTE) { + $this->_pv_define_params_data .= $this->_pv_quote_data; + unset($this->_pv_quote_data); + } + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_define_params_data .= $word; + } + + /** + * handler for IMPLEMENTS. + * + * this handler parses a class statement's implements clause (PHP 5) + */ + function handleImplements($word, $pevent) + { + if ($this->checkEventPop($word, $pevent)) { + $this->_wp->backupPos(); + return; + } + if (is_array($word) && $word[0] == T_STRING) { + $this->_pv_class->addImplements($word[1]); + } + } + + /** + * handler for ACCESS_MODIFIER. + * + * this handler parses public/private/protected/static/abstract PHP 5 modifiers + */ + function handleAccessModifier($word, $pevent) + { + if (!isset($this->_accessModifiers)) { + $this->_accessModifiers = array(); + } + $this->_wp->backupPos(); + $this->_event_stack->popEvent(); + if ($word[0] == T_VARIABLE) { + // this is a PHP5-style variable with no "var" + $this->_event_stack->pushEvent(PARSER_EVENT_VAR); + } + $this->_accessModifiers[] = strtolower($this->_pv_last_word[1]); + } + + /** + * handler for CLASS. + * + * this handler parses a class/interface statement + */ + function handleClass($word, $pevent) + { + if (!$this->_pf_in_class) { + $this->_pf_in_class = true; + if ($this->_pv_last_word[0] == T_INTERFACE) { + $this->_pf_interface = true; + } else { + $this->_pf_interface = false; + } + } + $a = $this->checkEventPush($word, $pevent); + + if (!isset($this->_pv_class)) { + $this->_pv_class = false; + } + if (!is_subclass_of($this->_pv_class, "parserBase")) { + $this->_pv_class = new parserClass; + if (isset($this->_accessModifiers)) { + $this->_pv_class->setModifiers($this->_accessModifiers); + unset($this->_accessModifiers); + } + if ($this->_pf_interface) { + $this->_pv_class->setInterface(); + } + $this->_pv_class->setLineNumber($this->_wp->linenum + 1); + $this->_pv_class->setname($word[1]); + $this->_pv_cur_class = $word[1]; + $this->_pv_class->setSourceLocation($this->source_location); + } + + if (is_array($this->_pv_last_word) && $this->_pv_last_word[0] == T_EXTENDS + ) { + // I don't know why I am so nice, this fixes 1150809 + if ($word[1] == $this->_pv_class->getName()) { + addErrorDie(PDERROR_CANNOT_EXTEND_SELF, $word[1]); + } + $this->_pv_class->setExtends($word[1]); + } + + if ($word == "{") { + $this->publishEvent(PHPDOCUMENTOR_EVENT_CLASS, $this->_pv_class); + } + //echo $this->wp->getPos() . ": |$word|\n"; + if ($this->checkEventPop($word, $pevent)) { + $this->_pv_class->setEndLineNumber($this->_wp->linenum + 1); + $this->_pf_in_class = $this->_pf_interface = false; + // throw an event when class is done + $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE, STATE_END_CLASS); + $this->_pv_class = false; + } + } + + /** + * handler for VAR_ARRAY_COMMENT + * + * if parsing a default value, add the comment to the text + */ + function handleVarArrayComment($word, $pevent) + { + $this->_pv_function_data .= $this->_pv_last_word[1]; + return $this->handleComment($word, $pevent); + } + + /** + * handler for VAR. + * + * handle a var $varname = default_value; + * or var $varname; statement + * in a class definition + */ + function handleVar($word, $pevent) + { + if (!$this->_pf_in_var) { + $this->_pf_set_var_value = false; + $this->_pv_var_value = ''; + $this->_pv_linenum = $this->_wp->linenum + 1; + } + $this->_pf_in_var = true; + //echo $word."\n"; + $e = $this->checkEventPush($word, $pevent); + + if (!isset($this->_pv_var)) { + $this->_pv_var = false; + } + if ($word == '=' || $word == ';' || $word == ',') { + $this->_wp->setWhitespace(true); + $this->_pf_var_equals = true; + $this->_pv_var = new parserVar($this->_pv_cur_class); + $this->_pv_var->setName($this->_pv_varname); + } + if ($this->_last_pevent == PARSER_EVENT_VAR_ARRAY) { + if (isset($this->_pv_function_data)) { + $this->_pv_var->setValue($this->_pv_function_data); + } + $this->_pf_set_var_value = true; + unset($this->_pv_function_data); + } elseif ($this->_pf_var_equals && $word != ';' && + $word != '=' && $word != ',' && !$e + ) { + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_var_value .= $word; + } + if ($word == ',') { + if (!$this->_pf_set_var_value) { + $this->_pv_var->setValue($this->_pv_var_value); + } + $this->_pf_set_var_value = false; + unset($this->_pv_var_value); + $this->_pv_var->setEndLineNumber($this->_wp->linenum + 1); + $this->_pv_var->setLineNumber($this->_pv_linenum); + if (isset($this->_accessModifiers)) { + $this->_pv_var->setModifiers($this->_accessModifiers); + } + $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR, $this->_pv_var); + unset($this->_pv_var); + $this->_pf_in_var = false; + $this->_pf_var_equals = false; + $this->_pv_varname = ''; + return; + } + if ($this->checkEventPop($word, $pevent)) { + $this->_wp->setWhitespace(false); + if (!$this->_pf_set_var_value) { + $this->_pv_var->setValue($this->_pv_var_value); + } + $this->_pf_set_var_value = false; + unset($this->_pv_var_value); + $this->_pv_var->setEndLineNumber($this->_wp->linenum + 1); + $this->_pv_var->setLineNumber($this->_pv_linenum); + if (isset($this->_accessModifiers)) { + $this->_pv_var->setModifiers($this->_accessModifiers); + unset($this->_accessModifiers); + } + $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR, $this->_pv_var); + unset($this->_pv_var); + $this->_pf_in_var = false; + $this->_pf_var_equals = false; + $this->_pv_varname = ''; + return; + } + if ($word[0] == T_VARIABLE) { + $this->_pv_varname = $word[1]; + } + } + + /** + * handler for CLASS_CONSTANT. + * + * handle a const constname = default_value; statement in a class definition + */ + function handleClassConstant($word, $pevent) + { + if (!$this->_pf_in_const) { + $this->_pf_set_const_value = false; + $this->_pv_const_value = ''; + $this->_pv_linenum = $this->_wp->linenum + 1; + } + $this->_pf_in_const = true; + //echo $word."\n"; + $e = $this->checkEventPush($word, $pevent); + + if (!isset($this->_pv_const)) { + $this->_pv_const = false; + } + if ($word == '=' || $word == ';' || $word == ',') { + $this->_wp->setWhitespace(true); + $this->_pf_const_equals = true; + $this->_pv_const = new parserConst($this->_pv_cur_class); + $this->_pv_const->setName($this->_pv_constname); + } + if ($this->_last_pevent == PARSER_EVENT_VAR_ARRAY) { + if (isset($this->_pv_function_data)) { + $this->_pv_const->setValue($this->_pv_function_data); + } + $this->_pf_set_const_value = true; + unset($this->_pv_function_data); + } elseif ($this->_pf_const_equals && $word != ';' && + $word != '=' && $word != ',' && !$e + ) { + if (is_array($word)) { + $word = $word[1]; + } + $this->_pv_const_value .= $word; + } + if ($word == ',') { + if (!$this->_pf_set_const_value) { + $this->_pv_const->setValue($this->_pv_const_value); + } + $this->_pf_set_const_value = false; + unset($this->_pv_const_value); + $this->_pv_const->setEndLineNumber($this->_wp->linenum + 1); + $this->_pv_const->setLineNumber($this->_pv_linenum); + $this->publishEvent(PHPDOCUMENTOR_EVENT_CONST, $this->_pv_const); + unset($this->_pv_const); + $this->_pf_in_const = false; + $this->_pf_const_equals = false; + $this->_pv_constname = ''; + return; + } + if ($this->checkEventPop($word, $pevent)) { + $this->_wp->setWhitespace(false); + if (!$this->_pf_set_const_value) { + $this->_pv_const->setValue($this->_pv_const_value); + } + $this->_pf_set_const_value = false; + unset($this->_pv_const_value); + $this->_pv_const->setEndLineNumber($this->_wp->linenum + 1); + $this->_pv_const->setLineNumber($this->_pv_linenum); + $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR, $this->_pv_const); + unset($this->_pv_const); + $this->_pf_in_const = false; + $this->_pf_const_equals = false; + $this->_pv_constname = ''; + return; + } + if ($word[0] == T_STRING && !$this->_pf_const_equals) { + $this->_pv_constname = $word[1]; + } + } + + /** + * Handler for the + * {@tutorial phpDocumentor.howto.pkg#using.command-line.javadocdesc} + * command-line switch DocBlocks. + * + * @todo CS cleanup - rename to javaDoc* for camelCasing rule + */ + function JavaDochandleDocblock($word, $pevent) + { + $this->commonDocBlock($word, $pevent, 'handleJavaDocDesc'); + } + + /** + * Handler for normal DocBlocks + */ + function handleDocBlock($word, $pevent) + { + $this->commonDocBlock($word, $pevent, 'handleDesc'); + } + /**#@-*/ + + /** + * Helper function for {@link handleFunctionParams()} + * + * This function adds a new parameter to the parameter list + * + * @param string $word the parameter word + * + * @return void + * @access private + */ + function endFunctionParam($word) + { + if (isset($this->_pv_quote_data)) { + $this->_pv_function_data .= $this->_pv_quote_data; + unset($this->_pv_quote_data); + } + if (isset($this->_pv_function_param)) { + $this->_pv_func->addParam($this->_pv_function_param, + $this->_pv_function_data, + $this->_pf_funcparam_val, + $this->_pv_function_param_type); + unset($this->_pv_function_param); + $this->_pv_function_data = ''; + $this->_pf_funcparam_val = false; + $this->_pv_function_param_type = null; + } + } + + /** + * Common DocBlock Handler for both JavaDoc-format and normal DocBlocks + * + * @param string $word the word + * @param int $pevent the parser event + * @param string $deschandler the handler to use + * + * @return void + * @access private + */ + function commonDocBlock($word, $pevent, $deschandler) + { + $this->_wp->backupPos(); + $this->_event_stack->popEvent(); + $word = $this->_pv_last_word[1]; + $dtype = '_pv_docblock'; + if (strpos($word, '/**') !== 0) { + // not a docblock + // $this->_wp->backupPos(); + $this->_event_stack->pushEvent(PARSER_EVENT_COMMENT); + return; + } + if ($word == '/**#@-*/') { + // stop using docblock template + $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE, + PHPDOCUMENTOR_EVENT_END_DOCBLOCK_TEMPLATE); + unset($this->_pv_dtemplate); + return; + } + if (strpos($word, '/**#@+') === 0) { + // docblock template definition + $dtype = '_pv_dtemplate'; + // strip /**#@+ and */ + $word = substr($word, 6).'*'; + $word = trim(substr($word, 0, strlen($word) - 3)); + if (strlen($word) && $word{0} != '*') { + $word = "* $word"; + } + } else { + // strip /** and */ + $word = substr($word, 2); + $word = substr($word, 0, strlen($word) - 2); + } + $lines = explode("\n", trim($word)); + $go = count($lines); + for ($i=0; $i < $go; $i++) { + if (substr(trim($lines[$i]), 0, 1) != '*') { + unset($lines[$i]); + } else { + // remove leading "* " + $lines[$i] = substr(trim($lines[$i]), 1); + } + } + // remove empty lines + if ($lines == array(false)) { + // prevent PHP 5.2 segfault (see http://bugs.php.net/bug.php?id=39350) + $lines = array(''); + } + $lines = explode("\n", trim(join("\n", $lines))); + for ($i = 0; $i < count($lines); $i++) { + if (substr(trim($lines[$i]), 0, 1) == '@' && + substr(trim($lines[$i]), 0, 2) != '@ ' + ) { + $tagindex = $i; + $i = count($lines); + } + } + if (isset($tagindex)) { + $tags = array_slice($lines, $tagindex); + $desc = array_slice($lines, 0, $tagindex); + } else { + $tags = array(); + $desc = $lines; + } + //var_dump($desc,$tags); + $this->$dtype = new parserDocBlock; + $this->$dtype->setLineNumber($this->_wp->_docblock_linenum + 1); + $this->$dtype->setEndLineNumber($this->_wp->linenum); + $this->_pv_dtype = $dtype; + $this->$deschandler($desc); + $this->handleTags($tags); + if ($dtype == '_pv_docblock') { + $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK, $this->$dtype); + $this->$dtype = new parserDocBlock(); + } else { + $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK_TEMPLATE, + $this->$dtype); + } + } + + /** + * Handles JavaDoc descriptions + * + * @param string $desc the description + * + * @return void + * @access private + */ + function handleJavaDocDesc($desc) + { + unset($this->_pv_periodline); + $this->_pf_useperiod = false; + if (empty($desc)) { + $desc = array(''); + } + foreach ($desc as $i => $line) { + $line = trim($line); + if (!isset($this->_pv_periodline) && + substr($line, strlen($line) - 1) == '.' + ) { + $this->_pv_periodline = $i; + $this->_pf_useperiod = true; + } + } + if (!isset($this->_pv_periodline)) { + $this->_pv_periodline = 0; + } + + $dtype = $this->_pv_dtype; + if ($dtype == '_pv_docblock') { + $save = $desc; + // strip leading <p> + if (strpos($desc[0], '<p>') === 0) { + $desc[0] = substr($desc[0], 3); + } + $sdesc = new parserDesc; + $desci = ''; + for ($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++ + ) { + if (strpos($desc[$i], '.') !== false) { + $desci .= substr($desc[$i], 0, strpos($desc[$i], '.') + 1); + } else { + $desci .= $desc[$i]; + } + $desci .= "\n"; + } + $sdesc->add($this->getInlineTags($desci)); + $desc = $save; + + $my_desc = new parserDesc; + if (isset($this->_pv_dtemplate)) { + // copy template values if not overridden + if (!$this->_pv_docblock->getExplicitPackage()) { + if ($p = $this->_pv_dtemplate->getKeyword('package')) { + $this->_pv_docblock->addKeyword('package', $p); + $this->_pv_docblock->setExplicitPackage(); + } + if ($p = $this->_pv_dtemplate->getKeyword('category')) { + $this->_pv_docblock->addKeyword('category', $p); + $this->_pv_docblock->setExplicitCategory(); + } + if ($p = $this->_pv_dtemplate->getKeyword('subpackage')) { + $this->_pv_docblock->addKeyword('subpackage', $p); + } + } + $tags = $this->_pv_dtemplate->listTags(); + foreach ($tags as $tag) { + $this->_pv_docblock->addTag($tag); + } + if (!count($this->_pv_docblock->params)) { + $this->_pv_docblock->params = $this->_pv_dtemplate->params; + } + $my_desc->add($this->_pv_dtemplate->desc); + } + //echo "i = ".$this->_pv_periodline."; i < " . count($desc) . "\n"; + $desci = ''; + for ($i = 0; $i < count($desc); $i++) { + // the line will not be set if it doesn't start with a * + if (isset($desc[$i])) { + $desci .= $desc[$i] . "\n"; + } + } + $my_desc->add($this->getInlineTags($desci)); + } else { + $sdesc = new parserDesc; + $save = $desc; + // strip leading <p> + if (strpos($desc[0], '<p>') === 0) { + $desc[0] = substr($desc[0], 3); + } + $desci = ''; + for ($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++ + ) { + if (strpos($desc[$i], '.') !== false) { + $desci .= substr($desc[$i], 0, strpos($desc[$i], '.') + 1); + } else { + $desci .= $desc[$i]; + } + $desci .= "\n"; + } + $sdesc->add($this->getInlineTags($desci)); + $desc = $save; + + $my_desc = new parserDesc; + $desci = ''; + for ($i=0; $i < count($desc); $i++) { + if (isset($desc[$i])) { + $desci .= $desci[$i] . "\n"; + } + } + $my_desc->add($this->getInlineTags($desci)); + } + + if ($this->_pf_internal) { + addError(PDERROR_INTERNAL_NOT_CLOSED); + $this->_pf_internal = false; + } + $this->$dtype->setShortDesc($sdesc); + $this->$dtype->setDesc($my_desc); + unset($my_desc); + //var_dump($this->$dtype); + //exit; + } + + /** + * Process the Long Description of a DocBlock + * + * @param array $desc array of lines containing the description + * with leading asterisk "*" stripped off. + * + * @return void + * @access private + */ + function handleDesc($desc) + { + unset($this->_pv_periodline); + $this->_pf_useperiod = false; + foreach ($desc as $i => $line) { + $line = trim($line); + if (!isset($this->_pv_periodline) && + substr($line, strlen($line) - 1) == '.' + ) { + $this->_pv_periodline = $i; + $this->_pf_useperiod = true; + } + } + if (!isset($this->_pv_periodline)) { + $this->_pv_periodline = 0; + } + if ($this->_pv_periodline > 3) { + $this->_pf_useperiod = false; + } else { + for ($i = 0; $i < $this->_pv_periodline; $i++) { + if (strlen($desc[$i]) == 0 && isset($desc[$i - 1]) && + strlen($desc[$i - 1]) + ) { + $this->_pv_periodline = $i; + } + } + } + for ($i=0;$i <= $this->_pv_periodline && $i < count($desc);$i++) { + if (!strlen(trim($desc[$i]))) { + $this->_pf_useperiod = false; + } + } + // figure out the shortdesc + if ($this->_pf_useperiod === false) { + // use the first non blank line for short desc + for ($i = 0; $i < count($desc); $i++) { + if (strlen($desc[$i]) > 0) { + $this->_pv_periodline = $i; + $i = count($desc); + } + } + + // 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($desc) > 4) { + $max = 4; + } else { + $max = count($desc); + } + + for ($i = $this->_pv_periodline; $i < $max; $i++) { + if (strlen(trim($desc[$i])) == 0) { + $this->_pv_periodline = $i; + $i = $max; + } + } + } + + $dtype = $this->_pv_dtype; + if ($dtype == '_pv_docblock') { + $sdesc = new parserDesc; + $desci = ''; + for ($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++ + ) { + $desci .= $desc[$i] . "\n"; + } + $sdesc->add($this->getInlineTags($desci)); + $this->_pv_periodline++; + + $my_desc = new parserDesc; + if (isset($this->_pv_dtemplate)) { + // copy template values if not overridden + if (!$this->_pv_docblock->getExplicitPackage()) { + if ($p = $this->_pv_dtemplate->getKeyword('package')) { + $this->_pv_docblock->addKeyword('package', $p); + $this->_pv_docblock->setExplicitPackage(); + } + if ($p = $this->_pv_dtemplate->getKeyword('category')) { + $this->_pv_docblock->addKeyword('category', $p); + $this->_pv_docblock->setExplicitCategory(); + } + if ($p = $this->_pv_dtemplate->getKeyword('subpackage')) { + $this->_pv_docblock->addKeyword('subpackage', $p); + } + } + $tags = $this->_pv_dtemplate->listTags(); + foreach ($tags as $tag) { + $this->_pv_docblock->addTag($tag); + } + if (!count($this->_pv_docblock->params)) { + $this->_pv_docblock->params = $this->_pv_dtemplate->params; + } + if (!$this->_pv_docblock->return) { + $this->_pv_docblock->return = $this->_pv_dtemplate->return; + } + if (!$this->_pv_docblock->var) { + $this->_pv_docblock->var = $this->_pv_dtemplate->var; + } + $my_desc->add($this->_pv_dtemplate->sdesc); + $my_desc->add($this->_pv_dtemplate->desc); + } + //echo "i = ".$this->_pv_periodline."; i < " . count($desc) . "\n"; + $desci = ''; + for ($i = $this->_pv_periodline; $i < count($desc); $i++) { + // the line will not be set if it doesn't start with a * + if (isset($desc[$i])) { + $desci .= $desc[$i] . "\n"; + } + } + $my_desc->add($this->getInlineTags($desci)); + } else { + // this is a docblock template + $sdesc = new parserDesc; + $desci = ''; + for ($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++ + ) { + if (isset($desc[$i])) { + $desci .= $desc[$i] . "\n"; + } + } + $sdesc->add($this->getInlineTags($desci)); + $this->_pv_periodline++; + + $my_desc = new parserDesc; + $desci = ''; + for ($i=$this->_pv_periodline; $i < count($desc); $i++) { + if (isset($desc[$i])) { + $desci .= $desc[$i] . "\n"; + } + } + $my_desc->add($this->getInlineTags($desci)); + } + if ($this->_pf_internal) { + addError(PDERROR_INTERNAL_NOT_CLOSED); + $this->_pf_internal = false; + } + $this->$dtype->setShortDesc($sdesc); + $this->$dtype->setDesc($my_desc); + unset($my_desc); + //var_dump($this->$dtype); + //exit; + } + + /** + * Process the tags of a DocBlock + * + * @param array $tags array of lines that contain all @tags + * + * @return void + * @access private + */ + function handleTags($tags) + { + $newtags = array(); + $curtag = ''; + for ($i=0; $i < count($tags); $i++) { + if (strpos(trim($tags[$i]), '@') === 0) { + $tags[$i] = ltrim($tags[$i]); + } + if (substr($tags[$i], 0, 1) == '@' && substr($tags[$i], 0, 2) != '@ ' + ) { + // start a new tag + if (!empty($curtag)) { + $newtags[] = $curtag; + } + $curtag = $tags[$i]; + } else { + $curtag .= "\n" . $tags[$i]; + } + } + if (!empty($curtag)) { + $newtags[] = $curtag; + } + foreach ($newtags as $tag) { + $x = explode(' ', str_replace("\t", ' ', $tag)); + $tagname = trim(substr(array_shift($x), 1)); + $restoftag = $x; + if (isset($this->tagHandlers[$tagname])) { + $handle = $this->tagHandlers[$tagname]; + } else { + $handle = $this->tagHandlers['*']; + } + $this->$handle($tagname, $restoftag); + } + } + + /** + * Process all inline tags in text, and convert them to their abstract + * object representations. + * + * @param string|array $value complete code to search for inline tags, + * if an array, it's an array of strings + * + * @return parserStringWithInlineTags + * @access private + */ + function getInlineTags($value) + { + if (is_array($value)) { + $value = join("\n", $value); + } + global $_phpDocumentor_setting; + $priv = (isset($_phpDocumentor_setting['parseprivate']) && + $_phpDocumentor_setting['parseprivate'] == 'on'); + $a = new parserStringWithInlineTags(); + if (!$priv && $this->_pf_internal) { + if ($x = strpos($value, '}}')) { + $x = strrpos($value, '}}'); + $value = substr($value, $x + 1); + $this->_pf_internal = false; + } else { + $value = ''; + } + } elseif ($this->_pf_internal) { + if ($x = strpos($value, '}}')) { + $x = strrpos($value, '}}'); + $value = substr($value, 0, $x) . substr($value, $x+2); + } + } + $save = $value; + $value = explode('{@', $value); + $newval = array(); + if ($priv || (!$priv && !$this->_pf_internal)) { + // ignore anything between {@internal and }} + $a->add($value[0]); + } + for ($i=1; $i < count($value); $i++) { + if (substr($value[$i], 0, 1) == '}') { + if ($priv || (!$priv && !$this->_pf_internal)) { + // ignore anything between {@internal and }} + $a->add('{@' . substr($value[$i], 1)); + } + } elseif (substr($value[$i], 0, 2) == '*}') { + // used for inserting */ in code examples + if ($priv || (!$priv && !$this->_pf_internal)) { + // ignore anything between {@internal and }} + $a->add('*/' . substr($value[$i], 2)); + } + } else { + $save = $value[$i]; + $value[$i] = preg_split("/[\t ]/", str_replace("\t", ' ', $value[$i])); + $word = trim(array_shift($value[$i])); + $val = join(' ', $value[$i]); + if (trim($word) == 'internal') { + if ($this->_pf_internal) { + addErrorDie(PDERROR_NESTED_INTERNAL); + } + $this->_pf_internal = true; + $value[$i] = substr($save, strlen('internal') + 1); + if (!$value[$i]) { + // substr can set this to false + $value[$i] = ''; + } + if (strpos($value[$i], '}}') !== false) { + $x = strrpos($value[$i], '}}'); + // strip internal and cycle as if it were normal text. + $startval = substr($value[$i], 0, $x); + if ($priv) { + $a->add($startval); + } + $value[$i] = substr($value[$i], $x + 2); + if (!$value[$i]) { + $value[$i] = ''; + } + $this->_pf_internal = false; + $a->add($value[$i]); + continue; + } elseif ($priv) { + $a->add($value[$i]); + } + continue; + } + if (in_array(str_replace('}', '', trim($word)), + $this->allowableInlineTags) + ) { + if (strpos($word, '}')) { + $res = substr($word, strpos($word, '}')); + $word = str_replace('}', '', trim($word)); + $val = $res . $val; + } + if ($priv || (!$priv && !$this->_pf_internal)) { + // ignore anything between {@internal and }} + if ($word == 'source') { + $this->_pf_get_source = true; + } + } + $val = explode('}', $val); + if (count($val) == 1) { + addError(PDERROR_UNTERMINATED_INLINE_TAG, + $word, '', $save); + } + $rest = $val; + $val = array_shift($rest); + $rest = join('}', $rest); + if (isset($this->inlineTagHandlers[$word])) { + $handle = $this->inlineTagHandlers[$word]; + } else { + $handle = $this->inlineTagHandlers['*']; + } + $val = $this->$handle($word, $val); + if ($priv || (!$priv && !$this->_pf_internal)) { + // ignore anything between {@internal and }} + $a->add($val); + } + if ($this->_pf_internal) { + if (($x = strpos($rest, '}}')) !== false) { + $value[$i] = $rest; + $startval = substr($value[$i], 0, $x); + if ((false !== $startval) && $priv) { + $a->add($startval); + } + $value[$i] = substr($value[$i], $x + 2); + if (!$value[$i]) { + $value[$i] = ''; + } + $this->_pf_internal = false; + $a->add($value[$i]); + } else { + $rest = explode('}}', $rest); + if ($priv) { + $a->add(array_shift($rest)); + } + $this->_pf_internal = false; + // try this line again without internal + $value[$i--] = join('}}', $rest); + continue; + } + } else { + $a->add($rest); + } + } else { + $val = $word . ' ' . $val; + if ($priv || (!$priv && !$this->_pf_internal)) { + // ignore anything between {@internal and }} + $a->add('{@' . $val); + } + } + } + } + return $a; + } + + /**#@+ + * @param string $name name of the tag + * @param string $value any parameters passed to the inline tag + * @access private + */ + /** + * Most inline tags require no special processing + * + * @return mixed some type of parser_*_InlineTag object + */ + function handleDefaultInlineTag($name, $value) + { + $tag = 'parser' . ucfirst($name) . 'InlineTag'; + return new $tag($value, $value); + } + + /** + * Handle the inline {@}link} tag + * + * @return parserLinkInlineTag + * @tutorial tags.inlinelink.pkg + */ + function handleLinkInlineTag($name, $value) + { + // support hyperlinks of any protocol + if (is_numeric(strpos($value, '://')) || + (strpos(trim($value), 'mailto:') === 0) + ) { + $value = str_replace('\\,', '###commanana####', $value); + if (strpos($value, ',')) { + $val = new parserLinkInlineTag($value, $value); + } elseif (strpos(trim($value), ' ')) { + // if there is more than 1 parameter, + // the stuff after the space is the hyperlink text + $i1 = strpos(trim($value), ' ') + 1; + $link = substr(trim($value), 0, $i1 - 1); + $text = substr(trim($value), $i1); + $val = new parserLinkInlineTag($link, $text); + } else { + $val = new parserLinkInlineTag($value, $value); + } + } else { + $value = str_replace('\\,', '###commanana####', $value); + if (!strpos($value, ',')) { + $testp = explode('#', $value); + if (count($testp) - 1) { + $val = new parserLinkInlineTag($value, $testp[1]); + } else { + $val = new parserLinkInlineTag($value, $value); + } + } else { + $val = new parserLinkInlineTag($value, $value); + } + } + return $val; + } + /**#@-*/ + + /**#@+ + * @access private + * @param string $name name of tag + * @param array $value all words in the tag that were separated by a space ' ' + * @return void + */ + /** + * Most tags only need the value as a string + * + * @uses getInlineTags() all tag handlers check their values for inline tags + * @uses parserDocBlock::addKeyword() + */ + function defaultTagHandler($name, $value) + { + $dtype = $this->_pv_dtype; + $this->$dtype->addKeyword($name, $this->getInlineTags(join(' ', $value))); + } + + /** + * handles the @example tag + * + * @tutorial tags.example.pkg + * @uses parserDocBlock::addExample() + */ + function exampleTagHandler($name, $value) + { + $dtype = $this->_pv_dtype; + $this->$dtype->addExample($this->getInlineTags(join(' ', $value)), + $this->_path); + } + + /** + * handles the @filesource tag + * + * @tutorial tags.filesource.pkg + * @uses phpDocumentorTWordParser::getFileSource() retrieves the source for + * use in the @filesource tag + * @uses parserDocBlock::addFileSource() + */ + function filesourceTagHandler($name, $value) + { + $dtype = $this->_pv_dtype; + $this->$dtype->addFileSource($this->_path, $this->_wp->getFileSource()); + } + + /** + * handles the @uses tag + * + * @tutorial tags.uses.pkg + * @uses parserDocBlock::addUses() + */ + function usesTagHandler($name, $value) + { + $dtype = $this->_pv_dtype; + $seel = ''; + while ($seel == '' && count($value)) { + $seel = array_shift($value); + } + $this->$dtype->addUses($this->getInlineTags($seel), + $this->getInlineTags(join(' ', $value))); + } + + /** + * handles the @author tag + * + * @tutorial tags.author.pkg + * @uses parserDocBlock::addKeyword() + */ + function authorTagHandler($name, $value) + { + $dtype = $this->_pv_dtype; + $value = join(' ', $value); + if ((strpos($value, '<') !== false) && (strpos($value, '>') !== false)) { + $email = substr($value, + strpos($value, '<') + 1, + strpos($value, '>') - strpos($value, '<') - 1); + $value = str_replace('<' . $email . '>', + '<{@link mailto:' . $email . ' ' . $email . '}>', + $value); + } + $this->$dtype->addKeyword('author', $this->getInlineTags($value)); + } + + /** + * handles the @package tag + * + * @tutorial tags.package.pkg + * @uses parserDocBlock::setExplicitPackage() + */ + function packageTagHandler($name, $value) + { + if (count($value) && empty($value[0])) { + $found = false; + // CRB - I believe this loop is correct in not having a body... + // I think it is only to determine the $i value needed + // by the one array_splice() call... + for ($i=0; $i < count($value) && !strlen($value[$i]); $i++); + array_splice($value, 0, $i); + } + $this->defaultTagHandler($name, $value); + $dtype = $this->_pv_dtype; + $this->$dtype->setExplicitPackage(); + } + + /** + * handles the @category tag + * + * @tutorial tags.category.pkg + * @uses parserDocBlock::setExplicitCategory() + */ + function categoryTagHandler($name, $value) + { + if (count($value) && empty($value[0])) { + $found = false; + // CRB - I believe this loop is correct in not having a body... + // I think it is only to determine the $i value needed + // by the one array_splice() call... + for ($i=0; $i < count($value) && !strlen($value[$i]); $i++); + array_splice($value, 0, $i); + } + $this->defaultTagHandler($name, $value); + $dtype = $this->_pv_dtype; + $this->$dtype->setExplicitCategory(); + } + + /** + * handles the @global tag + * + * @tutorial tags.global.pkg + * @uses parserDocBlock::addFuncGlobal() + */ + function globalTagHandler($name, $value) + { + $info = $this->retrieveType($value, true); + if (!$info) { + addError(PDERROR_MALFORMED_TAG, '@global'); + } + $type = $info['type']; + $var = $info['var']; + $desc = $info['desc']; + $dtype = $this->_pv_dtype; + if (!$var && empty($desc)) { + if ($type{0} == '$') { + addError(PDERROR_MALFORMED_GLOBAL_TAG); + } + return $this->$dtype->addFuncGlobal($type, + new parserStringWithInlineTags); + } + if ($var) { + // global define + $this->_pv_global_type = $type; + if (!empty($desc)) { + $var .= ' '.$desc; + } + $this->findGlobal(trim($var)); + } elseif (!empty($desc)) { + // function global + if ($type{0} == '$') { + addError(PDERROR_MALFORMED_GLOBAL_TAG); + } + $this->$dtype->addFuncGlobal($type, $this->getInlineTags($desc)); + } else { + addError(PDERROR_MALFORMED_GLOBAL_TAG); + } + } + + /** + * handles the @staticvar tag + * + * @tutorial tags.staticvar.pkg + * @uses parserDocBlock::addStaticVar() + */ + function staticvarTagHandler($name, $value) + { + $info = $this->retrieveType($value, true); + if (!$info) { + addError(PDERROR_MALFORMED_TAG, '@staticvar'); + } + $type = $info['type']; + $var = $info['var']; + $desc = $info['desc']; + $dtype = $this->_pv_dtype; + if (!$var && empty($desc)) { + $this->$dtype->addStaticVar(null, $type, + new parserStringWithInlineTags); + } else { + if ($var) { + $this->$dtype->addStaticVar($var, $type, + $this->getInlineTags($desc)); + } else { + $this->$dtype->addStaticVar(null, $type, + $this->getInlineTags($desc)); + } + } + } + + /** + * handles the @param tag + * + * @tutorial tags.param.pkg + * @uses parserDocBlock::addParam() + */ + function paramTagHandler($name, $value) + { + $info = $this->retrieveType($value, true); + if (!$info) { + addError(PDERROR_MALFORMED_TAG, '@param'); + return; + } + $type = $info['type']; + $var = $info['var']; + $desc = $info['desc']; + $dtype = $this->_pv_dtype; + if (!$var && empty($desc)) { + $this->$dtype->addParam(null, $type, new parserStringWithInlineTags); + } else { + if ($var) { + $this->$dtype->addParam($var, $type, $this->getInlineTags($desc)); + } else { + $this->$dtype->addParam(null, $type, $this->getInlineTags($desc)); + } + } + } + + /** + * handles the @return tag + * + * @tutorial tags.return.pkg + * @uses parserDocBlock::addReturn() + */ + function returnTagHandler($name, $value) + { + $info = $this->retrieveType($value, true); + if (!$info) { + addError(PDERROR_MALFORMED_TAG, '@return'); + return; + } + $type = $info['type']; + $desc = $info['desc']; + $dtype = $this->_pv_dtype; + $this->$dtype->addReturn($type, $this->getInlineTags($desc)); + } + + /** + * handles the @var tag + * + * @tutorial tags.var.pkg + * @uses parserDocBlock::addVar() + */ + function varTagHandler($name, $value) + { + $info = $this->retrieveType($value, true); + if (!$info) { + addError(PDERROR_MALFORMED_TAG, '@var'); + } + $type = $info['type']; + $desc = $info['desc']; + $dtype = $this->_pv_dtype; + $this->$dtype->addVar($type, $this->getInlineTags($desc)); + } + + /** + * Handles @property(-read or -write) and @method magic tags + * + * @tutorial tags.method.pkg + * @tutorial tags.property.pkg + * @uses parserDocBlock::addProperty() + */ + function propertyTagHandler($name, $value) + { + $info = $this->retrieveType($value, true); + if (!$info) { + addError(PDERROR_MALFORMED_TAG, '@' . $name); + } + $type = $info['type']; + $var = $info['var']; + $desc = $info['desc']; + $dtype = $this->_pv_dtype; + $this->$dtype->addProperty($name, $var, $type, $this->getInlineTags($desc)); + } + /**#@-*/ + + /**#@+ + * @access private + */ + + /** + * Retrieve the type portion of a @tag type description + * + * Tags like @param, @return and @var all have a PHP type portion in their + * description. Since the type may contain the expression "object blah" + * where blah is a classname, it makes parsing out the type field complex. + * + * Even more complicated is the case where a tag variable can contain + * multiple types, such as object blah|object blah2|false, and so this + * method handles these cases. + * + * @param array $value array of words that were separated by spaces + * @param bool $checkforvar flag to determine whether to check for the end of a + * type is defined by a $varname + * + * @return bool|array FALSE if there is no value, + * or an array of Format: + * <pre> + * array( + * 'type' => string, + * 'var' => false|string variable name, + * 'desc' => rest of the tag + * ) + * </pre> + */ + function retrieveType($value, $checkforvar = false) + { + if (!count($value)) { + return false; + } + $result = array(); + $types = ''; + // remove empty entries resulting from extra spaces between @tag and type + $this->_removeWhiteSpace($value, 0); + $index = 0; + if (trim($value[0]) == 'object') { + $types .= array_shift($value) . ' '; + $this->_removeWhiteSpace($value, 0); + if (!count($value)) { + // was just passed "object" + $result = array('type' => rtrim($types), 'desc' => ''); + if ($checkforvar) { + $result['var'] = false; + } + return $result; + } + if ($value[0]{0} == '$' || substr($value[0], 0, 2) == '&$') { + // was just passed "object" and the next thing is a variable name + $result['var'] = trim($value[0]); + $result['type'] = 'object'; + array_shift($value); + $result['desc'] = join(' ', $value); + return $result; + } + } + $done = false; + do { + // this loop checks for type|type|type + // and for type|object classname|type|object classname2 + if (strpos($value[0], '|')) { + $temptypes = explode('|', $value[0]); + while (count($temptypes)) { + $type = array_shift($temptypes); + $types .= $type; + if (count($temptypes)) { + $types .= '|'; + } + } + if (trim($type) == 'object') { + $types .= ' '; + $this->_removeWhiteSpace($value, 0); + } else { + $done = true; + } + array_shift($value); + if (isset ($value[0]) && strlen($value[0]) && ($value[0]{0} == '$' || + substr($value[0], 0, 2) == '&$') + ) { + // was just passed "object" and the next thing is a variable name + $result['var'] = trim($value[0]); + $result['type'] = $types; + array_shift($value); + $result['desc'] = join(' ', $value); + return $result; + } + } else { + $types .= $value[0]; + array_shift($value); + $done = true; + } + } while (!$done && count($value)); + $result['type'] = rtrim($types); + $this->_removeWhiteSpace($value, 0); + if ($checkforvar) { + if (!count($value)) { + $result['var'] = false; + } else { + /* + * check for: + * variable name ($) + * var passed by reference (&$) + * method name (only used by magic method) + */ + if (substr($value[0], 0, 1) == '$' || + substr($value[0], 0, 2) == '&$' || + substr($value[0], -2, 2) == '()' + ) { + $result['var'] = trim($value[0]); + array_shift($value); + } else { + $result['var'] = false; + } + } + } + $result['desc'] = join(' ', $value); + return $result; + } + + /** + * remove whitespace from a value + * + * @param array &$value array of string + * @param integer $index index to seek non-whitespace to + * + * @return void + */ + function _removeWhiteSpace(&$value, $index) + { + if (count($value) > $index && empty($value[$index])) { + $found = false; + // CRB - I believe this loop is correct in not having a body... + // I think it is only to determine the $i value needed + // by the one array_splice() call... + for ($i=$index; $i < count($value) && !strlen($value[$i]); $i++); + array_splice($value, $index, $i - $index); + } + } + + /** + * Retrieve all the tokens that represent the definition of the global variable + * + * {@source} + * + * @param string $name the global variable to find + * + * @return void + */ + function findGlobal($name) + { + $tokens = token_get_all('<?php ' . $name); + $tokens = array_slice($tokens, 1); + $this->_wp->findGlobal($tokens); + $this->_pv_findglobal = $name; + } + + /** + * this function checks whether parameter $word + * is a token for pushing a new event onto the Event Stack. + * + * @param string $word the word to check + * @param int $pevent the event to push + * + * @return mixed returns false, or the event number + */ + function checkEventPush($word, $pevent) + { + if (is_array($word) && $word[0] == T_STRING) { + $word = $word[1]; + } + if (is_array($word)) { + $pushEvent = &$this->tokenpushEvent; + $word = $word[0]; + } else { + $pushEvent = &$this->wordpushEvent; + $word = strtolower($word); + } + $e = false; + if (isset($pushEvent[$pevent])) { + if (isset($pushEvent[$pevent][$word])) { + $e = $pushEvent[$pevent][$word]; + } + } + if ($e) { + $this->_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. + * + * @param string $word the word to check + * @param int $pevent the event to pop + * + * @return mixed returns false, or the event number popped off of the stack + */ + function checkEventPop($word, $pevent) + { + if (is_array($word) && $word[0] == T_STRING) { + $word = $word[1]; + } + if (is_array($word)) { + $popEvent = &$this->tokenpopEvent; + $word = $word[0]; + } else { + $popEvent = &$this->wordpopEvent; + $word = strtolower($word); + } + if (!isset($popEvent[$pevent])) { + return false; + } + if (in_array($word, $popEvent[$pevent])) { + return $this->_event_stack->popEvent(); + } else { + return false; + } + } + + /** + * returns the token from the $word array + * + * @param mixed $word the token array + * + * @return mixed the token from the array, + * or FALSE if it's not an array + */ + function getToken($word) + { + if (is_array($word)) { + return $word[0]; + } + return false; + } + + /** + * setup the parser tokens, and the pushEvent/popEvent arrays + * + * @return void + * @see $tokens, $pushEvent, $popEvent + */ + function setupStates() + { + unset($this->_wp); + $this->_wp = new phpDocumentorTWordParser; + $this->_pv_class = null; + $this->_pv_cur_class = null; + $this->_pv_define = null; + $this->_pv_define_name = null; + $this->_pv_define_value = null; + $this->_pv_define_params_data = null; + $this->_pv_dtype = null; + $this->_pv_docblock = null; + $this->_pv_dtemplate = null; + $this->_pv_func = null; + $this->_pv_findglobal = null; + $this->_pv_global_name = null; + $this->_pv_global_val = null; + $this->_pv_globals = null; + $this->_pv_global_count = null; + $this->_pv_include_params_data = null; + $this->_pv_include_name = null; + $this->_pv_include_value = null; + $this->_pv_linenum = null; + $this->_pv_periodline = null; + $this->_pv_paren_count = 0; + $this->_pv_statics = null; + $this->_pv_static_count = null; + $this->_pv_static_val = null; + $this->_pv_quote_data = null; + $this->_pv_function_data = null; + $this->_pv_var = null; + $this->_pv_varname = null; + $this->_pv_const = null; + $this->_pv_constname = null; + $this->_pv_function_param_type = null; + $this->_pf_definename_isset = false; + $this->_pf_includename_isset = false; + $this->_pf_get_source = false; + $this->_pf_getting_source = false; + $this->_pf_in_class = false; + $this->_pf_in_define = false; + $this->_pf_in_global = false; + $this->_pf_in_include = false; + $this->_pf_in_var = false; + $this->_pf_in_const = false; + $this->_pf_funcparam_val = false; + $this->_pf_quote_active = false; + $this->_pf_reset_quote_data = true; + $this->_pf_useperiod = false; + $this->_pf_var_equals = false; + $this->_pf_const_equals = false; + $this->_event_stack = new EventStack; + } + + /** + * Creates the state arrays + * + * @return void + */ + function setupEventStates() + { + if (!defined('T_DOC_COMMENT')) { + define('T_DOC_COMMENT', T_DOC_COMMENT); + } + /**************************************************************/ + + $this->wordpushEvent[PARSER_EVENT_LOGICBLOCK] = + array( + "{" => PARSER_EVENT_LOGICBLOCK, + '"' => PARSER_EVENT_QUOTE, + ); + $this->tokenpushEvent[PARSER_EVENT_LOGICBLOCK] = + array( + T_GLOBAL => PARSER_EVENT_FUNC_GLOBAL, + T_STATIC => PARSER_EVENT_STATIC_VAR, + T_START_HEREDOC => PARSER_EVENT_EOFQUOTE, + T_CURLY_OPEN => PARSER_EVENT_LOGICBLOCK, + T_DOLLAR_OPEN_CURLY_BRACES => PARSER_EVENT_LOGICBLOCK, + ); + + $this->wordpopEvent[PARSER_EVENT_LOGICBLOCK] = array("}"); + $this->tokenpopEvent[PARSER_EVENT_LOGICBLOCK] = array(T_CURLY_OPEN); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_NOEVENTS] = + array( + T_OPEN_TAG => PARSER_EVENT_PHPCODE, + ); + + /**************************************************************/ + + $this->tokenpopEvent[PARSER_EVENT_EOFQUOTE] = array(T_END_HEREDOC); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_PHPCODE] = + array( + T_FUNCTION => PARSER_EVENT_FUNCTION, + T_ABSTRACT => PARSER_EVENT_ACCESS_MODIFIER, + T_CLASS => PARSER_EVENT_CLASS, + T_INTERFACE => PARSER_EVENT_CLASS, + T_INCLUDE_ONCE => PARSER_EVENT_INCLUDE, + T_INCLUDE => PARSER_EVENT_INCLUDE, + T_REQUIRE => PARSER_EVENT_INCLUDE, + T_REQUIRE_ONCE => PARSER_EVENT_INCLUDE, + T_COMMENT => PARSER_EVENT_DOCBLOCK, + T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK, + //"/**#@+" => PARSER_EVENT_DOCBLOCK_TEMPLATE, + //"/**#@-*/" => PARSER_EVENT_END_DOCBLOCK_TEMPLATE, + T_CLOSE_TAG => PARSER_EVENT_OUTPHP, + ); + $this->wordpushEvent[PARSER_EVENT_PHPCODE] = + array( + "define" => PARSER_EVENT_DEFINE, + ); + /**************************************************************/ + + $this->tokenpopEvent[PARSER_EVENT_OUTPHP] = array(T_OPEN_TAG); + /**************************************************************/ + + $this->wordpushEvent[PARSER_EVENT_FUNCTION] = + array( + '{' => PARSER_EVENT_LOGICBLOCK, + '(' => PARSER_EVENT_FUNCTION_PARAMS, + ); + $this->tokenpushEvent[PARSER_EVENT_FUNCTION] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + ); + + $this->wordpopEvent[PARSER_EVENT_FUNCTION] = array("}",';'); + /**************************************************************/ + + $this->wordpopEvent[PARSER_EVENT_QUOTE] = array('"'); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_FUNCTION_PARAMS] = + array( + T_VARIABLE => PARSER_EVENT_FUNCTION_PARAM_VAR, + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + ); + $this->wordpopEvent[PARSER_EVENT_FUNCTION_PARAMS] = array(")"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_FUNCTION_PARAM_VAR] = + array( + T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE, + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + T_ARRAY => PARSER_EVENT_ARRAY, + ); + $this->wordpushEvent[PARSER_EVENT_FUNCTION_PARAM_VAR] = + array( + '"' => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_QUOTE, + ); + $this->wordpopEvent[PARSER_EVENT_FUNCTION_PARAM_VAR] = array(",", ")"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_ARRAY] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + ); + $this->wordpopEvent[PARSER_EVENT_ARRAY] = array(")"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_VAR_ARRAY] = + array( + T_COMMENT => PARSER_EVENT_VAR_ARRAY_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_VAR_ARRAY_COMMENT, + ); + $this->wordpopEvent[PARSER_EVENT_VAR_ARRAY] = array(")"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_FUNC_GLOBAL] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + ); + $this->wordpopEvent[PARSER_EVENT_FUNC_GLOBAL] = array(";"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_STATIC_VAR] = + array( + T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE, + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + ); + $this->wordpushEvent[PARSER_EVENT_STATIC_VAR] = + array( + "=" => PARSER_EVENT_STATIC_VAR_VALUE, + ); + $this->wordpopEvent[PARSER_EVENT_STATIC_VAR] = array(";"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_STATIC_VAR_VALUE] = + array( + T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE, + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + T_ARRAY => PARSER_EVENT_ARRAY, + ); + $this->wordpushEvent[PARSER_EVENT_STATIC_VAR_VALUE] = + array( + '"' => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_QUOTE, + ); + $this->wordpopEvent[PARSER_EVENT_STATIC_VAR_VALUE] = array(";",","); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_DEFINE] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE, + ); + $this->wordpushEvent[PARSER_EVENT_DEFINE] = + array( + "(" => PARSER_EVENT_DEFINE_PARAMS, + ); + $this->wordpopEvent[PARSER_EVENT_DEFINE] = array(";"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_INCLUDE] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + ); + $this->wordpushEvent[PARSER_EVENT_INCLUDE] = + array( + "(" => PARSER_EVENT_INCLUDE_PARAMS, + ); + $this->wordpopEvent[PARSER_EVENT_INCLUDE] = array(";"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_DEFINE_PARAMS] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + T_START_HEREDOC => PARSER_EVENT_EOFQUOTE, + ); + $this->wordpushEvent[PARSER_EVENT_DEFINE_PARAMS] = + array( + "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS, + '"' => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_QUOTE, + ); + $this->wordpopEvent[PARSER_EVENT_DEFINE_PARAMS] = array(")"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_INCLUDE_PARAMS] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + ); + $this->wordpushEvent[PARSER_EVENT_INCLUDE_PARAMS] = + array( + "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS, + ); + $this->wordpopEvent[PARSER_EVENT_INCLUDE_PARAMS] = array(")"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + ); + $this->wordpushEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] = + array( + "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS, + '"' => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_QUOTE, + ); + $this->wordpopEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] = array(")"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + ); + $this->wordpushEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] = + array( + "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS, + ); + $this->wordpopEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] = array(")"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_VAR] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + T_ARRAY => PARSER_EVENT_VAR_ARRAY, + ); + $this->wordpopEvent[PARSER_EVENT_VAR] = array(";"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_CLASS_CONSTANT] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + T_ARRAY => PARSER_EVENT_VAR_ARRAY, + ); + $this->wordpopEvent[PARSER_EVENT_CLASS_CONSTANT] = array(";"); + /**************************************************************/ + + $this->wordpopEvent[PARSER_EVENT_IMPLEMENTS] = array('{'); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_CLASS] = + array( + T_ABSTRACT => PARSER_EVENT_ACCESS_MODIFIER, + T_PUBLIC => PARSER_EVENT_ACCESS_MODIFIER, + T_PRIVATE => PARSER_EVENT_ACCESS_MODIFIER, + T_PROTECTED => PARSER_EVENT_ACCESS_MODIFIER, + T_STATIC => PARSER_EVENT_ACCESS_MODIFIER, + T_IMPLEMENTS => PARSER_EVENT_IMPLEMENTS, + T_CONST => PARSER_EVENT_CLASS_CONSTANT, + T_FUNCTION => PARSER_EVENT_FUNCTION, + T_VAR => PARSER_EVENT_VAR, + T_COMMENT => PARSER_EVENT_DOCBLOCK, + T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK, + T_CLOSE_TAG => PARSER_EVENT_OUTPHP, + ); + $this->wordpopEvent[PARSER_EVENT_CLASS] = array("}"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_DEFINE_GLOBAL] = + array( + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + ); + $this->wordpushEvent[PARSER_EVENT_DEFINE_GLOBAL] = + array( + "=" => PARSER_EVENT_GLOBAL_VALUE, + ); + $this->wordpopEvent[PARSER_EVENT_DEFINE_GLOBAL] = array(";"); + /**************************************************************/ + + $this->tokenpushEvent[PARSER_EVENT_GLOBAL_VALUE] = + array( + T_ARRAY => PARSER_EVENT_ARRAY, + T_COMMENT => PARSER_EVENT_COMMENT, + T_DOC_COMMENT => PARSER_EVENT_COMMENT, + T_START_HEREDOC => PARSER_EVENT_EOFQUOTE, + ); + $this->wordpushEvent[PARSER_EVENT_GLOBAL_VALUE] = + array( + '"' => PARSER_EVENT_QUOTE, + "'" => PARSER_EVENT_QUOTE, + ); + $this->wordpopEvent[PARSER_EVENT_GLOBAL_VALUE] = array(";"); + } + + /** + * initializes all the setup + * + * @param mixed &$data the data parser (?) + * + * @return void + */ + function configWordParser(&$data) + { + $this->_wp->setup($data); + $this->_wp->setWhitespace(false); + } + + /**#@-*/ + +} +?> |