home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 June / ENTER.ISO / files / xampp-win32-1.4.5-installer.exe / xampp / XMLpackagePageParser.inc < prev    next >
Encoding:
Text File  |  2004-03-24  |  20.8 KB  |  547 lines

  1. <?php
  2. //
  3. // +------------------------------------------------------------------------+
  4. // | phpDocumentor                                                          |
  5. // +------------------------------------------------------------------------+
  6. // | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver                 |
  7. // | Email         jeichorn@phpdoc.org, cellog@phpdoc.org                   |
  8. // | Web           http://www.phpdoc.org                                    |
  9. // | Mirror        http://phpdocu.sourceforge.net/                          |
  10. // | PEAR          http://pear.php.net/package-info.php?pacid=137           |
  11. // +------------------------------------------------------------------------+
  12. // | This source file is subject to version 3.00 of the PHP License,        |
  13. // | that is available at http://www.php.net/license/3_0.txt.               |
  14. // | If you did not receive a copy of the PHP license and are unable to     |
  15. // | obtain it through the world-wide-web, please send a note to            |
  16. // | license@php.net so we can mail you a copy immediately.                 |
  17. // +------------------------------------------------------------------------+
  18. //
  19.  
  20. /**
  21.  * @package phpDocumentor
  22.  * @subpackage Parsers
  23.  * @author Greg Beaver <cellog@users.sourceforge.net>
  24.  * @since 1.2
  25.  */
  26. /** when <programlisting> is found */
  27. define('PHPDOCUMENTOR_PDP_EVENT_PROGRAMLISTING', 600);
  28. /** when <programlisting> is found */
  29. define('PHPDOCUMENTOR_PDP_STATE_PROGRAMLISTING', 700);
  30. /** when a DocBook <tag> is found */
  31. define('PHPDOCUMENTOR_PDP_EVENT_TAG', 601);
  32. /** when a DocBook <tag> is found */
  33. define('PHPDOCUMENTOR_PDP_STATE_TAG', 701);
  34. /** when <![CDATA[ ]]> is found */
  35. define('PHPDOCUMENTOR_PDP_EVENT_CDATA', 602);
  36. /** when <![CDATA[ ]]> is found */
  37. define('PHPDOCUMENTOR_PDP_STATE_CDATA', 702);
  38. /** when tag attributes name="value" are found */
  39. define('PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES', 603);
  40. /** when tag attributes name="value" are found */
  41. define('PHPDOCUMENTOR_PDP_STATE_ATTRIBUTES', 703);
  42. /** when tag attributes name="value" are found */
  43. define('PHPDOCUMENTOR_PDP_EVENT_ENTITY', 604);
  44. /** when tag attributes name="value" are found */
  45. define('PHPDOCUMENTOR_PDP_STATE_ENTITY', 704);
  46.  
  47. /**
  48.  * Used to parse XML DocBook-based tutorials
  49.  * @package phpDocumentor
  50.  * @subpackage Parsers
  51.  * @author Greg Beaver <cellog@users.sourceforge.net>
  52.  * @since 1.2
  53.  */
  54. class XMLPackagePageParser extends Parser
  55. {
  56.     var $eventHandlers = array(
  57.                                PHPDOCUMENTOR_PDP_EVENT_TAG => 'handleTag',
  58.                                PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES => 'handleAttributes',
  59.                                PHPDOCUMENTOR_PDP_EVENT_CDATA => 'handleCData',
  60.                                PARSER_EVENT_NOEVENTS => 'defaultHandler',
  61.                                PARSER_EVENT_COMMENTBLOCK => 'ignoreHandler',
  62.                                PARSER_EVENT_OUTPHP => 'ignoreHandler',
  63.                                PARSER_EVENT_QUOTE => 'handleQuote',
  64.                                PHPDOCUMENTOR_PDP_EVENT_ENTITY => 'handleEntity',
  65.                                );
  66.     
  67.     /**
  68.      * @var array
  69.      */
  70.     var $pars = array();
  71.     
  72.     var $refsect1id = false;
  73.     var $refsect2id = false;
  74.     var $refsect3id = false;
  75.     /**
  76.      * @var array the tag stack
  77.      */
  78.     var $context;
  79.     /**#@+ @access private */
  80.     var $_gettoc = false;
  81.     var $_toc = array();
  82.     var $_cursection = 0;
  83.     /**#@-*/
  84.     /**
  85.      * Set up the wordparser
  86.      *
  87.      * {@source}
  88.      * @uses ObjectWordParser
  89.      */
  90.     function XMLPackagePageParser()
  91.     {
  92.         $this->wp = new ObjectWordParser(true);
  93.     }
  94.     /**
  95.      * Parse a new file
  96.      *
  97.      * @param    string    $parse_data
  98.      * @param    array    $tutorial for format, see {@link Io::getTutorials()}
  99.      * @staticvar    integer    used for recursion limiting if a handler for an event is not found
  100.      * @return    bool
  101.      * @uses parserTutorial using {@link Publisher::PublishEvent()}, a new tutorial
  102.      *                      is created from the file parsed, and passed to the
  103.      *                      Intermediate Parser
  104.      */
  105.     function parse ($parse_data, $tutorial)
  106.     {
  107.         $tempparse = new ppageParser;
  108.         $parse_data = $tempparse->parse($parse_data,true,$tutorial['package'],$tutorial['subpackage'],basename($tutorial['path'],$tutorial['category']));
  109.         unset($tempparse);
  110.         static $endrecur = 0;
  111.         if (!is_array($parse_data) || count($parse_data) == 0)
  112.         {
  113.             return false;
  114.         }
  115.         $this->setupStates();
  116.  
  117.         // initialize variables so E_ALL error_reporting doesn't complain
  118.         $pevent = 0;
  119.         $word = 0;
  120.         $this->p_vars['start'] = true;
  121.         $this->p_vars['event_stack'] = new EventStack;
  122.  
  123.         $this->wp->setup($parse_data,false);
  124.         $this->wp->setWhitespace(true);
  125.         $this->context = array();
  126.         if (isset($this->curtag)) unset($this->curtag);
  127.  
  128.         do
  129.         {
  130.             $lpevent = $pevent;
  131.             $pevent = $this->p_vars['event_stack']->getEvent();
  132.             if ($lpevent != $pevent)
  133.             {
  134.                 $this->p_vars['last_pevent'] = $lpevent;
  135.             }
  136.  
  137.             if ($this->p_vars['last_pevent'] != $pevent)
  138.             {
  139.                 // its a new event so the word parser needs to be reconfigured 
  140.                 $this->configWordParser($pevent);
  141.             }
  142.  
  143.  
  144.             $this->p_vars['last_word'] = $word;
  145.             $word = $this->wp->getWord();
  146.  
  147.             if (0)//PHPDOCUMENTOR_DEBUG == true)
  148.             {
  149.                 echo "----------------\n";
  150.                 echo "LAST: |" . $this->p_vars['last_word'] . "|\n";
  151. //                echo "INDEX: ".$this->p_vars['curpar']."\n";
  152.                 echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";
  153.                 echo "LASTPEVENT: " . $this->getParserEventName($this->p_vars['last_pevent']) . "\n";
  154.                 echo $this->wp->getPos() . " WORD: |$word|\n\n";
  155. //                echo '"'.$this->p_vars['quote_data']."\"\n";
  156.             }
  157.             if (isset($this->eventHandlers[$pevent]))
  158.             {
  159.                 $handle = $this->eventHandlers[$pevent];
  160.                 if ($word !== false) $this->$handle($word, $pevent);
  161.             } else
  162.             {
  163.                 debug('WARNING: possible error, no XMLPackagePageParser handler for event number '.$pevent);
  164.                 if ($endrecur++ == 25)
  165.                 {
  166.                     die("FATAL ERROR, recursion limit reached");
  167.                 }
  168.             }
  169.             $this->p_vars['start'] = false;
  170.         } while (!($word === false));
  171.         if (count($this->_toc) && isset($this->p_vars['toc']))
  172.         {
  173.             $a = $this->curtag->getTOC($this->p_vars['toc']);
  174.             $a->setTOC($this->_toc);
  175.             $a->setPath($tutorial['path']);
  176.             $this->curtag->setTOC($this->p_vars['toc'],$a);
  177.         }
  178.         $this->PublishEvent(PHPDOCUMENTOR_EVENT_TUTORIAL,new parserTutorial($this->curtag, $tutorial));
  179.         return $this->curtag;
  180.     }
  181.     
  182.     /**#@+
  183.      * @access private
  184.      * @param string|parserInlineTag token
  185.      * @param integer parser event
  186.      */
  187.     function defaultHandler($word, $pevent)
  188.     {
  189.         if (is_string($word) && $this->checkEventPush($word, $pevent))
  190.         {
  191.             return;
  192.         }
  193.     }
  194.     
  195.     function ignoreHandler($word, $pevent)
  196.     {
  197.         $this->checkEventPop($word, $pevent);
  198.     }
  199.     
  200.     /**
  201.      * handler for QUOTE.
  202.      * this handler recognizes strings defined with double quotation marks (") and handles them correctly
  203.      * in any place that they legally appear in php code
  204.      */
  205.     
  206.     function handleQuote($word, $pevent)
  207.     {
  208.         if ($this->p_flags['reset_quote_data'] === true)
  209.         {
  210.             $this->p_flags['reset_quote_data'] = false;
  211.             $this->p_vars['quote_data'] = "";
  212.         }
  213.         if (!is_object($word)) $this->checkEventPush( $word, $pevent);
  214.         if ($word != "\"")
  215.         {
  216.             if (is_object($word))
  217.             {
  218.                 $this->p_vars['quote_data'] = $word;
  219.             }
  220.             else
  221.             {
  222.                 if (!is_object($this->p_vars['quote_data']))
  223.                 $this->p_vars['quote_data'] .= $word;
  224.             }
  225.         }
  226.         if (!is_object($word))
  227.         {
  228.             if ($word == '>')
  229.             {
  230.                 if (is_object($this->p_vars['quote_data'])) $this->p_vars['quote_data'] = '{@id '.$this->p_vars['quote_data']->id.'}';
  231.                 addErrorDie(PDERROR_UNTERMINATED_ATTRIB,$this->curtag->name,$this->p_vars['attrname'],$this->p_vars['quote_data']);
  232.             }
  233.             if ($this->checkEventPop($word,$pevent))
  234.             {
  235.                 $this->p_flags['reset_quote_data'] = true;
  236.             }
  237.         }
  238.     }
  239.     
  240.     /**
  241.      * Handles all XML DocBook tags
  242.      */
  243.     function handleTag($word, $pevent)
  244.     {
  245.         if (isset($this->curtag) && $this->curtag->hasTitle() && $this->_gettoc && $this->_gettoc->name == $this->curtag->name)
  246.         {
  247.             if (isset($this->_toc[$this->_cursection]))
  248.             {
  249.                 $this->_toc[$this->_cursection]['title'] = $this->curtag->_title;
  250.                 $this->_cursection++;
  251.             }
  252.             $this->_gettoc = false;
  253.         }
  254.         if ($this->p_vars['last_word'] == '<')
  255.         { // get tag name
  256.             $this->p_flags['begin_tag'] = true;
  257.             array_push($this->context,$word);
  258. //            if (isset($this->curtag)) debug("pushed ".$this->curtag->name);
  259.             if (isset($this->curtag))
  260.             {
  261.                 array_push($this->pars,$this->curtag);
  262.             }
  263.             $this->curtag = new parserXMLDocBookTag($word);
  264.         } elseif ($this->p_vars['last_word'] == '</')
  265.         {
  266.             $tag = array_pop($this->context);
  267.             if ($tag != $word)
  268.             {
  269.                 addErrorDie(PDERROR_UNMATCHED_TUTORIAL_TAG,$tag,$word,$this->curtag->getString());
  270.             }
  271.             if (in_array($this->curtag->name, array('refentry', 'refsect1', 'refsect2', 'refsect3')))
  272.             {
  273.                 if (!isset($this->curtag->_id))
  274.                 {
  275.                     $title = '';
  276.                     if (isset($this->curtag->_title))
  277.                     {
  278.                         $title = $this->curtag->_title->getString();
  279.                     }
  280.                     addWarning(PDERROR_NO_DOCBOOK_ID, $this->curtag->name, $title);
  281.                 }
  282.             }
  283.             $this->p_flags['begin_tag'] = false;
  284.             $curtag = @array_pop($this->pars);
  285. //            debug("popped $tag ".$curtag->name.' I am '.$this->curtag->name);
  286.             if ($curtag)
  287.             {
  288.                 if ($this->curtag->name == 'refsect1') $this->refsect1id = false;
  289.                 if ($this->curtag->name == 'refsect2') $this->refsect2id = false;
  290.                 if ($this->curtag->name == 'refsect3') $this->refsect3id = false;
  291.                 $curtag->add($this->curtag);
  292. //                debug("added ".$this->curtag->name." to ".$curtag->name.' '.$curtag->id);
  293.                 $this->curtag = $curtag;
  294.             } else
  295.             {
  296. //                debug("here");
  297.             }
  298.         } elseif (is_string($word))
  299.         {
  300.             if (!($e = $this->checkEventPush($word, $pevent)))
  301.             {
  302.                 if ($this->checkEventPop($word, $pevent))
  303.                 {
  304.                     if ($this->p_flags['begin_tag'])
  305.                     {
  306.                         $this->p_vars['event_stack']->pushEvent(PHPDOCUMENTOR_PDP_EVENT_TAG);
  307.                         $this->p_vars['event_stack']->pushEvent(PHPDOCUMENTOR_PDP_EVENT_CDATA);
  308.                         $this->p_vars['last_tag'] = array_pop($this->context);
  309.                         array_push($this->context,$this->p_vars['last_tag']);
  310.                         $this->p_flags['in_cdata'] = false;
  311.                     }
  312.                     return;
  313.                 }
  314.             } else
  315.             {
  316.                 $this->p_flags['start_attr'] = true;
  317.                 $this->p_flags['end_attr'] = false;
  318.             }
  319.         } else addErrorDie(PDERROR_CANT_HAVE_INLINE_IN_TAGNAME);
  320.     }
  321.     
  322.     /**
  323.      * Handle CData sections
  324.      */
  325.     function handleCData($word, $pevent)
  326.     {
  327.         if ($this->curtag->name == 'refentry' && get_class($word) == 'parsertocinlinetag')
  328.         {
  329.             $this->p_vars['toc'] = $this->curtag->getTOC();
  330.         }
  331.         if (is_string($word) && !$this->p_flags['in_cdata'])
  332.         {
  333.             if ($this->checkEventPop($word, $pevent))
  334.             {
  335.                 return;
  336.             }
  337.             if ($this->checkEventPush($word, $pevent))
  338.             {
  339.                 return;
  340.             }
  341.         }
  342.         if ($word == '<![CDATA[')
  343.         {
  344.             $this->curtag->startCData();
  345.             $this->p_flags['in_cdata'] = true;
  346.         } elseif ($this->p_flags['in_cdata'] && $word == ']]>')
  347.         {
  348.             $this->curtag->endCData();
  349.             $this->p_flags['in_cdata'] = false;
  350.         } else
  351.         {
  352.             if ($this->p_flags['in_cdata'])
  353.             $this->curtag->addCData($word);
  354.             else
  355.             $this->curtag->add($word);
  356.         }
  357.     }
  358.     
  359.     /**
  360.      * Handle Entities like ”
  361.      */
  362.     function handleEntity($word, $pevent)
  363.     {
  364.         if (!$word)
  365.         {
  366.             if (!isset($this->p_vars['entity_name']))
  367.                 $this->p_vars['entity_name'] = '';
  368.             addErrorDie(PDERROR_UNTERMINATED_ENTITY,$this->p_vars['entity_name']);
  369.         }
  370.         $e = $this->checkEventPop($word, $pevent);
  371.         if ($word && !$e) $this->p_vars['entity_name'] = $word;
  372.         if ($e)
  373.         {
  374.             $entity = new parserEntity($this->p_vars['entity_name']);
  375.             unset($this->p_vars['entity_name']);
  376.             $this->curtag->add($entity);
  377.         }
  378.     }
  379.     
  380.     /**
  381.      * Handle Tag attributes name="value"
  382.      */
  383.     function handleAttributes($word, $pevent)
  384.     {
  385.         if ($this->checkEventPush($word, $pevent)) return;
  386.         if ($word == '=')
  387.         {
  388.             $this->p_flags['start_attr'] = false;
  389.             $this->p_vars['end_attr'] = true;
  390.         } else
  391.         {
  392.             if ($this->p_flags['start_attr'])
  393.             {
  394.                 $this->p_vars['attrname'] = $word;
  395.             } else
  396.             {
  397.                 if (isset($this->p_vars['attrname']))
  398.                 {
  399.                     $value = $this->p_vars['quote_data'];
  400.                     if (get_class($value) == 'parseridinlinetag')
  401.                     { // "inherit" the parent section's id, so
  402.                       // <refsect1 id="{@id test"}> <!-- id is 'test' -->
  403.                       // ...
  404.                       //  <refsect2 id="{@id me}"> <!-- id is 'test.me' -->
  405.                       //  ...
  406.                       //   <refsect3 id="{@id out}"> <!-- id is 'test.me.out' -->
  407.                       //    <example id="{@id withexample}"> <!-- id is 'test.me.out.withexample' -->
  408.                         $a = ($this->refsect1id ? $this->refsect1id . '.' : '');
  409.                         $a .= ($this->refsect2id ? $this->refsect2id . '.' : '');
  410.                         $a .= ($this->refsect3id ? $this->refsect3id . '.' : '');
  411.                         if ($this->curtag->name == 'refsect1')
  412.                         {
  413.                             $this->refsect1id = $value->id;
  414.                         }
  415.                         if ($this->curtag->name == 'refsect2')
  416.                         {
  417.                             $this->refsect2id = $value->id;
  418.                         }
  419.                         if ($this->curtag->name == 'refsect3')
  420.                         {
  421.                             $this->refsect3id = $value->id;
  422.                         }
  423. //                            debug($value->id.' is now '.$a.$value->id);
  424.                         $value->id = $a . $value->id;
  425.                         if ($value->id != '')
  426.                         {
  427.                             if (isset($this->_toc[$this->_cursection]))
  428.                             {
  429.                                 $this->_cursection++;
  430.                             }
  431.                             $this->_toc[$this->_cursection]['id'] = $value;
  432.                             $this->_toc[$this->_cursection]['tag'] = new parserXMLDocBookTag($this->curtag->name);
  433. //                            debug("set gettoc to ".$this->curtag->name .' '. $value->id);
  434.                             $this->_gettoc = $this->curtag;
  435.                         }
  436.                     }
  437.                     $this->curtag->addAttribute($this->p_vars['attrname'],$value);
  438.                     unset($this->p_vars['attrname']);
  439.                     $this->p_flags['end_attr'] = false;
  440.                 }
  441.             }
  442.         }
  443.         if (is_string($word) && $this->checkEventPop($word, $pevent))
  444.         {
  445.             $this->p_flags['start_attr'] = true;
  446.             $this->p_flags['end_attr'] = false;
  447.             $this->wp->setPos($this->wp->getPos() - strlen($word));
  448.         }
  449.     }
  450.     /**#@-*/
  451.     
  452.     /**
  453.      * setup the parser tokens, and the pushEvent/popEvent arrays
  454.      * @see $tokens, $pushEvent, $popEvent
  455.      */
  456.     
  457.     function setupStates()
  458.     {
  459.         $this->_gettoc = false;
  460.         $this->_toc = array();
  461.         $this->_cursection = 0;
  462.         if (isset($this->p_vars['toc'])) unset($this->p_vars['toc']);
  463.         
  464.         $this->tokens[STATE_NOEVENTS]                     = array('</','<','<!--','<?');
  465.         $this->tokens[STATE_COMMENTBLOCK]                 = array('-->');
  466.         $this->tokens[STATE_OUTPHP]                       = array('?>');
  467.         $this->tokens[STATE_QUOTE]                        = array("\\\"","\\\\","\"",'>');
  468.         $this->tokens[STATE_ESCAPE]                       = false;// this tells the word parser to just cycle
  469.         $this->tokens[PHPDOCUMENTOR_PDP_STATE_TAG]        = array('>',' ');
  470.         $this->tokens[PHPDOCUMENTOR_PDP_STATE_CDATA]      = array('&','<!--','</','<![CDATA[','<',']]>');
  471.         $this->tokens[PHPDOCUMENTOR_PDP_STATE_ATTRIBUTES] = array('=','>','"');
  472.         $this->tokens[PHPDOCUMENTOR_PDP_STATE_ENTITY]     = array(';');
  473.  
  474.         // For each event word to event mapings
  475.         $this->pushEvent[PARSER_EVENT_NOEVENTS] = 
  476.             array(
  477.                 "<" => PHPDOCUMENTOR_PDP_EVENT_TAG,
  478.                 "</" => PHPDOCUMENTOR_PDP_EVENT_TAG,
  479.                 '<!--' => PARSER_EVENT_COMMENTBLOCK,
  480.                 '<?' => PARSER_EVENT_OUTPHP,
  481.                 '&' => PHPDOCUMENTOR_PDP_EVENT_ENTITY,
  482.             );
  483. ##########################
  484.  
  485.         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_TAG] =
  486.             array(
  487.                 ' ' => PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES,
  488.             );
  489.          
  490.         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_TAG] = array(">");
  491. ##########################
  492.         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES] =
  493.             array(
  494.                 '"' => PARSER_EVENT_QUOTE,
  495.             );
  496.  
  497.         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES] = array(">");
  498. ##########################
  499.  
  500.         $this->popEvent[PARSER_EVENT_COMMENTBLOCK] = array("-->");
  501. ##########################
  502.         $this->pushEvent[PARSER_EVENT_QUOTE] = 
  503.             array(
  504.                 "\\"    => PARSER_EVENT_ESCAPE
  505.             );
  506.         $this->popEvent[PARSER_EVENT_QUOTE] = array("\"");
  507. ##########################
  508.  
  509.         $this->popEvent[PARSER_EVENT_OUTPHP] = array("?>");
  510. ##########################
  511.  
  512.         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_ENTITY] = array(";");
  513. ##########################
  514.  
  515.         $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_CDATA] =
  516.             array(
  517.                 "<" => PHPDOCUMENTOR_PDP_EVENT_TAG,
  518.                 '<!--' => PARSER_EVENT_COMMENTBLOCK,
  519.                 '<?' => PARSER_EVENT_OUTPHP,
  520.                 '&' => PHPDOCUMENTOR_PDP_EVENT_ENTITY,
  521.             );
  522.         $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_CDATA] = array("</");
  523.     }
  524.     
  525.     /**
  526.      * debugging function
  527.      *
  528.      * {@source}
  529.      * @static
  530.      */
  531.     function getParserEventName ($value)
  532.     {    
  533.         $lookup = array(
  534.             PARSER_EVENT_NOEVENTS         => "PARSER_EVENT_NOEVENTS",
  535.             PHPDOCUMENTOR_PDP_EVENT_TAG        => "PHPDOCUMENTOR_PDP_EVENT_TAG",
  536.             PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES        => "PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES",
  537.             PHPDOCUMENTOR_PDP_EVENT_CDATA        => "PHPDOCUMENTOR_PDP_EVENT_CDATA",
  538.             PHPDOCUMENTOR_PDP_EVENT_LIST    => "PHPDOCUMENTOR_PDP_EVENT_LIST",
  539.             PARSER_EVENT_QUOTE  => "PARSER_EVENT_QUOTE",
  540.             PHPDOCUMENTOR_PDP_EVENT_ENTITY => "PHPDOCUMENTOR_PDP_EVENT_ENTITY",
  541.         );
  542.         if (isset($lookup[$value]))
  543.         return $lookup[$value];
  544.         else return $value;
  545.     }
  546. }
  547. ?>