Source for file phpDocumentorTParser.inc
Documentation is available at phpDocumentorTParser.inc
* tokenizer extension-based parser for PHP code
* phpDocumentor :: automatic documentation generator
* Copyright (c) 2002-2006 Gregory Beaver
* 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
* 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
* @copyright 2002-2006 Gregory Beaver
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version CVS: $Id: phpDocumentorTParser.inc,v 1.18 2006/08/17 03:13:39 cellog Exp $
* @link http://www.phpdoc.org
* @link http://pear.php.net/PhpDocumentor
* Tokenizer-based parser for PHP source code
* @version $Revision: 1.18 $
* last event triggered before the current event
* full path of the currently parsed file
var $_pv_define_params_data;
var $_pv_include_params_data;
var $_pv_paren_count = 0;
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_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
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',
'*' => 'handleDefaultInlineTag',
'link' => 'handleLinkInlineTag',
$this->allowableTags = $GLOBALS['_phpDocumentor_tags_allowed'];
$this->allowableInlineTags = $GLOBALS['_phpDocumentor_inline_doc_tags_allowed'];
$this->tagHandlers['author'] = 'authorTagHandler';
$this->tagHandlers['filesource'] = 'filesourceTagHandler';
* @param string $parse_data
* @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
function parse (&$parse_data, $path, $base = 0, $packages = false)
global $_phpDocumentor_options;
// initialize variables so E_ALL error_reporting doesn't complain
$page->setSource($this->_wp->getFileSource());
$page->setPackageOutput($packages);
//$name = str_replace("/","_",dirname($path)) . "_" . array_shift(explode(".",$page->getFile()));
// if base is '', drive letter is present in windows
if ($temploc == $_phpDocumentor_options['Program_Root'] . PATH_DELIMITER) $temploc .= $path;
$page->setSourceLocation($source_location);
$pevent = $this->_event_stack->getEvent();
$this->_last_pevent = $lpevent;
$this->_pv_last_word = $word;
$word = $this->_wp->getWord();
if (isset ($this->_pv_findglobal) && $word == $this->_pv_findglobal)
$this->_last_pevent = $pevent;
// in wordparser, have to keep track of lines
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 (0)//PHPDOCUMENTOR_DEBUG == true)
} else echo "|" . $this->_pv_last_word;
echo $this->_wp->getPos() . ": ";
echo "|\n-------------------\n\n\n";
if (0)//$this->_pf_getting_source && ($pevent == PARSER_EVENT_DOCBLOCK) || ($pevent == PARSER_EVENT_NOEVENTS))
$this->$handle($word, $pevent);
debug('WARNING: possible error, no handler for event number '. $pevent);
die("FATAL ERROR, recursion limit reached");
} while (!($word === false));
function handleComment($word, $pevent)
* this handler recognizes the <code><?</code> php processor directive, and begins parsing php code
function handlePhpCode($word, $pevent)
if (isset ($this->_pv_findglobal) && $e)
$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)
$this->_pv_global_count++ ;
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++;
$this->_pv_globals[$this->_pv_global_count] .= $word;
* handler for STATIC_VAR.
* this handler recognizes "static $var1, $var2 = 6" declarations in a function, and parses them
function handleStaticVar($word, $pevent)
$this->_pv_static_count++ ;
$this->_pv_static_count++ ;
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++ ;
$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 (!isset ($this->_pv_static_val[$this->_pv_static_count])) $this->_pv_static_val[$this->_pv_static_count] = '';
$this->_pv_static_val[$this->_pv_static_count] .= $this->_pv_quote_data;
unset ($this->_pv_quote_data);
$this->_pv_static_val[$this->_pv_static_count] .= $this->_pv_function_data;
$this->_pv_function_data = '';
$this->_pv_static_val[$this->_pv_static_count] = trim($this->_pv_static_val[$this->_pv_static_count]);
$this->_wp->backupPos($word);
$this->_pv_static_val[$this->_pv_static_count] .= $word;
* Logic Blocks are the stuff between { and } in a function/method. A
* logic block can clearly contain other logic blocks, as in:
* { // 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.
function handleLogicBlock($word, $pevent)
* this handler recognizes function declarations, and parses them. The body
* of the function is parsed by handleLogicBlock()
* @see handleLogicBlock()
function handleFunction($word, $pevent)
$this->_pv_function_data = '';
if (!isset ($this->_pv_func)) $this->_pv_func = false;
$this->_pv_globals = array();
$this->_pv_global_count = $this->_pv_static_count = 0;
unset ($this->_accessModifiers);
if (isset ($this->_accessModifiers))
$this->_pv_func->setModifiers($this->_accessModifiers);
unset ($this->_accessModifiers);
$this->_pv_func->setLineNumber($this->_wp->linenum + 1);
$this->_pv_func->setReturnsReference();
if (is_array($word) && $word[0] == T_STRING)
$this->_pv_func->setName($word[1]);
if ($this->_pv_func->getReturnsReference())
if (is_array($word) && $word[0] == T_STRING)
$this->_pv_func->setName($word[1]);
$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;
unset ($this->_pv_quote_data); // subtle bug fixed by this, sometimes string
// from function body was picked up
// by the next function as a default value
* Helper function for {@link handleFunctionParams()}
* This function adds a new parameter to the parameter list
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;
* handler for FUNCTION_PARAMS.
* this handler recognizes the parameters of a function within parentheses like function(param, param = default_value)
* @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";
{ // end of [typehint ]$param[= defaultval]
$this->endFunctionParam($word);
{ // about to parse the default value
$this->_pf_funcparam_val = true;
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);
$this->_pv_function_data .= $word;
if (!isset ($this->_pv_function_param)) $this->_pv_function_param = '';
if ($word[0] == T_STRING || $word[0] == T_ARRAY)
{ // object or array type hint
$this->_pv_function_param_type = $word[1];
$this->_pv_function_param .= $word;
$this->_wp->setWhiteSpace(true);
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];
* this event handler parses arrays in default values of function and var definitions
function handleArray($word, $pevent)
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->_pv_function_data .= $word[1];
$this->_pv_function_data .= $word;
//echo "function_data = |$this->_pv_function_data|\n";
$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)
$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->_pv_quote_data .= $word;
$this->_pf_quote_active = false;
* 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)
$this->_pv_quote_data = $this->_pv_last_word . $word;
$this->_pf_quote_active = true;
} elseif (!$this->_pf_quote_active)
$this->_pv_quote_data = $this->_pv_last_word[1];
$this->_pv_quote_data .= $word;
$this->_pf_quote_active = false;
* this handler recognizes include/require/include_once/include_once statements, and publishes the
function handleInclude($word, $pevent)
if (!$this->_pf_in_include)
$this->_pv_linenum = $this->_wp->linenum;
$this->_pf_in_include = true;
if (!$this->_pf_includename_isset)
$this->_pf_includename_isset = true;
$w = $this->_pv_last_word;
$this->_pv_include_name = $w;
$this->_pv_include_value = '';
$this->_pv_include_value = $word;
unset ($this->_pv_quote_data);
if (empty($this->_pv_include_params_data))
$this->_pv_include_value .= $word;
$this->_pv_include_params_data = '';
$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->_pf_includename_isset = false;
unset ($this->_pv_include);
unset ($this->_pv_include_name);
unset ($this->_pv_include_value);
unset ($this->_pv_include_params_data);
// include is part of a larger statement
// force ending of include
$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->_pf_includename_isset = 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)
if(!isset ($this->_pv_include_params_data)) $this->_pv_include_params_data = '';
if (!empty($this->_pv_include_params_data))
$this->_pv_include_value = $this->_pv_include_params_data;
$w = $this->_pv_last_word;
$this->_pv_include_value = $w;
$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->_pv_include_params_data .= $word;
* 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->_pf_definename_isset = false;
$this->_pv_define_params_data = '';
unset ($this->_pv_quote_data);
$this->_pf_in_define = false;
$this->_pv_define->setLineNumber($this->_pv_linenum);
$this->_pv_define->setName($this->_pv_define_name);
$this->_pv_define->setValue($this->_pv_define_value);
$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)
if(!isset ($this->_pv_define_params_data)) $this->_pv_define_params_data = '';
$this->_pv_define_params_data .= $this->_pv_quote_data;
unset ($this->_pv_quote_data);
if (!empty($this->_pv_define_params_data))
//echo $this->_pv_define_params_data."\n";
$this->_pv_define_value = $this->_pv_define_params_data;
$w = $this->_pv_last_word;
if (is_array($this->_pv_last_word)) $w = $this->_pv_last_word[1];
$this->_pv_define_value = $w;
$this->_pv_define_value = "";
$this->_pv_define_value = "0";
$this->_pv_define_value = "null";
$this->_pv_define_value = "";
if ($this->_pf_definename_isset)
$this->_pv_define_params_data .= $word;
$this->_pv_define_params_data .= $word;
if (substr($this->_pv_define_params_data,0,1) ==
substr($this->_pv_define_params_data,strlen($this->_pv_define_params_data) - 1) &&
{ // 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);
$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)
$this->_pv_define_params_data .= $this->_pv_quote_data;
unset ($this->_pv_quote_data);
$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 (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();
if ($word[0] == T_VARIABLE) {
// this is a PHP5-style variable with no "var"
$this->_accessModifiers[] = strtolower($this->_pv_last_word[1]);
* this handler parses a class/interface statement
function handleClass($word, $pevent)
if (!$this->_pf_in_class)
$this->_pf_in_class = true;
$this->_pf_interface = true;
$this->_pf_interface = false;
if (!isset ($this->_pv_class)) $this->_pv_class = false;
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];
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()) {
$this->_pv_class->setExtends($word[1]);
//echo $this->wp->getPos() . ": |$word|\n";
$this->_pv_class->setEndLineNumber($this->_wp->linenum + 1);
$this->_pf_in_class = $this->_pf_interface = false;
// throw an event when class is done
$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);
* handle a var $varname = default_value; or var $varname; statement in a class definition
function handleVar($word, $pevent)
$this->_pf_set_var_value = false;
$this->_pv_var_value = '';
$this->_pv_linenum = $this->_wp->linenum + 1;
$this->_pf_in_var = true;
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 (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)
$this->_pv_var_value .= $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->_pf_in_var = false;
$this->_pf_var_equals = false;
$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->_pf_in_var = false;
$this->_pf_var_equals = false;
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;
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 (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)
$this->_pv_const_value .= $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->_pf_in_const = false;
$this->_pf_const_equals = false;
$this->_pv_constname = '';
$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->_pf_in_const = false;
$this->_pf_const_equals = false;
$this->_pv_constname = '';
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.
function JavaDochandleDocblock($word, $pevent)
$this->commonDocBlock($word, $pevent, 'handleJavaDocDesc');
* Handler for normal DocBlocks
function handleDocBlock($word, $pevent)
$this->commonDocBlock($word, $pevent, 'handleDesc');
* Common DocBlock Handler for both JavaDoc-format and normal DocBlocks
function commonDocBlock($word, $pevent, $deschandler)
$word = $this->_pv_last_word[1];
if (strpos($word,'/**') !== 0)
// $this->_wp->backupPos();
{ // stop using docblock template
unset ($this->_pv_dtemplate);
if (strpos($word,'/**#@+') === 0)
{ // docblock template definition
$dtype = '_pv_dtemplate';
if (strlen($word) && $word{0} != '*') {
if (substr(trim($lines[$i]),0,1) != '*') unset ($lines[$i]);
$lines[$i] = substr(trim($lines[$i]),1); // remove leading "* "
for($i = 0;$i< count($lines);$i++ )
// var_dump($desc,$tags);
$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')
* Handles JavaDoc descriptions
function handleJavaDocDesc($desc)
unset ($this->_pv_periodline);
$this->_pf_useperiod = false;
foreach($desc as $i => $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')
if (strpos($desc[0],'<p>') === 0) $desc[0] = substr($desc[0],3);
for($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++ )
if (strpos($desc[$i],'.') !== false)
$sdesc->add($this->getInlineTags($desci));
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();
$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";
for($i = 0; $i < count($desc); $i++ )
// the line will not be set if it doesn't start with a *
$desci .= $desc[$i]. "\n";
$my_desc->add($this->getInlineTags($desci));
if (strpos($desc[0],'<p>') === 0) $desc[0] = substr($desc[0],3);
for($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++ )
if (strpos($desc[$i],'.') !== false)
$sdesc->add($this->getInlineTags($desci));
for($i= 0; $i < count($desc); $i++ )
$desci .= $desci[$i]. "\n";
$my_desc->add($this->getInlineTags($desci));
$this->_pf_internal = false;
$this->$dtype->setShortDesc($sdesc);
$this->$dtype->setDesc($my_desc);
// var_dump($this->$dtype);
* Process the Long Description of a DocBlock
* @param array array of lines containing the description with leading
* asterisk "*" stripped off.
function handleDesc($desc)
unset ($this->_pv_periodline);
$this->_pf_useperiod = false;
foreach($desc as $i => $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;
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++ )
$this->_pv_periodline = $i;
// 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
for($i = $this->_pv_periodline; $i < $max; $i++ )
$this->_pv_periodline = $i;
$dtype = $this->_pv_dtype;
if ($dtype == '_pv_docblock')
for($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++ )
$desci .= $desc[$i]. "\n";
$sdesc->add($this->getInlineTags($desci));
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();
$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;
$my_desc->add($this->_pv_dtemplate->sdesc);
$my_desc->add($this->_pv_dtemplate->desc);
// echo "i = ".$this->_pv_periodline."; i < " . count($desc) . "\n";
for($i = $this->_pv_periodline; $i < count($desc); $i++ )
// the line will not be set if it doesn't start with a *
$desci .= $desc[$i]. "\n";
$my_desc->add($this->getInlineTags($desci));
{ // this is a docblock template
for($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++ )
$desci .= $desc[$i]. "\n";
$sdesc->add($this->getInlineTags($desci));
for($i= $this->_pv_periodline; $i < count($desc); $i++ )
$desci .= $desc[$i]. "\n";
$my_desc->add($this->getInlineTags($desci));
$this->_pf_internal = false;
$this->$dtype->setShortDesc($sdesc);
$this->$dtype->setDesc($my_desc);
// var_dump($this->$dtype);
* Process the tags of a DocBlock
* @param array array of lines that contain all @tags
function handleTags($tags)
for($i= 0;$i < count($tags);$i++ )
if (substr($tags[$i],0,1) == '@' && substr($tags[$i],0,2) != '@ ')
} else $curtag .= "\n". $tags[$i];
if (!empty($curtag)) $newtags[] = $curtag;
foreach($newtags as $tag)
if (isset ($this->tagHandlers[$tagname])) {
$handle = $this->tagHandlers[$tagname];
$handle = $this->tagHandlers['*'];
$this->$handle($tagname,$restoftag);
* Process all inline tags in text, and convert them to their abstract
* object representations.
* @param string|arraycomplete code to search for inline tags, if an
* array, it's an array of strings
* @return parserStringWithInlineTags
function getInlineTags($value)
$priv = (isset ($_phpDocumentor_setting['parseprivate']) && $_phpDocumentor_setting['parseprivate'] == 'on');
if (!$priv && $this->_pf_internal)
$value = substr($value,$x + 1);
$this->_pf_internal = false;
} elseif ($this->_pf_internal)
if ($priv || (!$priv && !$this->_pf_internal)) {
// ignore anything between {@internal and }}
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));
$val = join(' ',$value[$i]);
if (trim($word) == 'internal')
if ($this->_pf_internal) {
$this->_pf_internal = true;
$value[$i] = ''; // substr can set this to false
if (strpos($value[$i],'}}') !== false)
// strip internal and cycle as if it were normal text.
$startval = substr($value[$i],0,$x - 1);
$value[$i] = substr($value[$i],$x + 1);
if (!$value[$i]) $value[$i] = '';
$this->_pf_internal = false;
if ($priv || (!$priv && !$this->_pf_internal)) {
// ignore anything between {@internal and }}
$this->_pf_get_source = true;
$val = $this->$handle($word,$val);
if ($priv || (!$priv && !$this->_pf_internal)) {
// ignore anything between {@internal and }}
if (($x = strpos($rest,'}}')) !== false)
$startval = substr($value[$i],0,$x);
if ((false !== $startval) && $priv) {
$value[$i] = substr($value[$i],$x + 2);
$this->_pf_internal = false;
$this->_pf_internal = false;
// try this line again without internal
$value[$i-- ] = join('}}', $rest);
if ($priv || (!$priv && !$this->_pf_internal)) {
// ignore anything between {@internal and }}
* @param string name of the tag
* @param string any parameters passed to the inline tag
* Most inline tags require no special processing
function handleDefaultInlineTag($name, $value)
$tag = 'parser'. ucfirst($name). 'InlineTag';
return new $tag($value,$value);
* Handle the inline {@}link} tag
* @tutorial tags.inlinelink.pkg
function handleLinkInlineTag($name, $value)
// support hyperlinks of any protocol
$value = str_replace('\\,', '###commanana####', $value);
{ // if there is more than 1 parameter, the stuff after the space is the hyperlink text
$value = str_replace('\\,', '###commanana####', $value);
* @param string name of tag
* @param array all words in the tag that were separated by a space ' '
* Most tags only need the value as a string
* @uses getInlineTags() all tag handlers check their values for inline tags
$dtype = $this->_pv_dtype;
$this->$dtype->addKeyword($name,$this->getInlineTags(join(' ',$value)));
* @tutorial tags.example.pkg
* @uses parserDocBlock::addExample()
$dtype = $this->_pv_dtype;
$this->$dtype->addExample($this->getInlineTags(join(' ',$value)), $this->_path);
* @tutorial tags.filesource.pkg
* @uses phpDocumentorTWordParser::getFileSource() retrieves the source for
* use in the @filesource tag
function filesourceTagHandler($name, $value)
$dtype = $this->_pv_dtype;
$this->$dtype->addFileSource($this->_path, $this->_wp->getFileSource());
* @tutorial tags.uses.pkg
$dtype = $this->_pv_dtype;
while ($seel == '' && count($value))
$this->$dtype->addUses($this->getInlineTags($seel), $this->getInlineTags(join(' ',$value)));
* @tutorial tags.author.pkg
function authorTagHandler($name, $value)
$dtype = $this->_pv_dtype;
$value = join(' ',$value);
if ((strpos($value,'<') !== false) && (strpos($value,'>') !== false))
$value = str_replace('<'. $email. '>','<{@link mailto:'. $email. ' ' .
$this->$dtype->addKeyword('author',$this->getInlineTags($value));
* @tutorial tags.package.pkg
if (count($value) && empty($value[0]))
for($i= 0;$i< count($value) && !strlen($value[$i]);$i++ );
$dtype = $this->_pv_dtype;
$this->$dtype->setExplicitPackage();
* @tutorial tags.category.pkg
if (count($value) && empty($value[0]))
for($i= 0;$i< count($value) && !strlen($value[$i]);$i++ );
$dtype = $this->_pv_dtype;
$this->$dtype->setExplicitCategory();
* @tutorial tags.global.pkg
$info = $this->retrieveType($value, true);
$dtype = $this->_pv_dtype;
if (!$var && empty($desc))
$this->_pv_global_type = $type;
if (!empty($desc)) $var .= ' '. $desc;
$this->findGlobal(trim($var));
$this->$dtype->addFuncGlobal($type,$this->getInlineTags($desc));
* @tutorial tags.staticvar.pkg
$info = $this->retrieveType($value, true);
$dtype = $this->_pv_dtype;
if (!$var && empty($desc))
$this->$dtype->addStaticVar($var,$type,$this->getInlineTags($desc));
$this->$dtype->addStaticVar(null,$type,$this->getInlineTags($desc));
* @tutorial tags.param.pkg
$info = $this->retrieveType($value, true);
//if (!$info) addErrorDie(PDERROR_MALFORMED_TAG, '@param');
$dtype = $this->_pv_dtype;
if (!$var && empty($desc))
$this->$dtype->addParam($var,$type,$this->getInlineTags($desc));
$this->$dtype->addParam(null,$type,$this->getInlineTags($desc));
* @tutorial tags.return.pkg
$info = $this->retrieveType($value, true);
//if (!$info) addErrorDie(PDERROR_MALFORMED_TAG, '@return');
$dtype = $this->_pv_dtype;
$this->$dtype->addReturn($type,$this->getInlineTags($desc));
$info = $this->retrieveType($value, true);
$dtype = $this->_pv_dtype;
$this->$dtype->addVar($type,$this->getInlineTags($desc));
* 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 array of words that were separated by spaces
* @param boolean flag to determine whether to check for the end of a
* type is defined by a $varname
* @return array Format: array('type' => string, 'var' =>
* false|string variable name, 'desc' => rest
function retrieveType($value, $checkforvar = false)
if (!count($value)) return false;
// remove empty entries resulting from extra spaces between @tag and type
$this->_removeWhiteSpace($value, 0);
if (trim($value[0]) == 'object')
$this->_removeWhiteSpace($value, 0);
{ // was just passed "object"
$result = array('type' => rtrim($types),'desc' => '');
if ($checkforvar) $result['var'] = false;
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';
$result['desc'] = join(' ', $value);
{ // this loop checks for type|type|type and for
// type|object classname|type|object classname2
$temptypes = explode('|', $value[0]);
if (count($temptypes)) $types .= '|';
if (trim($type) == 'object')
$this->_removeWhiteSpace($value,0);
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;
$result['desc'] = join(' ', $value);
} while (!$done && count($value));
$result['type'] = rtrim($types);
$this->_removeWhiteSpace($value,0);
if (substr($value[0],0,1) == '$' || substr($value[0],0,2) == '&$')
$result['var'] = trim($value[0]);
} else $result['var'] = false;
$result['desc'] = join(' ',$value);
* @param array array of string
* @param integer index to seek non-whitespace to
function _removeWhiteSpace(&$value, $index)
if (count($value) > $index && empty($value[$index]))
for($i= $index; $i< count($value) && !strlen($value[$i]); $i++ );
* Retrieve all the tokens that represent the definition of the global
function findGlobal($name)
$this->_wp->findGlobal($tokens);
$this->_pv_findglobal = $name;
* 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;
$this->_wp->setWhitespace(true);
$this->_pf_in_global = false;
$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));
unset ($this->_pv_global_val);
unset ($this->_pv_global_type);
* handler for GLOBAL_VALUE
function handleGlobalValue($word, $pevent)
$this->_wp->setWhitespace(true);
if (!isset ($this->_pv_global_val)) $this->_pv_global_val = '';
$this->_pv_global_val .= $this->_pv_function_data;
$this->_pv_function_data = '';
$this->_pv_global_val .= $this->_pv_quote_data;
unset ($this->_pv_quote_data);
$this->_wp->setWhitespace(false);
$this->_pv_global_val .= $word;
* 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
if (is_array($word) && $word[0] == T_STRING) $word = $word[1];
$pushEvent = &$this->tokenpushEvent;
$pushEvent = &$this->wordpushEvent;
if (isset ($pushEvent[$pevent]))
if (isset ($pushEvent[$pevent][$word]))
$e = $pushEvent[$pevent][$word];
* 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
if (is_array($word) && $word[0] == T_STRING) $word = $word[1];
$popEvent = &$this->tokenpopEvent;
$popEvent = &$this->wordpopEvent;
if (!isset ($popEvent[$pevent])) return false;
* setup the parser tokens, and the pushEvent/popEvent arrays
* @see $tokens, $pushEvent, $popEvent
$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_docblock = null;
$this->_pv_dtemplate = 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_varname = 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;
* Creates the state arrays
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
// "/**#@+" => PARSER_EVENT_DOCBLOCK_TEMPLATE,
// "/**#@-*/" => PARSER_EVENT_END_DOCBLOCK_TEMPLATE,
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
/**************************************************************/
$this->_wp->setup($data);
$this->_wp->setWhitespace(false);
|