Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php/*** Source Code Highlighting** The classes in this file are responsible for the dynamic @example, and* <programlisting role="tutorial"> tags output. Using the* WordParser, the phpDocumentor_TutorialHighlightParser* retrieves PHP tokens one by one from the array generated by* {@link WordParser} source retrieval functions* and then highlights them individually.** It accomplishes this highlighting through the assistance of methods in* the output Converter passed to its parse() method, and then returns the* fully highlighted source as a string** phpDocumentor :: automatic documentation generator** PHP versions 4 and 5** Copyright (c) 2003-2007 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 2003-2007 Gregory Beaver* @license http://www.opensource.org/licenses/lgpl-license.php LGPL* @version CVS: $Id: TutorialHighlightParser.inc 246148 2007-11-14 01:57:04Z ashnazg $* @tutorial tags.example.pkg, tags.filesource.pkg* @link http://www.phpdoc.org* @link http://pear.php.net/PhpDocumentor* @since 1.3.0* @todo CS cleanup - change package to PhpDocumentor* @todo CS cleanup - PHPCS needs to ignore CVS Id length*//*** Highlights source code using {@link parse()}** @category ToolsAndUtilities* @package phpDocumentor* @subpackage Parsers* @author Gregory Beaver <cellog@php.net>* @copyright 2003-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* @todo CS cleanup - change package to PhpDocumentor* @todo CS cleanup - change classname to PhpDocumentor_**/class phpDocumentor_TutorialHighlightParser extends Parser{/**#@+ @access private *//*** Highlighted source is built up in this string* @var string*/var $_output;/*** contents of the current source code line as it is parsed* @var string*/var $_line;/*** Used to retrieve highlighted tokens* @var Converter a descendant of Converter*/var $_converter;/*** Path to file being highlighted, if this is from a @filesource tag* @var false|string full path*/var $_filesourcepath;/*** @var array*/var $eventHandlers = array(TUTORIAL_EVENT_NOEVENTS => 'defaultHandler',TUTORIAL_EVENT_ITAG => 'defaultHandler',TUTORIAL_EVENT_ATTRIBUTE => 'attrHandler',TUTORIAL_EVENT_OPENTAG => 'defaultHandler',TUTORIAL_EVENT_CLOSETAG => 'defaultHandler',TUTORIAL_EVENT_ENTITY => 'defaultHandler',TUTORIAL_EVENT_COMMENT => 'defaultHandler',TUTORIAL_EVENT_SINGLEQUOTE => 'defaultHandler',TUTORIAL_EVENT_DOUBLEQUOTE => 'defaultHandler',);/**#@-*//*** advances output to a new line** @return void* @uses Converter::SourceLine() encloses {@link $_line} in a* converter-specific format*/function newLineNum(){$this->_line .= $this->_converter->flushHighlightCache();$this->_output .= $this->_converter->SourceLine($this->_pv_curline + 1,$this->_line, $this->_path);$this->_line = '';}/*** Start the parsing at a certain line number** @param int $num the line number** @return void*/function setLineNum($num){$this->_wp->linenum = $num;}/*** Parse a new file** The parse() method is a do...while() loop that retrieves tokens one by* one from the {@link $_event_stack}, and uses the token event array set up* by the class constructor to call event handlers.** The event handlers each process the tokens passed to them, and use the* {@link _addoutput()} method to append the processed tokens to the* {@link $_line} variable. The word parser calls {@link newLineNum()}* every time a line is reached.** In addition, the event handlers use special linking functions* {@link _link()} and its cousins (_classlink(), etc.) to create in-code* hyperlinks to the documentation for source code elements that are in the* source code.** @param string $parse_data blah* @param Converter &$converter blah* @param false|string $filesourcepath full path to file with @filesource tag,* if this is a @filesource parse* @param false|integer $linenum starting line number from* {@}source linenum}** @staticvar integer used for recursion limiting if a handler for* an event is not found* @return bool* @uses setupStates() initialize parser state variables* @uses configWordParser() pass $parse_data to prepare retrieval of tokens* @todo CS cleanup - unable to get function signature below 85char wide*/function parse($parse_data, &$converter, $filesourcepath = false, $linenum = false){static $endrecur = 0;$parse_data =str_replace(array("\r\n", "\t"), array("\n", ' '), $parse_data);$this->_converter = &$converter;$converter->startHighlight();$this->_path = $filesourcepath;$this->setupStates($parse_data);$this->configWordParser(TUTORIAL_EVENT_NOEVENTS);if ($linenum !== false) {$this->setLineNum($linenum);}// initialize variables so E_ALL error_reporting doesn't complain$pevent = 0;$word = 0;do {$lpevent = $pevent;$pevent = $this->_event_stack->getEvent();if ($lpevent != $pevent) {$this->_last_pevent = $lpevent;$this->configWordParser($pevent);}$this->_wp->setWhitespace(true);$dbg_linenum = $this->_wp->linenum;$dbg_pos = $this->_wp->getPos();$this->_pv_last_word = $word;$this->_pv_curline = $this->_wp->linenum;$word = $this->_wp->getWord();if (PHPDOCUMENTOR_DEBUG == true) {echo "LAST: ";echo "|" . $this->_pv_last_word;echo "|\n";echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";echo "LASTPEVENT: " .$this->getParserEventName($this->_last_pevent) . "\n";//DEBUG echo "LINE: " . $this->_line . "\n";//DEBUG echo "OUTPUT: " . $this->_output . "\n";echo $dbg_linenum.'-'.$dbg_pos . ": ";echo '|'.htmlspecialchars($word);echo "|\n";echo "-------------------\n\n\n";flush();}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));if (strlen($this->_line)) {$this->newLineNum();}return $this->_output;}/**#@+* Event Handlers** All Event Handlers use {@link checkEventPush()} and* {@link checkEventPop()} to set up the event stack and parser state.** @param string|array $word token value* @param integer $pevent parser event from {@link Parser.inc}** @return void* @access private*//*** Most tokens only need highlighting, and this method handles them** @todo CS cleanup - PHPCS needs to recognize docblock template tags*/function defaultHandler($word, $pevent){if ($word == "\n") {$this->newLineNum();return;}if ($this->checkEventPush($word, $pevent)) {$this->_wp->backupPos($word);return;}$this->_addoutput($word);$this->checkEventPop($word, $pevent);}/*** Most tokens only need highlighting, and this method handles them** @todo CS cleanup - PHPCS needs to recognize docblock template tags*/function attrHandler($word, $pevent){if ($word == "\n") {$this->newLineNum();return;}if ($e = $this->checkEventPush($word, $pevent)) {if ($e == TUTORIAL_EVENT_SINGLEQUOTE|| $e == TUTORIAL_EVENT_DOUBLEQUOTE) {$this->_addoutput($word);}return;}if ($this->checkEventPop($word, $pevent)) {$this->_wp->backupPos($word);return;}$this->_addoutput($word);}/**#@-*//**#@+* Output Methods* @access private*//*** This method adds output to {@link $_line}** If a string with variables like "$test this" is present, then special* handling is used to allow processing of the variable in context.** @param string $word the output to add* @param bool $preformatted whether or not its preformatted** @return void* @see _flush_save()*/function _addoutput($word, $preformatted = false){$type = array(TUTORIAL_EVENT_ATTRIBUTE => 'attribute',TUTORIAL_EVENT_SINGLEQUOTE => 'attributevalue',TUTORIAL_EVENT_DOUBLEQUOTE => 'attributevalue',TUTORIAL_EVENT_CLOSETAG => 'closetag',TUTORIAL_EVENT_ENTITY => 'entity',TUTORIAL_EVENT_ITAG => 'itag',TUTORIAL_EVENT_OPENTAG => 'opentag',TUTORIAL_EVENT_COMMENT => 'comment',);$a = $this->_event_stack->getEvent();if (in_array($a, array_keys($type))) {$this->_line .=$this->_converter->highlightTutorialSource($type[$a], $word);} else {$this->_line .= $this->_converter->flushHighlightCache();$this->_line .= $this->_converter->postProcess($word);}}/**#@-*//*** Tell the parser's WordParser {@link $wp} to set up tokens to parse words by.** Tokens are word separators. In English, a space or punctuation are* examples of tokens. In PHP, a token can be a ;, a parenthesis, or* even the word "function"** @param integer $e an event number** @return void* @see WordParser*/function configWordParser($e){$this->_wp->setSeperator($this->tokens[($e + 100)]);}/**#@+* @param string|array $word token value* @param integer $pevent parser event from {@link Parser.inc}** @return mixed returns false, or the event number*//*** This function checks whether parameter $word is a token* for pushing a new event onto the Event Stack.** @todo CS cleanup - PHPCS needs to recognize docblock template tags*/function checkEventPush($word, $pevent){$e = false;if (isset($this->pushEvent[$pevent])) {if (isset($this->pushEvent[$pevent][strtolower($word)])) {$e = $this->pushEvent[$pevent][strtolower($word)];}}if ($e) {$this->_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.** @todo CS cleanup - PHPCS needs to recognize docblock template tags*/function checkEventPop($word, $pevent){if (!isset($this->popEvent[$pevent])) {return false;}if (in_array(strtolower($word), $this->popEvent[$pevent])) {return $this->_event_stack->popEvent();} else {return false;}}/**#@-*//*** Initialize all parser state variables** @param bool|string $parsedata true if we are highlighting an inline {@}source}* tag's output, or the name of class we are going* to start from** @return void* @uses $_wp sets to a new {@link phpDocumentor_HighlightWordParser}*/function setupStates($parsedata){$this->_output = '';$this->_line = '';unset($this->_wp);$this->_wp = new WordParser;$this->_wp->setup($parsedata);$this->_event_stack = new EventStack;$this->_event_stack->popEvent();$this->_event_stack->pushEvent(TUTORIAL_EVENT_NOEVENTS);$this->_pv_linenum = null;$this->_pv_next_word = false;}/*** Initialize the {@link $tokenpushEvent, $wordpushEvent} arrays*/function phpDocumentor_TutorialHighlightParser(){$this->allowableInlineTags =$GLOBALS['_phpDocumentor_inline_tutorial_tags_allowed'];$this->inlineTagHandlers =array('*' => 'handleDefaultInlineTag');$this->tokens[STATE_TUTORIAL_NOEVENTS] =array("\n",'{@', '<!--', '</', '<', '&');$this->tokens[STATE_TUTORIAL_ITAG] = array("\n","}");$this->tokens[STATE_TUTORIAL_OPENTAG] = array("\n","\t"," ", '>', '/>');$this->tokens[STATE_TUTORIAL_CLOSETAG] = array("\n",'>');$this->tokens[STATE_TUTORIAL_COMMENT] = array("\n",'-->');$this->tokens[STATE_TUTORIAL_ENTITY] = array("\n",';');$this->tokens[STATE_TUTORIAL_ATTRIBUTE] = array("\n",'"',"'",'>','/>');$this->tokens[STATE_TUTORIAL_DOUBLEQUOTE] = array("\n",'"','&','{@');$this->tokens[STATE_TUTORIAL_SINGLEQUOTE] = array("\n","'",'&','{@');/**************************************************************/$this->pushEvent[TUTORIAL_EVENT_NOEVENTS] = array("{@" => TUTORIAL_EVENT_ITAG,'<' => TUTORIAL_EVENT_OPENTAG,'</' => TUTORIAL_EVENT_CLOSETAG,'&' => TUTORIAL_EVENT_ENTITY,'<!--' => TUTORIAL_EVENT_COMMENT,);/**************************************************************/$this->pushEvent[TUTORIAL_EVENT_OPENTAG] = array(" " => TUTORIAL_EVENT_ATTRIBUTE,"\n" => TUTORIAL_EVENT_ATTRIBUTE,);/**************************************************************/$this->pushEvent[TUTORIAL_EVENT_ATTRIBUTE] = array("'" => TUTORIAL_EVENT_SINGLEQUOTE,'"' => TUTORIAL_EVENT_DOUBLEQUOTE,);/**************************************************************/$this->pushEvent[TUTORIAL_EVENT_SINGLEQUOTE] = array('&' => TUTORIAL_EVENT_ENTITY,'{@' => TUTORIAL_EVENT_ITAG,);/**************************************************************/$this->pushEvent[TUTORIAL_EVENT_DOUBLEQUOTE] = array('&' => TUTORIAL_EVENT_ENTITY,'{@' => TUTORIAL_EVENT_ITAG,);/**************************************************************/$this->popEvent[TUTORIAL_EVENT_ENTITY] = array(';');/**************************************************************/$this->popEvent[TUTORIAL_EVENT_SINGLEQUOTE] = array("'");/**************************************************************/$this->popEvent[TUTORIAL_EVENT_DOUBLEQUOTE] = array('"');/**************************************************************/$this->popEvent[TUTORIAL_EVENT_OPENTAG] = array('>', '/>');/**************************************************************/$this->popEvent[TUTORIAL_EVENT_CLOSETAG] = array('>');/**************************************************************/$this->popEvent[TUTORIAL_EVENT_COMMENT] = array('-->');/**************************************************************/$this->popEvent[TUTORIAL_EVENT_ATTRIBUTE] = array('>','/>');/**************************************************************/$this->popEvent[TUTORIAL_EVENT_ITAG] = array('}');/**************************************************************/}/*** searches for a parser event name based on its number** @param int $value the event number** @return string|int the event name, or the original value*/function getParserEventName ($value){$lookup = array(TUTORIAL_EVENT_NOEVENTS => "TUTORIAL_EVENT_NOEVENTS",TUTORIAL_EVENT_ITAG => "TUTORIAL_EVENT_ITAG",TUTORIAL_EVENT_OPENTAG => "TUTORIAL_EVENT_OPENTAG",TUTORIAL_EVENT_ATTRIBUTE => "TUTORIAL_EVENT_ATTRIBUTE",TUTORIAL_EVENT_CLOSETAG => "TUTORIAL_EVENT_CLOSETAG",TUTORIAL_EVENT_ENTITY => "TUTORIAL_EVENT_ENTITY",TUTORIAL_EVENT_COMMENT => "TUTORIAL_EVENT_COMMENT",TUTORIAL_EVENT_SINGLEQUOTE => "TUTORIAL_EVENT_SINGLEQUOTE",TUTORIAL_EVENT_DOUBLEQUOTE => "TUTORIAL_EVENT_DOUBLEQUOTE",);if (isset($lookup[$value])) {return $lookup[$value];} else {return $value;}}}/*** starting state*/define("TUTORIAL_EVENT_NOEVENTS", 1);/*** currently in starting state*/define("STATE_TUTORIAL_NOEVENTS", 101);/*** used when an {@}inline tag} is found*/define("TUTORIAL_EVENT_ITAG", 2);/*** currently parsing an {@}inline tag}*/define("STATE_TUTORIAL_ITAG", 102);/*** used when an open <tag> is found*/define("TUTORIAL_EVENT_OPENTAG", 3);/*** currently parsing an open <tag>*/define("STATE_TUTORIAL_OPENTAG", 103);/*** used when a <tag attr="attribute"> is found*/define("TUTORIAL_EVENT_ATTRIBUTE", 4);/*** currently parsing an open <tag>*/define("STATE_TUTORIAL_ATTRIBUTE", 104);/*** used when a close </tag> is found*/define("TUTORIAL_EVENT_CLOSETAG", 5);/*** currently parsing a close </tag>*/define("STATE_TUTORIAL_CLOSETAG", 105);/*** used when an &entity; is found*/define("TUTORIAL_EVENT_ENTITY", 6);/*** currently parsing an &entity;*/define("STATE_TUTORIAL_ENTITY", 106);/*** used when a <!-- comment --> is found*/define("TUTORIAL_EVENT_COMMENT", 7);/*** currently parsing a <!-- comment -->*/define("STATE_TUTORIAL_COMMENT", 107);/*** used when a <!-- comment --> is found*/define("TUTORIAL_EVENT_SINGLEQUOTE", 8);/*** currently parsing a <!-- comment -->*/define("STATE_TUTORIAL_SINGLEQUOTE", 108);/*** used when a <!-- comment --> is found*/define("TUTORIAL_EVENT_DOUBLEQUOTE", 9);/*** currently parsing a <!-- comment -->*/define("STATE_TUTORIAL_DOUBLEQUOTE", 109);?>