"Fossies" - the Fresh Open Source Software Archive

Member "yii-1.1.22.bf1d26/framework/vendors/TextHighlighter/Text/Highlighter/Generator.php" (16 Jan 2020, 36881 Bytes) of package /linux/www/yii-1.1.22.bf1d26.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Generator.php" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.1.21.733ac5_vs_1.1.22.bf1d26.

    1 <?php
    2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
    3 /**
    4 * Syntax highlighter class generator
    5 *
    6 * To simplify the process of creating new syntax highlighters
    7 * for different languages, {@link Text_Highlighter_Generator} class is
    8 * provided. It takes highlighting rules from XML file and generates
    9 * a code of a class inherited from {@link Text_Highlighter}.
   10 *
   11 * PHP versions 4 and 5
   12 *
   13 * LICENSE: This source file is subject to version 3.0 of the PHP license
   14 * that is available through the world-wide-web at the following URI:
   15 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
   16 * the PHP License and are unable to obtain it through the web, please
   17 * send a note to license@php.net so we can mail you a copy immediately.
   18 *
   19 * @category   Text
   20 * @package    Text_Highlighter
   21 * @author     Andrey Demenev <demenev@gmail.com>
   22 * @copyright  2004-2006 Andrey Demenev
   23 * @license    http://www.php.net/license/3_0.txt  PHP License
   24 * @version    CVS: $Id: Generator.php,v 1.1 2007/06/03 02:36:35 ssttoo Exp $
   25 * @link       http://pear.php.net/package/Text_Highlighter
   26 */
   27 
   28 // {{{ error codes
   29 
   30 define ('TEXT_HIGHLIGHTER_EMPTY_RE',          1);
   31 define ('TEXT_HIGHLIGHTER_INVALID_RE',        2);
   32 define ('TEXT_HIGHLIGHTER_EMPTY_OR_MISSING',  3);
   33 define ('TEXT_HIGHLIGHTER_EMPTY',             4);
   34 define ('TEXT_HIGHLIGHTER_REGION_REGION',     5);
   35 define ('TEXT_HIGHLIGHTER_REGION_BLOCK',      6);
   36 define ('TEXT_HIGHLIGHTER_BLOCK_REGION',      7);
   37 define ('TEXT_HIGHLIGHTER_KEYWORD_BLOCK',     8);
   38 define ('TEXT_HIGHLIGHTER_KEYWORD_INHERITS',  9);
   39 define ('TEXT_HIGHLIGHTER_PARSE',            10);
   40 define ('TEXT_HIGHLIGHTER_FILE_WRITE',       11);
   41 define ('TEXT_HIGHLIGHTER_FILE_READ',        12);
   42 // }}}
   43 
   44 /**
   45 * Syntax highliter class generator class
   46 *
   47 * This class is used to generate PHP classes
   48 * from XML files with highlighting rules
   49 *
   50 * Usage example
   51 * <code>
   52 *require_once 'Text/Highlighter/Generator.php';
   53 *$generator =& new Text_Highlighter_Generator('php.xml');
   54 *$generator->generate();
   55 *$generator->saveCode('PHP.php');
   56 * </code>
   57 *
   58 * A command line script <b>generate</b> is provided for
   59 * class generation (installs in scripts/Text/Highlighter).
   60 *
   61 * @author     Andrey Demenev <demenev@gmail.com>
   62 * @copyright  2004-2006 Andrey Demenev
   63 * @license    http://www.php.net/license/3_0.txt  PHP License
   64 * @version    Release: 0.7.1
   65 * @link       http://pear.php.net/package/Text_Highlighter
   66 */
   67 
   68 class Text_Highlighter_Generator extends  XML_Parser
   69 {
   70     // {{{ properties
   71     /**
   72     * Whether to do case folding.
   73     * We have to declare it here, because XML_Parser
   74     * sets case folding in constructor
   75     *
   76     * @var  boolean
   77     */
   78     var $folding = false;
   79 
   80     /**
   81     * Holds name of file with highlighting rules
   82     *
   83     * @var string
   84     * @access private
   85     */
   86     var $_syntaxFile;
   87 
   88     /**
   89     * Current element being processed
   90     *
   91     * @var array
   92     * @access private
   93     */
   94     var $_element;
   95 
   96     /**
   97     * List of regions
   98     *
   99     * @var array
  100     * @access private
  101     */
  102     var $_regions = array();
  103 
  104     /**
  105     * List of blocks
  106     *
  107     * @var array
  108     * @access private
  109     */
  110     var $_blocks = array();
  111 
  112     /**
  113     * List of keyword groups
  114     *
  115     * @var array
  116     * @access private
  117     */
  118     var $_keywords = array();
  119 
  120     /**
  121     * List of authors
  122     *
  123     * @var array
  124     * @access private
  125     */
  126     var $_authors = array();
  127 
  128     /**
  129     * Name of language
  130     *
  131     * @var string
  132     * @access public
  133     */
  134     var $language = '';
  135 
  136     /**
  137     * Generated code
  138     *
  139     * @var string
  140     * @access private
  141     */
  142     var $_code = '';
  143 
  144     /**
  145     * Default class
  146     *
  147     * @var string
  148     * @access private
  149     */
  150     var $_defClass = 'default';
  151 
  152     /**
  153     * Comment
  154     *
  155     * @var string
  156     * @access private
  157     */
  158     var $_comment = '';
  159 
  160     /**
  161     * Flag for comment processing
  162     *
  163     * @var boolean
  164     * @access private
  165     */
  166     var $_inComment = false;
  167 
  168     /**
  169     * Sorting order of current block/region
  170     *
  171     * @var integer
  172     * @access private
  173     */
  174     var $_blockOrder = 0;
  175 
  176     /**
  177     * Generation errors
  178     *
  179     * @var array
  180     * @access private
  181     */
  182     var $_errors;
  183 
  184     // }}}
  185     // {{{ constructor
  186 
  187     /**
  188     * Constructor
  189     *
  190     * @param string $syntaxFile Name of XML file
  191     * with syntax highlighting rules
  192     *
  193     * @access public
  194     */
  195 
  196     function __construct($syntaxFile = '')
  197     {
  198         XML_Parser::XML_Parser(null, 'func');
  199         $this->_errors = array();
  200         $this->_declareErrorMessages();
  201         if ($syntaxFile) {
  202             $this->setInputFile($syntaxFile);
  203         }
  204     }
  205 
  206     // }}}
  207     // {{{ _formatError
  208 
  209     /**
  210     * Format error message
  211     *
  212     * @param integer $code error code
  213     * @param string $params parameters
  214     * @param string $fileName file name
  215     * @param integer $lineNo line number
  216     * @return  array
  217     * @access  public
  218     */
  219     function _formatError($code, $params, $fileName, $lineNo)
  220     {
  221         $template = $this->_templates[$code];
  222         $ret = call_user_func_array('sprintf', array_merge(array($template), $params));
  223         if ($fileName) {
  224             $ret = '[' . $fileName . '] ' . $ret;
  225         }
  226         if ($lineNo) {
  227             $ret .= ' (line ' . $lineNo . ')';
  228         }
  229         return $ret;
  230     }
  231 
  232     // }}}
  233     // {{{ declareErrorMessages
  234 
  235     /**
  236     * Set up error message templates
  237     *
  238     * @access  private
  239     */
  240     function _declareErrorMessages()
  241     {
  242         $this->_templates = array (
  243         TEXT_HIGHLIGHTER_EMPTY_RE => 'Empty regular expression',
  244         TEXT_HIGHLIGHTER_INVALID_RE => 'Invalid regular expression : %s',
  245         TEXT_HIGHLIGHTER_EMPTY_OR_MISSING => 'Empty or missing %s',
  246         TEXT_HIGHLIGHTER_EMPTY  => 'Empty %s',
  247         TEXT_HIGHLIGHTER_REGION_REGION => 'Region %s refers undefined region %s',
  248         TEXT_HIGHLIGHTER_REGION_BLOCK => 'Region %s refers undefined block %s',
  249         TEXT_HIGHLIGHTER_BLOCK_REGION => 'Block %s refers undefined region %s',
  250         TEXT_HIGHLIGHTER_KEYWORD_BLOCK => 'Keyword group %s refers undefined block %s',
  251         TEXT_HIGHLIGHTER_KEYWORD_INHERITS => 'Keyword group %s inherits undefined block %s',
  252         TEXT_HIGHLIGHTER_PARSE => '%s',
  253         TEXT_HIGHLIGHTER_FILE_WRITE => 'Error writing file %s',
  254         TEXT_HIGHLIGHTER_FILE_READ => '%s'
  255         );
  256     }
  257 
  258     // }}}
  259     // {{{ setInputFile
  260 
  261     /**
  262     * Sets the input xml file to be parsed
  263     *
  264     * @param    string      Filename (full path)
  265     * @return   boolean
  266     * @access   public
  267     */
  268     function setInputFile($file)
  269     {
  270         $this->_syntaxFile = $file;
  271         $ret = parent::setInputFile($file);
  272         if (PEAR::isError($ret)) {
  273             $this->_error(TEXT_HIGHLIGHTER_FILE_READ, $ret->message);
  274             return false;
  275         }
  276         return true;
  277     }
  278 
  279     // }}}
  280     // {{{ generate
  281 
  282     /**
  283     * Generates class code
  284     *
  285     * @access public
  286     */
  287 
  288     function generate()
  289     {
  290         $this->_regions    = array();
  291         $this->_blocks     = array();
  292         $this->_keywords   = array();
  293         $this->language    = '';
  294         $this->_code       = '';
  295         $this->_defClass   = 'default';
  296         $this->_comment    = '';
  297         $this->_inComment  = false;
  298         $this->_authors    = array();
  299         $this->_blockOrder = 0;
  300         $this->_errors   = array();
  301 
  302         $ret = $this->parse();
  303         if (PEAR::isError($ret)) {
  304             $this->_error(TEXT_HIGHLIGHTER_PARSE, $ret->message);
  305             return false;
  306         }
  307         return true;
  308     }
  309 
  310     // }}}
  311     // {{{ getCode
  312 
  313     /**
  314     * Returns generated code as a string.
  315     *
  316     * @return string Generated code
  317     * @access public
  318     */
  319 
  320     function getCode()
  321     {
  322         return $this->_code;
  323     }
  324 
  325     // }}}
  326     // {{{ saveCode
  327 
  328     /**
  329     * Saves generated class to file. Note that {@link Text_Highlighter::factory()}
  330     * assumes that filename is uppercase (SQL.php, DTD.php, etc), and file
  331     * is located in Text/Highlighter
  332     *
  333     * @param string $filename Name of file to write the code to
  334     * @return boolean true on success, false on failure
  335     * @access public
  336     */
  337 
  338     function saveCode($filename)
  339     {
  340         $f = @fopen($filename, 'wb');
  341         if (!$f) {
  342             $this->_error(TEXT_HIGHLIGHTER_FILE_WRITE, array('outfile'=>$filename));
  343             return false;
  344         }
  345         fwrite ($f, $this->_code);
  346         fclose($f);
  347         return true;
  348     }
  349 
  350     // }}}
  351     // {{{ hasErrors
  352 
  353     /**
  354     * Reports if there were errors
  355     *
  356     * @return boolean
  357     * @access public
  358     */
  359 
  360     function hasErrors()
  361     {
  362         return count($this->_errors) > 0;
  363     }
  364 
  365     // }}}
  366     // {{{ getErrors
  367 
  368     /**
  369     * Returns errors
  370     *
  371     * @return array
  372     * @access public
  373     */
  374 
  375     function getErrors()
  376     {
  377         return $this->_errors;
  378     }
  379 
  380     // }}}
  381     // {{{ _sortBlocks
  382 
  383     /**
  384     * Sorts blocks
  385     *
  386     * @access private
  387     */
  388 
  389     function _sortBlocks($b1, $b2) {
  390         return $b1['order'] - $b2['order'];
  391     }
  392 
  393     // }}}
  394     // {{{ _sortLookFor
  395     /**
  396     * Sort 'look for' list
  397     * @return int
  398     * @param string $b1
  399     * @param string $b2
  400     */
  401     function _sortLookFor($b1, $b2) {
  402         $o1 = isset($this->_blocks[$b1]) ? $this->_blocks[$b1]['order'] : $this->_regions[$b1]['order'];
  403         $o2 = isset($this->_blocks[$b2]) ? $this->_blocks[$b2]['order'] : $this->_regions[$b2]['order'];
  404         return $o1 - $o2;
  405     }
  406 
  407     // }}}
  408     // {{{ _makeRE
  409 
  410     /**
  411     * Adds delimiters and modifiers to regular expression if necessary
  412     *
  413     * @param string $text Original RE
  414     * @return string Final RE
  415     * @access private
  416     */
  417     function _makeRE($text, $case = false)
  418     {
  419         if (!strlen($text)) {
  420             $this->_error(TEXT_HIGHLIGHTER_EMPTY_RE);
  421         }
  422         if (!strlen($text) || $text[0] != '/') {
  423             $text = '/' . $text . '/';
  424         }
  425         if (!$case) {
  426             $text .= 'i';
  427         }
  428         $php_errormsg = '';
  429         @preg_match($text, '');
  430         if ($php_errormsg) {
  431             $this->_error(TEXT_HIGHLIGHTER_INVALID_RE, $php_errormsg);
  432         }
  433         preg_match ('#^/(.+)/(.*)$#', $text, $m);
  434         if (@$m[2]) {
  435             $text = '(?' . $m[2] . ')' . $m[1];
  436         } else {
  437             $text = $m[1];
  438         }
  439         return $text;
  440     }
  441 
  442     // }}}
  443     // {{{ _exportArray
  444 
  445     /**
  446     * Exports array as PHP code
  447     *
  448     * @param array $array
  449     * @return string Code
  450     * @access private
  451     */
  452     function _exportArray($array)
  453     {
  454         $array = var_export($array, true);
  455         return trim(preg_replace('~^(\s*)~m','        \1\1',$array));
  456     }
  457 
  458     // }}}
  459     // {{{ _countSubpatterns
  460     /**
  461     * Find number of capturing suppaterns in regular expression
  462     * @return int
  463     * @param string $re Regular expression (without delimiters)
  464     */
  465     function _countSubpatterns($re)
  466     {
  467         preg_match_all('/' . $re . '/', '', $m);
  468         return count($m)-1;
  469     }
  470 
  471     // }}}
  472 
  473     /**#@+
  474     * @access private
  475     * @param resource $xp      XML parser resource
  476     * @param string   $elem    XML element name
  477     * @param array    $attribs XML element attributes
  478     */
  479 
  480     // {{{ xmltag_Default
  481 
  482     /**
  483     * start handler for <default> element
  484     */
  485     function xmltag_Default($xp, $elem, $attribs)
  486     {
  487         $this->_aliasAttributes($attribs);
  488         if (!isset($attribs['innerGroup']) || $attribs['innerGroup'] === '') {
  489             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'innerGroup');
  490         }
  491         $this->_defClass = @$attribs['innerGroup'];
  492     }
  493 
  494     // }}}
  495     // {{{ xmltag_Region
  496 
  497     /**
  498     * start handler for <region> element
  499     */
  500     function xmltag_Region($xp, $elem, $attribs)
  501     {
  502         $this->_aliasAttributes($attribs);
  503         if (!isset($attribs['name']) || $attribs['name'] === '') {
  504             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'region name');
  505         }
  506         if (!isset($attribs['innerGroup']) || $attribs['innerGroup'] === '') {
  507             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'innerGroup');
  508         }
  509         $this->_element = array('name' => $attribs['name']);
  510         $this->_element['line'] = xml_get_current_line_number($this->parser);
  511         if (isset($attribs['case'])) {
  512             $this->_element['case'] = $attribs['case'] == 'yes';
  513         } else {
  514             $this->_element['case'] = $this->_case;
  515         }
  516         $this->_element['innerGroup'] = $attribs['innerGroup'];
  517         $this->_element['delimGroup'] = isset($attribs['delimGroup']) ?
  518         $attribs['delimGroup'] :
  519         $attribs['innerGroup'];
  520         $this->_element['start'] = $this->_makeRE(@$attribs['start'], $this->_element['case']);
  521         $this->_element['end'] = $this->_makeRE(@$attribs['end'], $this->_element['case']);
  522         $this->_element['contained'] = @$attribs['contained'] == 'yes';
  523         $this->_element['never-contained'] = @$attribs['never-contained'] == 'yes';
  524         $this->_element['remember'] = @$attribs['remember'] == 'yes';
  525         if (isset($attribs['startBOL']) && $attribs['startBOL'] == 'yes') {
  526             $this->_element['startBOL'] = true;
  527         }
  528         if (isset($attribs['endBOL']) && $attribs['endBOL'] == 'yes') {
  529             $this->_element['endBOL'] = true;
  530         }
  531         if (isset($attribs['neverAfter'])) {
  532             $this->_element['neverafter'] = $this->_makeRE($attribs['neverAfter']);
  533         }
  534     }
  535 
  536     // }}}
  537     // {{{ xmltag_Block
  538 
  539     /**
  540     * start handler for <block> element
  541     */
  542     function xmltag_Block($xp, $elem, $attribs)
  543     {
  544         $this->_aliasAttributes($attribs);
  545         if (!isset($attribs['name']) || $attribs['name'] === '') {
  546             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'block name');
  547         }
  548         if (isset($attribs['innerGroup']) && $attribs['innerGroup'] === '') {
  549             $this->_error(TEXT_HIGHLIGHTER_EMPTY, 'innerGroup');
  550         }
  551         $this->_element = array('name' => $attribs['name']);
  552         $this->_element['line'] = xml_get_current_line_number($this->parser);
  553         if (isset($attribs['case'])) {
  554             $this->_element['case'] = $attribs['case'] == 'yes';
  555         } else {
  556             $this->_element['case'] = $this->_case;
  557         }
  558         if (isset($attribs['innerGroup'])) {
  559             $this->_element['innerGroup'] = @$attribs['innerGroup'];
  560         }
  561         $this->_element['match'] = $this->_makeRE($attribs['match'], $this->_element['case']);
  562         $this->_element['contained'] = @$attribs['contained'] == 'yes';
  563         $this->_element['multiline'] = @$attribs['multiline'] == 'yes';
  564         if (isset($attribs['BOL']) && $attribs['BOL'] == 'yes') {
  565             $this->_element['BOL'] = true;
  566         }
  567         if (isset($attribs['neverAfter'])) {
  568             $this->_element['neverafter'] = $this->_makeRE($attribs['neverAfter']);
  569         }
  570     }
  571 
  572     // }}}
  573     // {{{ cdataHandler
  574 
  575     /**
  576     * Character data handler. Used for comment
  577     */
  578     function cdataHandler($xp, $cdata)
  579     {
  580         if ($this->_inComment) {
  581             $this->_comment .= $cdata;
  582         }
  583     }
  584 
  585     // }}}
  586     // {{{ xmltag_Comment
  587 
  588     /**
  589     * start handler for <comment> element
  590     */
  591     function xmltag_Comment($xp, $elem, $attribs)
  592     {
  593         $this->_comment = '';
  594         $this->_inComment = true;
  595     }
  596 
  597     // }}}
  598     // {{{ xmltag_PartGroup
  599 
  600     /**
  601     * start handler for <partgroup> element
  602     */
  603     function xmltag_PartGroup($xp, $elem, $attribs)
  604     {
  605         $this->_aliasAttributes($attribs);
  606         if (!isset($attribs['innerGroup']) || $attribs['innerGroup'] === '') {
  607             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'innerGroup');
  608         }
  609         $this->_element['partClass'][$attribs['index']] = @$attribs['innerGroup'];
  610     }
  611 
  612     // }}}
  613     // {{{ xmltag_PartClass
  614 
  615     /**
  616     * start handler for <partclass> element
  617     */
  618     function xmltag_PartClass($xp, $elem, $attribs)
  619     {
  620         $this->xmltag_PartGroup($xp, $elem, $attribs);
  621     }
  622 
  623     // }}}
  624     // {{{ xmltag_Keywords
  625 
  626     /**
  627     * start handler for <keywords> element
  628     */
  629     function xmltag_Keywords($xp, $elem, $attribs)
  630     {
  631         $this->_aliasAttributes($attribs);
  632         if (!isset($attribs['name']) || $attribs['name'] === '') {
  633             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'keyword group name');
  634         }
  635         if (!isset($attribs['innerGroup']) || $attribs['innerGroup'] === '') {
  636             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'innerGroup');
  637         }
  638         if (!isset($attribs['inherits']) || $attribs['inherits'] === '') {
  639             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'inherits');
  640         }
  641         $this->_element = array('name'=>@$attribs['name']);
  642         $this->_element['line'] = xml_get_current_line_number($this->parser);
  643         $this->_element['innerGroup'] = @$attribs['innerGroup'];
  644         if (isset($attribs['case'])) {
  645             $this->_element['case'] = $attribs['case'] == 'yes';
  646         } else {
  647             $this->_element['case'] = $this->_case;
  648         }
  649         $this->_element['inherits'] = @$attribs['inherits'];
  650         if (isset($attribs['otherwise'])) {
  651             $this->_element['otherwise'] = $attribs['otherwise'];
  652         }
  653         if (isset($attribs['ifdef'])) {
  654             $this->_element['ifdef'] = $attribs['ifdef'];
  655         }
  656         if (isset($attribs['ifndef'])) {
  657             $this->_element['ifndef'] = $attribs['ifndef'];
  658         }
  659     }
  660 
  661     // }}}
  662     // {{{ xmltag_Keyword
  663 
  664     /**
  665     * start handler for <keyword> element
  666     */
  667     function xmltag_Keyword($xp, $elem, $attribs)
  668     {
  669         if (!isset($attribs['match']) || $attribs['match'] === '') {
  670             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'match');
  671         }
  672         $keyword = @$attribs['match'];
  673         if (!$this->_element['case']) {
  674             $keyword = strtolower($keyword);
  675         }
  676         $this->_element['match'][$keyword] = true;
  677     }
  678 
  679     // }}}
  680     // {{{ xmltag_Contains
  681 
  682     /**
  683     * start handler for <contains> element
  684     */
  685     function xmltag_Contains($xp, $elem, $attribs)
  686     {
  687         $this->_element['contains-all'] = @$attribs['all'] == 'yes';
  688         if (isset($attribs['region'])) {
  689             $this->_element['contains']['region'][$attribs['region']] =
  690             xml_get_current_line_number($this->parser);
  691         }
  692         if (isset($attribs['block'])) {
  693             $this->_element['contains']['block'][$attribs['block']] =
  694             xml_get_current_line_number($this->parser);
  695         }
  696     }
  697 
  698     // }}}
  699     // {{{ xmltag_But
  700 
  701     /**
  702     * start handler for <but> element
  703     */
  704     function xmltag_But($xp, $elem, $attribs)
  705     {
  706         if (isset($attribs['region'])) {
  707             $this->_element['not-contains']['region'][$attribs['region']] = true;
  708         }
  709         if (isset($attribs['block'])) {
  710             $this->_element['not-contains']['block'][$attribs['block']] = true;
  711         }
  712     }
  713 
  714     // }}}
  715     // {{{ xmltag_Onlyin
  716 
  717     /**
  718     * start handler for <onlyin> element
  719     */
  720     function xmltag_Onlyin($xp, $elem, $attribs)
  721     {
  722         if (!isset($attribs['region']) || $attribs['region'] === '') {
  723             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'region');
  724         }
  725         $this->_element['onlyin'][$attribs['region']] = xml_get_current_line_number($this->parser);
  726     }
  727 
  728     // }}}
  729     // {{{ xmltag_Author
  730 
  731     /**
  732     * start handler for <author> element
  733     */
  734     function xmltag_Author($xp, $elem, $attribs)
  735     {
  736         if (!isset($attribs['name']) || $attribs['name'] === '') {
  737             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'author name');
  738         }
  739         $this->_authors[] = array(
  740         'name'  => @$attribs['name'],
  741         'email' => (string)@$attribs['email']
  742         );
  743     }
  744 
  745     // }}}
  746     // {{{ xmltag_Highlight
  747 
  748     /**
  749     * start handler for <highlight> element
  750     */
  751     function xmltag_Highlight($xp, $elem, $attribs)
  752     {
  753         if (!isset($attribs['lang']) || $attribs['lang'] === '') {
  754             $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'language name');
  755         }
  756         $this->_code = '';
  757         $this->language = strtoupper(@$attribs['lang']);
  758         $this->_case = @$attribs['case'] == 'yes';
  759     }
  760 
  761     // }}}
  762 
  763     /**#@-*/
  764 
  765     // {{{ _error
  766 
  767     /**
  768     * Add an error message
  769     *
  770     * @param integer $code Error code
  771     * @param mixed   $message Error message or array with error message parameters
  772     * @param integer $lineNo Source code line number
  773     * @access private
  774     */
  775     function _error($code, $params = array(), $lineNo = 0)
  776     {
  777         if (!$lineNo && !empty($this->parser)) {
  778             $lineNo = xml_get_current_line_number($this->parser);
  779         }
  780         $this->_errors[] = $this->_formatError($code, $params, $this->_syntaxFile, $lineNo);
  781     }
  782 
  783     // }}}
  784     // {{{ _aliasAttributes
  785 
  786     /**
  787     * BC trick
  788     *
  789     * @param array $attrs attributes
  790     */
  791     function _aliasAttributes(&$attrs)
  792     {
  793         if (isset($attrs['innerClass']) && !isset($attrs['innerGroup'])) {
  794             $attrs['innerGroup'] = $attrs['innerClass'];
  795         }
  796         if (isset($attrs['delimClass']) && !isset($attrs['delimGroup'])) {
  797             $attrs['delimGroup'] = $attrs['delimClass'];
  798         }
  799         if (isset($attrs['partClass']) && !isset($attrs['partGroup'])) {
  800             $attrs['partGroup'] = $attrs['partClass'];
  801         }
  802     }
  803 
  804     // }}}
  805 
  806     /**#@+
  807     * @access private
  808     * @param resource $xp      XML parser resource
  809     * @param string   $elem    XML element name
  810     */
  811 
  812     // {{{ xmltag_Comment_
  813 
  814     /**
  815     * end handler for <comment> element
  816     */
  817     function xmltag_Comment_($xp, $elem)
  818     {
  819         $this->_inComment = false;
  820     }
  821 
  822     // }}}
  823     // {{{ xmltag_Region_
  824 
  825     /**
  826     * end handler for <region> element
  827     */
  828     function xmltag_Region_($xp, $elem)
  829     {
  830         $this->_element['type'] = 'region';
  831         $this->_element['order'] = $this->_blockOrder ++;
  832         $this->_regions[$this->_element['name']] = $this->_element;
  833     }
  834 
  835     // }}}
  836     // {{{ xmltag_Keywords_
  837 
  838     /**
  839     * end handler for <keywords> element
  840     */
  841     function xmltag_Keywords_($xp, $elem)
  842     {
  843         $this->_keywords[$this->_element['name']] = $this->_element;
  844     }
  845 
  846     // }}}
  847     // {{{ xmltag_Block_
  848 
  849     /**
  850     * end handler for <block> element
  851     */
  852     function xmltag_Block_($xp, $elem)
  853     {
  854         $this->_element['type'] = 'block';
  855         $this->_element['order'] = $this->_blockOrder ++;
  856         $this->_blocks[$this->_element['name']] = $this->_element;
  857     }
  858 
  859     // }}}
  860     // {{{ xmltag_Highlight_
  861 
  862     /**
  863     * end handler for <highlight> element
  864     */
  865     function xmltag_Highlight_($xp, $elem)
  866     {
  867         $conditions = array();
  868         $toplevel = array();
  869         foreach ($this->_blocks as $i => $current) {
  870             if (!$current['contained'] && !isset($current['onlyin'])) {
  871                 $toplevel[] = $i;
  872             }
  873             foreach ((array)@$current['onlyin'] as $region => $lineNo) {
  874                 if (!isset($this->_regions[$region])) {
  875                     $this->_error(TEXT_HIGHLIGHTER_BLOCK_REGION,
  876                     array(
  877                     'block' => $current['name'],
  878                     'region' => $region
  879                     ));
  880                 }
  881             }
  882         }
  883         foreach ($this->_regions as $i=>$current) {
  884             if (!$current['contained'] && !isset($current['onlyin'])) {
  885                 $toplevel[] = $i;
  886             }
  887             foreach ((array)@$current['contains']['region'] as $region => $lineNo) {
  888                 if (!isset($this->_regions[$region])) {
  889                     $this->_error(TEXT_HIGHLIGHTER_REGION_REGION,
  890                     array(
  891                     'region1' => $current['name'],
  892                     'region2' => $region
  893                     ));
  894                 }
  895             }
  896             foreach ((array)@$current['contains']['block'] as $region => $lineNo) {
  897                 if (!isset($this->_blocks[$region])) {
  898                     $this->_error(TEXT_HIGHLIGHTER_REGION_BLOCK,
  899                     array(
  900                     'block' => $current['name'],
  901                     'region' => $region
  902                     ));
  903                 }
  904             }
  905             foreach ((array)@$current['onlyin'] as $region => $lineNo) {
  906                 if (!isset($this->_regions[$region])) {
  907                     $this->_error(TEXT_HIGHLIGHTER_REGION_REGION,
  908                     array(
  909                     'region1' => $current['name'],
  910                     'region2' => $region
  911                     ));
  912                 }
  913             }
  914             foreach ($this->_regions as $j => $region) {
  915                 if (isset($region['onlyin'])) {
  916                     $suits = isset($region['onlyin'][$current['name']]);
  917                 } elseif (isset($current['not-contains']['region'][$region['name']])) {
  918                     $suits = false;
  919                 } elseif (isset($current['contains']['region'][$region['name']])) {
  920                     $suits = true;
  921                 } else {
  922                     $suits = @$current['contains-all'] && @!$region['never-contained'];
  923                 }
  924                 if ($suits) {
  925                     $this->_regions[$i]['lookfor'][] = $j;
  926                 }
  927             }
  928             foreach ($this->_blocks as $j=>$region) {
  929                 if (isset($region['onlyin'])) {
  930                     $suits = isset($region['onlyin'][$current['name']]);
  931                 } elseif (isset($current['not-contains']['block'][$region['name']])) {
  932                     $suits = false;
  933                 } elseif (isset($current['contains']['block'][$region['name']])) {
  934                     $suits = true;
  935                 } else {
  936                     $suits = @$current['contains-all'] && @!$region['never-contained'];
  937                 }
  938                 if ($suits) {
  939                     $this->_regions[$i]['lookfor'][] = $j;
  940                 }
  941             }
  942         }
  943         foreach ($this->_blocks as $i=>$current) {
  944             unset ($this->_blocks[$i]['never-contained']);
  945             unset ($this->_blocks[$i]['contained']);
  946             unset ($this->_blocks[$i]['contains-all']);
  947             unset ($this->_blocks[$i]['contains']);
  948             unset ($this->_blocks[$i]['onlyin']);
  949             unset ($this->_blocks[$i]['line']);
  950         }
  951 
  952         foreach ($this->_regions as $i=>$current) {
  953             unset ($this->_regions[$i]['never-contained']);
  954             unset ($this->_regions[$i]['contained']);
  955             unset ($this->_regions[$i]['contains-all']);
  956             unset ($this->_regions[$i]['contains']);
  957             unset ($this->_regions[$i]['onlyin']);
  958             unset ($this->_regions[$i]['line']);
  959         }
  960 
  961         foreach ($this->_keywords as $name => $keyword) {
  962             if (isset($keyword['ifdef'])) {
  963                 $conditions[$keyword['ifdef']][] = array($name, true);
  964             }
  965             if (isset($keyword['ifndef'])) {
  966                 $conditions[$keyword['ifndef']][] = array($name, false);
  967             }
  968             unset($this->_keywords[$name]['line']);
  969             if (!isset($this->_blocks[$keyword['inherits']])) {
  970                 $this->_error(TEXT_HIGHLIGHTER_KEYWORD_INHERITS,
  971                 array(
  972                 'keyword' => $keyword['name'],
  973                 'block' => $keyword['inherits']
  974                 ));
  975             }
  976             if (isset($keyword['otherwise']) && !isset($this->_blocks[$keyword['otherwise']]) ) {
  977                 $this->_error(TEXT_HIGHLIGHTER_KEYWORD_BLOCK,
  978                 array(
  979                 'keyword' => $keyword['name'],
  980                 'block' => $keyword['inherits']
  981                 ));
  982             }
  983         }
  984 
  985         $syntax=array(
  986         'keywords'   => $this->_keywords,
  987         'blocks'     => array_merge($this->_blocks, $this->_regions),
  988         'toplevel'   => $toplevel,
  989         );
  990         uasort($syntax['blocks'], array(&$this, '_sortBlocks'));
  991         foreach ($syntax['blocks'] as $name => $block) {
  992             if ($block['type'] == 'block') {
  993                 continue;
  994             }
  995             if (is_array(@$syntax['blocks'][$name]['lookfor'])) {
  996                 usort($syntax['blocks'][$name]['lookfor'], array(&$this, '_sortLookFor'));
  997             }
  998         }
  999         usort($syntax['toplevel'], array(&$this, '_sortLookFor'));
 1000         $syntax['case'] = $this->_case;
 1001         $this->_code = <<<CODE
 1002 <?php
 1003 /**
 1004  * Auto-generated class. {$this->language} syntax highlighting
 1005 CODE;
 1006 
 1007         if ($this->_comment) {
 1008             $comment = preg_replace('~^~m',' * ',$this->_comment);
 1009             $this->_code .= "\n * \n" . $comment;
 1010         }
 1011 
 1012         $this->_code .= <<<CODE
 1013  
 1014  *
 1015  * PHP version 4 and 5
 1016  *
 1017  * LICENSE: This source file is subject to version 3.0 of the PHP license
 1018  * that is available through the world-wide-web at the following URI:
 1019  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 1020  * the PHP License and are unable to obtain it through the web, please
 1021  * send a note to license@php.net so we can mail you a copy immediately.
 1022  *
 1023  * @copyright  2004-2006 Andrey Demenev
 1024  * @license    http://www.php.net/license/3_0.txt  PHP License
 1025  * @link       http://pear.php.net/package/Text_Highlighter
 1026  * @category   Text
 1027  * @package    Text_Highlighter
 1028  * @version    generated from: $this->_syntaxFile
 1029 
 1030 CODE;
 1031 
 1032         foreach ($this->_authors as $author) {
 1033             $this->_code .= ' * @author ' . $author['name'];
 1034             if ($author['email']) {
 1035                 $this->_code .= ' <' . $author['email'] . '>';
 1036             }
 1037             $this->_code .= "\n";
 1038         }
 1039 
 1040         $this->_code .= <<<CODE
 1041  *
 1042  */
 1043 
 1044 /**
 1045  * Auto-generated class. {$this->language} syntax highlighting
 1046  *
 1047 
 1048 CODE;
 1049         foreach ($this->_authors as $author) {
 1050             $this->_code .= ' * @author ' . $author['name'];
 1051             if ($author['email']) {
 1052                 $this->_code .= ' <' . $author['email']. '>';
 1053             }
 1054             $this->_code .= "\n";
 1055         }
 1056 
 1057 
 1058         $this->_code .= <<<CODE
 1059  * @category   Text
 1060  * @package    Text_Highlighter
 1061  * @copyright  2004-2006 Andrey Demenev
 1062  * @license    http://www.php.net/license/3_0.txt  PHP License
 1063  * @version    Release: 0.7.1
 1064  * @link       http://pear.php.net/package/Text_Highlighter
 1065  */
 1066 class  Text_Highlighter_{$this->language} extends Text_Highlighter
 1067 {
 1068     
 1069 CODE;
 1070         $this->_code .= 'var $_language = \'' . strtolower($this->language) . "';\n\n";
 1071         $array = var_export($syntax, true);
 1072         $array = trim(preg_replace('~^(\s*)~m','        \1\1',$array));
 1073         //        \$this->_syntax = $array;
 1074         $this->_code .= <<<CODE
 1075 
 1076     /**
 1077      *  Constructor
 1078      *
 1079      * @param array  \$options
 1080      * @access public
 1081      */
 1082     function __construct(\$options=array())
 1083     {
 1084 
 1085 CODE;
 1086         $this->_code .= <<<CODE
 1087 
 1088         \$this->_options = \$options;
 1089 CODE;
 1090         $states = array();
 1091         $i = 0;
 1092         foreach ($syntax['blocks'] as $name => $block) {
 1093             if ($block['type'] == 'region') {
 1094                 $states[$name] = $i++;
 1095             }
 1096         }
 1097         $regs = array();
 1098         $counts = array();
 1099         $delim = array();
 1100         $inner = array();
 1101         $end = array();
 1102         $stat = array();
 1103         $keywords = array();
 1104         $parts = array();
 1105         $kwmap = array();
 1106         $subst = array();
 1107         $re = array();
 1108         $ce = array();
 1109         $rd = array();
 1110         $in = array();
 1111         $st = array();
 1112         $kw = array();
 1113         $sb = array();
 1114         foreach ($syntax['toplevel'] as $name) {
 1115             $block = $syntax['blocks'][$name];
 1116             if ($block['type'] == 'block') {
 1117                 $kwm = array();
 1118                 $re[] = '(' . $block['match'] . ')';
 1119                 $ce[] = $this->_countSubpatterns($block['match']);
 1120                 $rd[] = '';
 1121                 $sb[] = false;;
 1122                 $st[] = -1;
 1123                 foreach ($syntax['keywords'] as $kwname => $kwgroup) {
 1124                     if ($kwgroup['inherits'] != $name) {
 1125                         continue;
 1126                     }
 1127                     $gre = implode('|', array_keys($kwgroup['match']));
 1128                     if (!$kwgroup['case']) {
 1129                         $gre = '(?i)' . $gre;
 1130                     }
 1131                     $kwm[$kwname][] =  $gre;
 1132                     $kwmap[$kwname] = $kwgroup['innerGroup'];
 1133                 }
 1134                 foreach ($kwm as $g => $ma) {
 1135                     $kwm[$g] = '/^(' . implode(')|(', $ma) . ')$/';
 1136                 }
 1137                 $kw[] = $kwm;
 1138             } else {
 1139                 $kw[] = -1;
 1140                 $re[] = '(' . $block['start'] . ')';
 1141                 $ce[] = $this->_countSubpatterns($block['start']);
 1142                 $rd[] = $block['delimGroup'];
 1143                 $st[] = $states[$name];
 1144                 $sb[] = $block['remember'];
 1145             }
 1146             $in[] = $block['innerGroup'];
 1147         }
 1148         $re = implode('|', $re);
 1149         $regs[-1] = '/' . $re . '/';
 1150         $counts[-1] = $ce;
 1151         $delim[-1] = $rd;
 1152         $inner[-1] = $in;
 1153         $stat[-1] = $st;
 1154         $keywords[-1] = $kw;
 1155         $subst[-1] = $sb;
 1156 
 1157         foreach ($syntax['blocks'] as $ablock) {
 1158             if ($ablock['type'] != 'region') {
 1159                 continue;
 1160             }
 1161             $end[] = '/' . $ablock['end'] . '/';
 1162             $re = array();
 1163             $ce = array();
 1164             $rd = array();
 1165             $in = array();
 1166             $st = array();
 1167             $kw = array();
 1168             $pc = array();
 1169             $sb = array();
 1170             foreach ((array)@$ablock['lookfor'] as $name) {
 1171                 $block = $syntax['blocks'][$name];
 1172                 if (isset($block['partClass'])) {
 1173                     $pc[] = $block['partClass'];
 1174                 } else {
 1175                     $pc[] = null;
 1176                 }
 1177                 if ($block['type'] == 'block') {
 1178                     $kwm = array();;
 1179                     $re[] = '(' . $block['match'] . ')';
 1180                     $ce[] = $this->_countSubpatterns($block['match']);
 1181                     $rd[] = '';
 1182                     $sb[] = false;
 1183                     $st[] = -1;
 1184                     foreach ($syntax['keywords'] as $kwname => $kwgroup) {
 1185                         if ($kwgroup['inherits'] != $name) {
 1186                             continue;
 1187                         }
 1188                         $gre = implode('|', array_keys($kwgroup['match']));
 1189                         if (!$kwgroup['case']) {
 1190                             $gre = '(?i)' . $gre;
 1191                         }
 1192                         $kwm[$kwname][] =  $gre;
 1193                         $kwmap[$kwname] = $kwgroup['innerGroup'];
 1194                     }
 1195                     foreach ($kwm as $g => $ma) {
 1196                         $kwm[$g] = '/^(' . implode(')|(', $ma) . ')$/';
 1197                     }
 1198                     $kw[] = $kwm;
 1199                 } else {
 1200                     $sb[] = $block['remember'];
 1201                     $kw[] = -1;
 1202                     $re[] = '(' . $block['start'] . ')';
 1203                     $ce[] = $this->_countSubpatterns($block['start']);
 1204                     $rd[] = $block['delimGroup'];
 1205                     $st[] = $states[$name];
 1206                 }
 1207                 $in[] = $block['innerGroup'];
 1208             }
 1209             $re = implode('|', $re);
 1210             $regs[] = '/' . $re . '/';
 1211             $counts[] = $ce;
 1212             $delim[] = $rd;
 1213             $inner[] = $in;
 1214             $stat[] = $st;
 1215             $keywords[] = $kw;
 1216             $parts[] = $pc;
 1217             $subst[] = $sb;
 1218         }
 1219 
 1220 
 1221         $this->_code .= "\n        \$this->_regs = " . $this->_exportArray($regs);
 1222         $this->_code .= ";\n        \$this->_counts = " .$this->_exportArray($counts);
 1223         $this->_code .= ";\n        \$this->_delim = " .$this->_exportArray($delim);
 1224         $this->_code .= ";\n        \$this->_inner = " .$this->_exportArray($inner);
 1225         $this->_code .= ";\n        \$this->_end = " .$this->_exportArray($end);
 1226         $this->_code .= ";\n        \$this->_states = " .$this->_exportArray($stat);
 1227         $this->_code .= ";\n        \$this->_keywords = " .$this->_exportArray($keywords);
 1228         $this->_code .= ";\n        \$this->_parts = " .$this->_exportArray($parts);
 1229         $this->_code .= ";\n        \$this->_subst = " .$this->_exportArray($subst);
 1230         $this->_code .= ";\n        \$this->_conditions = " .$this->_exportArray($conditions);
 1231         $this->_code .= ";\n        \$this->_kwmap = " .$this->_exportArray($kwmap);
 1232         $this->_code .= ";\n        \$this->_defClass = '" .$this->_defClass . '\'';
 1233         $this->_code .= <<<CODE
 1234 ;
 1235         \$this->_checkDefines();
 1236     }
 1237     
 1238 }
 1239 CODE;
 1240 }
 1241 
 1242 // }}}
 1243 }
 1244 
 1245 
 1246 /*
 1247 * Local variables:
 1248 * tab-width: 4
 1249 * c-basic-offset: 4
 1250 * c-hanging-comment-ender-p: nil
 1251 * End:
 1252 */
 1253 
 1254 ?>