phpDocumentor phpDocumentor
Parsers
[ class tree: phpDocumentor ] [ index: phpDocumentor ] [ all elements ]

Source for file TutorialHighlightParser.inc

Documentation is available at TutorialHighlightParser.inc

  1. <?php
  2. /**
  3.  * Source Code Highlighting
  4.  *
  5.  * The classes in this file are responsible for the dynamic @example, and
  6.  * <programlisting role="tutorial"> tags output.  Using the
  7.  * WordParser, the phpDocumentor_TutorialHighlightParser
  8.  * retrieves PHP tokens one by one from the array generated by
  9.  * {@link WordParser} source retrieval functions
  10.  * and then highlights them individually.
  11.  *
  12.  * It accomplishes this highlighting through the assistance of methods in
  13.  * the output Converter passed to its parse() method, and then returns the
  14.  * fully highlighted source as a string
  15.  * 
  16.  * phpDocumentor :: automatic documentation generator
  17.  * 
  18.  * PHP versions 4 and 5
  19.  *
  20.  * Copyright (c) 2003-2006 Gregory Beaver
  21.  * 
  22.  * LICENSE:
  23.  * 
  24.  * This library is free software; you can redistribute it
  25.  * and/or modify it under the terms of the GNU Lesser General
  26.  * Public License as published by the Free Software Foundation;
  27.  * either version 2.1 of the License, or (at your option) any
  28.  * later version.
  29.  * 
  30.  * This library is distributed in the hope that it will be useful,
  31.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  32.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  33.  * Lesser General Public License for more details.
  34.  * 
  35.  * You should have received a copy of the GNU Lesser General Public
  36.  * License along with this library; if not, write to the Free Software
  37.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  38.  *
  39.  * @package    phpDocumentor
  40.  * @subpackage Parsers
  41.  * @author     Gregory Beaver <cellog@php.net>
  42.  * @copyright  2003-2006 Gregory Beaver
  43.  * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL
  44.  * @version    CVS: $Id: TutorialHighlightParser.inc,v 1.4 2006/05/01 04:13:51 cellog Exp $
  45.  * @tutorial   tags.example.pkg, tags.filesource.pkg
  46.  * @link       http://www.phpdoc.org
  47.  * @link       http://pear.php.net/PhpDocumentor
  48.  * @since      1.3.0
  49.  */
  50.  
  51. /**
  52.  * Highlights source code using {@link parse()}
  53.  * @package phpDocumentor
  54.  * @subpackage Parsers
  55.  */
  56. {
  57.     /**#@+ @access private */
  58.     /**
  59.      * Highlighted source is built up in this string
  60.      * @var string 
  61.      */
  62.     var $_output;
  63.     /**
  64.      * contents of the current source code line as it is parsed
  65.      * @var string 
  66.      */
  67.     var $_line;
  68.     /**
  69.      * Used to retrieve highlighted tokens
  70.      * @var Converter a descendant of Converter
  71.      */
  72.     var $_converter;
  73.     /**
  74.      * Path to file being highlighted, if this is from a @filesource tag
  75.      * @var false|stringfull path
  76.      */
  77.     var $_filesourcepath;
  78.     /**
  79.      * @var array 
  80.      */
  81.     var $eventHandlers array(
  82.                                 TUTORIAL_EVENT_NOEVENTS => 'defaultHandler',
  83.                                 TUTORIAL_EVENT_ITAG => 'defaultHandler',
  84.                                 TUTORIAL_EVENT_ATTRIBUTE => 'attrHandler',
  85.                                 TUTORIAL_EVENT_OPENTAG => 'defaultHandler',
  86.                                 TUTORIAL_EVENT_CLOSETAG => 'defaultHandler',
  87.                                 TUTORIAL_EVENT_ENTITY => 'defaultHandler',
  88.                                 TUTORIAL_EVENT_COMMENT => 'defaultHandler',
  89.                                 TUTORIAL_EVENT_SINGLEQUOTE => 'defaultHandler',
  90.                                 TUTORIAL_EVENT_DOUBLEQUOTE => 'defaultHandler',
  91.     );
  92.     /**#@-*/
  93.     
  94.     /**
  95.      * @uses Converter::SourceLine() encloses {@link $_line} in a
  96.      *                                converter-specific format
  97.      */
  98.     function newLineNum()
  99.     {
  100.         $this->_line .= $this->_converter->flushHighlightCache();
  101.         $this->_output .= $this->_converter->SourceLine($this->_pv_curline 1$this->_line$this->_path);
  102.         $this->_line '';
  103.     }
  104.     
  105.     /**
  106.      * Start the parsing at a certain line number
  107.      */
  108.     function setLineNum($num)
  109.     {
  110.         $this->_wp->linenum $num;
  111.     }
  112.     
  113.     /**
  114.      * Parse a new file
  115.      *
  116.      * The parse() method is a do...while() loop that retrieves tokens one by
  117.      * one from the {@link $_event_stack}, and uses the token event array set up
  118.      * by the class constructor to call event handlers.
  119.      *
  120.      * The event handlers each process the tokens passed to them, and use the
  121.      * {@link _addoutput()} method to append the processed tokens to the
  122.      * {@link $_line} variable.  The word parser calls {@link newLineNum()}
  123.      * every time a line is reached.
  124.      *
  125.      * In addition, the event handlers use special linking functions
  126.      * {@link _link()} and its cousins (_classlink(), etc.) to create in-code
  127.      * hyperlinks to the documentation for source code elements that are in the
  128.      * source code.
  129.      *
  130.      * @uses setupStates() initialize parser state variables
  131.      * @uses configWordParser() pass $parse_data to prepare retrieval of tokens
  132.      * @param    string 
  133.      * @param    Converter 
  134.      * @param    false|stringfull path to file with @filesource tag, if this
  135.      *            is a @filesource parse
  136.      * @param    false|integerstarting line number from {@}source linenum}
  137.      * @staticvar    integer    used for recursion limiting if a handler for
  138.      *                           an event is not found
  139.      * @return    bool 
  140.      */
  141.     function parse ($parse_data&$converter$filesourcepath false$linenum false)
  142.     {
  143.         static $endrecur 0;
  144.         $parse_data str_replace(array("\r\n""\t")array("\n"'    ')$parse_data);
  145.         $this->_converter &$converter;
  146.         $converter->startHighlight();
  147.         $this->_path $filesourcepath;
  148.         $this->setupStates($parse_data);
  149.  
  150.         $this->configWordParser(TUTORIAL_EVENT_NOEVENTS);
  151.         if ($linenum !== false$this->setLineNum($linenum);
  152.         // initialize variables so E_ALL error_reporting doesn't complain
  153.         $pevent 0;
  154.         $word 0;
  155.  
  156.         do
  157.         {
  158.             $lpevent $pevent;
  159.             $pevent $this->_event_stack->getEvent();
  160.             if ($lpevent != $pevent)
  161.             {
  162.                 $this->_last_pevent $lpevent;
  163.                 $this->configWordParser($pevent);
  164.             }
  165.             $this->_wp->setWhitespace(true);
  166.  
  167.             $dbg_linenum $this->_wp->linenum;
  168.             $dbg_pos $this->_wp->getPos();
  169.             $this->_pv_last_word $word;
  170.             $this->_pv_curline $this->_wp->linenum;
  171.             $word $this->_wp->getWord();
  172.  
  173.             if (0)//PHPDOCUMENTOR_DEBUG == true)
  174.             {
  175.                 echo "LAST: ";
  176.                 echo "|" $this->_pv_last_word;
  177.                 echo "|\n";
  178.                 echo "PEVENT: " $this->getParserEventName($pevent"\n";
  179.                 echo "LASTPEVENT: " $this->getParserEventName($this->_last_pevent"\n";
  180. //                echo "LINE: ".$this->_line."\n";
  181. //                echo "OUTPUT: ".$this->_output."\n";
  182.                 echo $dbg_linenum.'-'.$dbg_pos ": ";
  183.                 echo '|'.htmlspecialchars($word);
  184.                 echo "|\n";
  185.                 echo "-------------------\n\n\n";
  186.                 flush();
  187.             }
  188.             if (isset($this->eventHandlers[$pevent]))
  189.             {
  190.                 $handle $this->eventHandlers[$pevent];
  191.                 $this->$handle($word$pevent);
  192.             else
  193.             {
  194.                 debug('WARNING: possible error, no handler for event number '.$pevent);
  195.                 if ($endrecur++ == 25)
  196.                 {
  197.                     die("FATAL ERROR, recursion limit reached");
  198.                 }
  199.             }
  200.         while (!($word === false));
  201.         if (strlen($this->_line)) $this->newLineNum();
  202.         return $this->_output;
  203.     }
  204.     
  205.     /**#@+
  206.      * Event Handlers
  207.      *
  208.      * All Event Handlers use {@link checkEventPush()} and
  209.      * {@link checkEventPop()} to set up the event stack and parser state.
  210.      * @access private
  211.      * @param string|arraytoken value
  212.      * @param integer parser event from {@link Parser.inc}
  213.      */
  214.     /**
  215.      * Most tokens only need highlighting, and this method handles them
  216.      */
  217.     function defaultHandler($word$pevent)
  218.     {
  219.         if ($word == "\n"{
  220.             $this->newLineNum();
  221.             return;
  222.         }
  223.         if ($this->checkEventPush($word$pevent)) {
  224.             $this->_wp->backupPos($word);
  225.             return;
  226.         }
  227.         $this->_addoutput($word);
  228.         $this->checkEventPop($word$pevent);
  229.     }
  230.  
  231.     /**
  232.      * Most tokens only need highlighting, and this method handles them
  233.      */
  234.     function attrHandler($word$pevent)
  235.     {
  236.         if ($word == "\n"{
  237.             $this->newLineNum();
  238.             return;
  239.         }
  240.         if ($e $this->checkEventPush($word$pevent)) {
  241.             if ($e == TUTORIAL_EVENT_SINGLEQUOTE || $e == TUTORIAL_EVENT_DOUBLEQUOTE{
  242.                 $this->_addoutput($word);
  243.             }
  244.             return;
  245.         }
  246.         if ($this->checkEventPop($word$pevent)) {
  247.             $this->_wp->backupPos($word);
  248.             return;
  249.         }
  250.         $this->_addoutput($word);
  251.     }
  252.     
  253.     /**#@+
  254.      * Output Methods
  255.      * @access private
  256.      */
  257.     /**
  258.      * This method adds output to {@link $_line}
  259.      *
  260.      * If a string with variables like "$test this" is present, then special
  261.      * handling is used to allow processing of the variable in context.
  262.      * @see _flush_save()
  263.      */
  264.     function _addoutput($word$preformatted false)
  265.     {
  266.         $type =
  267.         array(
  268.             TUTORIAL_EVENT_ATTRIBUTE => 'attribute',
  269.             TUTORIAL_EVENT_SINGLEQUOTE => 'attributevalue',
  270.             TUTORIAL_EVENT_DOUBLEQUOTE => 'attributevalue',
  271.             TUTORIAL_EVENT_CLOSETAG => 'closetag',
  272.             TUTORIAL_EVENT_ENTITY => 'entity',
  273.             TUTORIAL_EVENT_ITAG => 'itag',
  274.             TUTORIAL_EVENT_OPENTAG => 'opentag',
  275.             TUTORIAL_EVENT_COMMENT => 'comment',
  276.         );
  277.         $a $this->_event_stack->getEvent();
  278.         if (in_array($aarray_keys($type))) {
  279.             $this->_line .= $this->_converter->highlightTutorialSource($type[$a]$word);
  280.         else {
  281.             $this->_line .= $this->_converter->flushHighlightCache();
  282.             $this->_line .= $this->_converter->postProcess($word);
  283.         }
  284.     }
  285.     /**#@-*/
  286.  
  287.     /**
  288.      * tell the parser's WordParser {@link $wp} to set up tokens to parse words by.
  289.      * tokens are word separators.  In English, a space or punctuation are examples of tokens.
  290.      * In PHP, a token can be a ;, a parenthesis, or even the word "function"
  291.      * @param    $value integer an event number
  292.      * @see WordParser
  293.      */
  294.     
  295.     function configWordParser($e)
  296.     {
  297.         $this->_wp->setSeperator($this->tokens[($e 100)]);
  298.     }
  299.     /**
  300.      * this function checks whether parameter $word is a token for pushing a new event onto the Event Stack.
  301.      * @return mixed    returns false, or the event number
  302.      */
  303.     
  304.     function checkEventPush($word,$pevent)
  305.     {
  306.         $e false;
  307.         if (isset($this->pushEvent[$pevent]))
  308.         {
  309.             if (isset($this->pushEvent[$pevent][strtolower($word)]))
  310.             $e $this->pushEvent[$pevent][strtolower($word)];
  311.         }
  312.         if ($e)
  313.         {
  314.             $this->_event_stack->pushEvent($e);
  315.             return $e;
  316.         else {
  317.             return false;
  318.         }
  319.     }
  320.  
  321.     /**
  322.      * this function checks whether parameter $word is a token for popping the current event off of the Event Stack.
  323.      * @return mixed    returns false, or the event number popped off of the stack
  324.      */
  325.     
  326.     function checkEventPop($word,$pevent)
  327.     {
  328.         if (!isset($this->popEvent[$pevent])) return false;
  329.         if (in_array(strtolower($word),$this->popEvent[$pevent]))
  330.         {
  331.             return $this->_event_stack->popEvent();
  332.         else {
  333.             return false;
  334.         }
  335.     }
  336.  
  337.     /**
  338.      * Initialize all parser state variables
  339.      * @param boolean true if we are highlighting an inline {@}source} tag's
  340.      *                 output
  341.      * @param false|stringname of class we are going to start from
  342.      * @uses $_wp sets to a new {@link phpDocumentor_HighlightWordParser}
  343.      */
  344.     function setupStates($parsedata)
  345.     {
  346.         $this->_output '';
  347.         $this->_line '';
  348.         unset($this->_wp);
  349.         $this->_wp new WordParser;
  350.         $this->_wp->setup($parsedata);
  351.         $this->_event_stack new EventStack;
  352.         $this->_event_stack->popEvent();
  353.         $this->_event_stack->pushEvent(TUTORIAL_EVENT_NOEVENTS);
  354.         $this->_pv_linenum null;
  355.         $this->_pv_next_word false;
  356.     }
  357.  
  358.     /**
  359.      * Initialize the {@link $tokenpushEvent, $wordpushEvent} arrays
  360.      */
  361.     {
  362.         $this->allowableInlineTags $GLOBALS['_phpDocumentor_inline_tutorial_tags_allowed'];
  363.         $this->inlineTagHandlers array('*' => 'handleDefaultInlineTag');
  364.         $this->tokens[STATE_TUTORIAL_NOEVENTS]        array("\n",'{@''<!--''</''<''&');
  365.         $this->tokens[STATE_TUTORIAL_ITAG]        array("\n","}");
  366.         $this->tokens[STATE_TUTORIAL_OPENTAG]        array("\n","\t"," "'>''/>');
  367.         $this->tokens[STATE_TUTORIAL_CLOSETAG]        array("\n",'>');
  368.         $this->tokens[STATE_TUTORIAL_COMMENT]        array("\n",'-->');
  369.         $this->tokens[STATE_TUTORIAL_ENTITY]        array("\n",';');
  370.         $this->tokens[STATE_TUTORIAL_ATTRIBUTE]        array("\n",'"',"'",'>','/>');
  371.         $this->tokens[STATE_TUTORIAL_DOUBLEQUOTE]        array("\n",'"','&','{@');
  372.         $this->tokens[STATE_TUTORIAL_SINGLEQUOTE]        array("\n","'",'&','{@');
  373. /**************************************************************/
  374.  
  375.         $this->pushEvent[TUTORIAL_EVENT_NOEVENTS
  376.             array(
  377.                 "{@" => TUTORIAL_EVENT_ITAG,
  378.                 '<' => TUTORIAL_EVENT_OPENTAG,
  379.                 '</' => TUTORIAL_EVENT_CLOSETAG,
  380.                 '&' => TUTORIAL_EVENT_ENTITY,
  381.                 '<!--' => TUTORIAL_EVENT_COMMENT,
  382.             );
  383. /**************************************************************/
  384.  
  385.         $this->pushEvent[TUTORIAL_EVENT_OPENTAG
  386.             array(
  387.                 " " => TUTORIAL_EVENT_ATTRIBUTE,
  388.                 "\n" => TUTORIAL_EVENT_ATTRIBUTE,
  389.             );
  390. /**************************************************************/
  391.  
  392.         $this->pushEvent[TUTORIAL_EVENT_ATTRIBUTE
  393.             array(
  394.                 "'" => TUTORIAL_EVENT_SINGLEQUOTE,
  395.                 '"' => TUTORIAL_EVENT_DOUBLEQUOTE,
  396.             );
  397. /**************************************************************/
  398.  
  399.         $this->pushEvent[TUTORIAL_EVENT_SINGLEQUOTE
  400.             array(
  401.                 '&' => TUTORIAL_EVENT_ENTITY,
  402.                 '{@' => TUTORIAL_EVENT_ITAG,
  403.             );
  404. /**************************************************************/
  405.  
  406.         $this->pushEvent[TUTORIAL_EVENT_DOUBLEQUOTE
  407.             array(
  408.                 '&' => TUTORIAL_EVENT_ENTITY,
  409.                 '{@' => TUTORIAL_EVENT_ITAG,
  410.             );
  411. /**************************************************************/
  412.  
  413.         $this->popEvent[TUTORIAL_EVENT_ENTITYarray(';');
  414. /**************************************************************/
  415.  
  416.         $this->popEvent[TUTORIAL_EVENT_SINGLEQUOTEarray("'");
  417. /**************************************************************/
  418.  
  419.         $this->popEvent[TUTORIAL_EVENT_DOUBLEQUOTEarray('"');
  420. /**************************************************************/
  421.  
  422.         $this->popEvent[TUTORIAL_EVENT_OPENTAGarray('>''/>');
  423. /**************************************************************/
  424.  
  425.         $this->popEvent[TUTORIAL_EVENT_CLOSETAGarray('>');
  426. /**************************************************************/
  427.  
  428.         $this->popEvent[TUTORIAL_EVENT_COMMENTarray('-->');
  429. /**************************************************************/
  430.  
  431.         $this->popEvent[TUTORIAL_EVENT_ATTRIBUTEarray('>','/>');
  432. /**************************************************************/
  433.  
  434.         $this->popEvent[TUTORIAL_EVENT_ITAGarray('}');
  435. /**************************************************************/
  436.     }
  437.  
  438.     function getParserEventName ($value)
  439.     {    
  440.         $lookup array(
  441.             TUTORIAL_EVENT_NOEVENTS         => "TUTORIAL_EVENT_NOEVENTS",
  442.             TUTORIAL_EVENT_ITAG         => "TUTORIAL_EVENT_ITAG",
  443.             TUTORIAL_EVENT_OPENTAG         => "TUTORIAL_EVENT_OPENTAG",
  444.             TUTORIAL_EVENT_ATTRIBUTE         => "TUTORIAL_EVENT_ATTRIBUTE",
  445.             TUTORIAL_EVENT_CLOSETAG         => "TUTORIAL_EVENT_CLOSETAG",
  446.             TUTORIAL_EVENT_ENTITY         => "TUTORIAL_EVENT_ENTITY",
  447.             TUTORIAL_EVENT_COMMENT         => "TUTORIAL_EVENT_COMMENT",
  448.             TUTORIAL_EVENT_SINGLEQUOTE         => "TUTORIAL_EVENT_SINGLEQUOTE",
  449.             TUTORIAL_EVENT_DOUBLEQUOTE         => "TUTORIAL_EVENT_DOUBLEQUOTE",
  450.         );
  451.         if (isset($lookup[$value]))
  452.         return $lookup[$value];
  453.         else return $value;
  454.     }
  455. }
  456.  
  457.  
  458. /** starting state */
  459. define("TUTORIAL_EVENT_NOEVENTS"    ,    1);
  460. /** currently in starting state */
  461. define("STATE_TUTORIAL_NOEVENTS"    ,    101);
  462.  
  463. /** used when an {@}inline tag} is found */
  464. define("TUTORIAL_EVENT_ITAG"    ,    2);
  465. /** currently parsing an {@}inline tag} */
  466. define("STATE_TUTORIAL_ITAG"    ,    102);
  467.  
  468. /** used when an open <tag> is found */
  469. define("TUTORIAL_EVENT_OPENTAG"    ,    3);
  470. /** currently parsing an open <tag> */
  471. define("STATE_TUTORIAL_OPENTAG"    ,    103);
  472.  
  473. /** used when a <tag attr="attribute"> is found */
  474. define("TUTORIAL_EVENT_ATTRIBUTE"    ,    4);
  475. /** currently parsing an open <tag> */
  476. define("STATE_TUTORIAL_ATTRIBUTE"    ,    104);
  477.  
  478. /** used when a close </tag> is found */
  479. define("TUTORIAL_EVENT_CLOSETAG"    ,    5);
  480. /** currently parsing a close </tag> */
  481. define("STATE_TUTORIAL_CLOSETAG"    ,    105);
  482.  
  483. /** used when an &entity; is found */
  484. define("TUTORIAL_EVENT_ENTITY"    ,    6);
  485. /** currently parsing an &entity; */
  486. define("STATE_TUTORIAL_ENTITY"    ,    106);
  487.  
  488. /** used when a <!-- comment --> is found */
  489. define("TUTORIAL_EVENT_COMMENT"    ,    7);
  490. /** currently parsing a <!-- comment --> */
  491. define("STATE_TUTORIAL_COMMENT"    ,    107);
  492.  
  493. /** used when a <!-- comment --> is found */
  494. define("TUTORIAL_EVENT_SINGLEQUOTE"    ,    8);
  495. /** currently parsing a <!-- comment --> */
  496. define("STATE_TUTORIAL_SINGLEQUOTE"    ,    108);
  497.  
  498. /** used when a <!-- comment --> is found */
  499. define("TUTORIAL_EVENT_DOUBLEQUOTE"    ,    9);
  500. /** currently parsing a <!-- comment --> */
  501. define("STATE_TUTORIAL_DOUBLEQUOTE"    ,    109);
  502. ?>

Documentation generated on Tue, 24 Oct 2006 09:26:37 -0500 by phpDocumentor 1.3.1