* @copyright 2002-2007 Gregory Beaver * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @version CVS: $Id: phpDocumentorTWordParser.inc 287887 2009-08-30 06:10:55Z ashnazg $ * @link http://www.phpdoc.org * @link http://pear.php.net/PhpDocumentor * @since 1.2 * @todo CS cleanup - change package to PhpDocumentor * @todo CS cleanup - PHPCS needs to ignore CVS Id length */ /** * Like WordParser, but expects an array of tokens from the tokenizer * instead of a string. * * @category ToolsAndUtilities * @package phpDocumentor * @subpackage WordParsers * @author Gregory Beaver * @copyright 2002-2007 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 * @since 1.2 * @todo CS cleanup - change package to PhpDocumentor * @todo CS cleanup - change classname to PhpDocumentor_* */ class phpDocumentorTWordParser extends WordParser { /**#@+ * @access private */ /** * tokenized array from {@link token_get_all()} * @var array */ var $_all; /** * List of tokens that can contain a newline * @var array */ var $_nl_check = array( T_WHITESPACE, T_ENCAPSED_AND_WHITESPACE, T_CONSTANT_ENCAPSED_STRING, T_COMMENT, T_DOC_COMMENT, T_OPEN_TAG, T_CLOSE_TAG, T_INLINE_HTML, T_START_HEREDOC, ); /** * @var array */ var $_global_search; /** * current source line number (relative) * @var integer */ var $_sourceline; /** * Source of the entire file, parsed into arrays of tokens on each line * @var array */ var $_file_source = array(); /** * Line number the last comment was on * @var integer */ var $_docblock_linenum; /**#@-*/ /** * Uses {@link token_get_all()} to tokenize the source code. * {@internal * Also, it divides the source tokens into separate lines for use by * the @filesource tag. * * {@source}}} * * @param string &$input source code * * @return void */ function setup(&$input) { $input = rtrim(ltrim($input, "\r\n")); $this->data = &$input; // fix php warnings on invalid source code $this->_all = @token_get_all($input); $this->_file_source = array(); $this->addFileSource($this->_all); $this->_sourceline = 0; $this->pos = 0; $this->linenum = 0; } /** * loads up next set of source code * * @return array source code array */ function getSource() { $source = $this->source; $this->source = array(); $this->getsource = false; return $source; } /** * gets the source code tokens * * @return array source code tokens split up by line number */ function getFileSource() { return $this->_file_source; } /** * Begin retrieving source code * * @param string $word word to add the beginning of source code * * @return void * @access private * @todo CS cleanup - rename to retrieveSource for camelCase rule */ function retrievesource($word = '') { $this->source = array(array($word)); $this->_sourceline = 0; $this->getsource = true; } /** * Utility function to determine whether two tokens from the tokenizer are equal * * @param mixed $a first token * @param mixed $b second token * * @return bool whether or not the tokens are equal * @static */ function tokenEquals($a, $b) { if (is_array($a)) $a = $a[1]; if (is_array($b)) $b = $b[1]; return $a == $b; } /** * Utility function to convert a series of tokens into a string * * @param array $a array of tokens * * @return string the resulting string * @static */ function concatTokens($a) { $b = ''; foreach ($a as $c) { if (is_array($c)) { $c = $c[1]; } $b .= $c; } return $b; } /** * Retrieve a token for the phpDocumentorTParser * {@internal * This method adds source code to the array for a function to be returned * to a {@}source} tag, and will return the token unless it is T_WHITESPACE * and {@link $returnWhiteSpace} is false. * * The global variable search is more complicated than it is in the * WordParser, as we have to compare an array of tokens to each other, and * that is what this code does}} * * @return string|array token from tokenizer */ function getWord() { if (!isset($this->_all[$this->pos])) { return false; } $oldlinenum = $this->linenum; $word = $this->_all[$this->pos++]; // if we're looking for a global variable declaration, then this section // will search the upcoming tokens to see if they match the tokens // that define the global variable if (isset($this->_global_search)) { $pos = $this->pos; $gpos = 0; $found = false; if ($this->tokenEquals($word, $this->_global_search[$gpos++])) { $found = true; for (;$gpos_global_search);$gpos++, $pos++) { if (isset($this->_all[$pos]) && !$this->tokenEquals($this->_global_search[$gpos], $this->_all[$pos]) ) { $found = false; } } } if ($found) { $a = $this->concatTokens($this->_global_search); $this->pos += count($this->_global_search) - 1; unset($this->_global_search); return $a; } } if ($this->getsource) { $this->addSource($word); } if (is_array($word)) { if (in_array($word[0], $this->_nl_check)) { $this->linenum += substr_count($word[1], "\n"); } if ($word[0] == T_WHITESPACE && !$this->returnWhiteSpace) { return $this->getWord(); } // seeing if we can get line numbers out of the beast } if (is_array($word) && $word[0] == T_COMMENT) { $this->_docblock_linenum = $oldlinenum; } return $word; } /** * Wrapper for {@link addSource()} used to retrieve the entire source code * organized by line number in setup() * * @param array $word full file source code * * @return void */ function addFileSource($word) { $this->_sourceline = 0; foreach ($word as $token) { $this->addSource($token, true); } // var_dump($this->_file_source); } /** * Generate source token arrays organized by line number * * This code will split up tokens that contain "\n" and add them to the * source code as separate tokens on different lines. * * @param array|string $word token to add * @param bool $file true if this should be added * to {@link $_file_source} * * @return void * @uses _set_sars() */ function addSource($word, $file = false) { if (is_array($word)) { $lines = str_replace("\r", '', explode("\n", $word[1])); foreach ($lines as $i => $line) { $this->_set_sars($file, array($word[0], $line)); if ($i < count($lines) - 1) { // increment sourceline $this->_sourceline++; } } } else { $this->_set_sars($file, $word); } } /** * Add tokens to source code * * {@source} * * @param bool $type true if this is file source, * otherwise it is function source * @param string|array $word token to add * * @return void * @access private * @todo CS cleanup - rename to _setSars for camelCasing rule */ function _set_sars($type, $word) { if ($type) { $this->_file_source[$this->_sourceline][] = $word; } else { $this->source[$this->_sourceline][] = $word; } } /** * Tell the phpDocumentorTWordParser to return the entire global variable * if it is found. * * @param array $tokens tokens that represent the global variable definition * * @return void * @uses $_global_search */ function findGlobal($tokens) { if (!$tokens) { unset($this->_global_search); } else { $this->_global_search = $tokens; } } /** * backs the parser up to the previous position * * @return int|void can return a word */ function backupPos() { $this->pos--; $word = $this->_all[$this->pos]; if ($this->getsource) { unset($this->source[$this->_sourceline] [count($this->source[$this->_sourceline]) - 1]); if (empty($this->source[$this->_sourceline])) { unset($this->source[$this->_sourceline]); } else { $this->source[$this->_sourceline] = array_values($this->source[$this->_sourceline]); } } if (is_array($word)) { if ($word[0] == T_WHITESPACE && !$this->returnWhiteSpace) { return $this->getWord(); } // seeing if we can get line numbers out of the beast if (in_array($word[0], $this->_nl_check)) { $this->linenum -= substr_count($word[1], "\n"); } } } } ?>