123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254 |
- <?php
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
- /**
- * Syntax highlighter class generator
- *
- * To simplify the process of creating new syntax highlighters
- * for different languages, {@link Text_Highlighter_Generator} class is
- * provided. It takes highlighting rules from XML file and generates
- * a code of a class inherited from {@link Text_Highlighter}.
- *
- * PHP versions 4 and 5
- *
- * LICENSE: This source file is subject to version 3.0 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_0.txt. If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @category Text
- * @package Text_Highlighter
- * @author Andrey Demenev <demenev@gmail.com>
- * @copyright 2004-2006 Andrey Demenev
- * @license http://www.php.net/license/3_0.txt PHP License
- * @version CVS: $Id: Generator.php,v 1.1 2007/06/03 02:36:35 ssttoo Exp $
- * @link http://pear.php.net/package/Text_Highlighter
- */
- // {{{ error codes
- define ('TEXT_HIGHLIGHTER_EMPTY_RE', 1);
- define ('TEXT_HIGHLIGHTER_INVALID_RE', 2);
- define ('TEXT_HIGHLIGHTER_EMPTY_OR_MISSING', 3);
- define ('TEXT_HIGHLIGHTER_EMPTY', 4);
- define ('TEXT_HIGHLIGHTER_REGION_REGION', 5);
- define ('TEXT_HIGHLIGHTER_REGION_BLOCK', 6);
- define ('TEXT_HIGHLIGHTER_BLOCK_REGION', 7);
- define ('TEXT_HIGHLIGHTER_KEYWORD_BLOCK', 8);
- define ('TEXT_HIGHLIGHTER_KEYWORD_INHERITS', 9);
- define ('TEXT_HIGHLIGHTER_PARSE', 10);
- define ('TEXT_HIGHLIGHTER_FILE_WRITE', 11);
- define ('TEXT_HIGHLIGHTER_FILE_READ', 12);
- // }}}
- /**
- * Syntax highliter class generator class
- *
- * This class is used to generate PHP classes
- * from XML files with highlighting rules
- *
- * Usage example
- * <code>
- *require_once 'Text/Highlighter/Generator.php';
- *$generator =& new Text_Highlighter_Generator('php.xml');
- *$generator->generate();
- *$generator->saveCode('PHP.php');
- * </code>
- *
- * A command line script <b>generate</b> is provided for
- * class generation (installs in scripts/Text/Highlighter).
- *
- * @author Andrey Demenev <demenev@gmail.com>
- * @copyright 2004-2006 Andrey Demenev
- * @license http://www.php.net/license/3_0.txt PHP License
- * @version Release: 0.7.1
- * @link http://pear.php.net/package/Text_Highlighter
- */
- class Text_Highlighter_Generator extends XML_Parser
- {
- // {{{ properties
- /**
- * Whether to do case folding.
- * We have to declare it here, because XML_Parser
- * sets case folding in constructor
- *
- * @var boolean
- */
- var $folding = false;
- /**
- * Holds name of file with highlighting rules
- *
- * @var string
- * @access private
- */
- var $_syntaxFile;
- /**
- * Current element being processed
- *
- * @var array
- * @access private
- */
- var $_element;
- /**
- * List of regions
- *
- * @var array
- * @access private
- */
- var $_regions = array();
- /**
- * List of blocks
- *
- * @var array
- * @access private
- */
- var $_blocks = array();
- /**
- * List of keyword groups
- *
- * @var array
- * @access private
- */
- var $_keywords = array();
- /**
- * List of authors
- *
- * @var array
- * @access private
- */
- var $_authors = array();
- /**
- * Name of language
- *
- * @var string
- * @access public
- */
- var $language = '';
- /**
- * Generated code
- *
- * @var string
- * @access private
- */
- var $_code = '';
- /**
- * Default class
- *
- * @var string
- * @access private
- */
- var $_defClass = 'default';
- /**
- * Comment
- *
- * @var string
- * @access private
- */
- var $_comment = '';
- /**
- * Flag for comment processing
- *
- * @var boolean
- * @access private
- */
- var $_inComment = false;
- /**
- * Sorting order of current block/region
- *
- * @var integer
- * @access private
- */
- var $_blockOrder = 0;
- /**
- * Generation errors
- *
- * @var array
- * @access private
- */
- var $_errors;
- // }}}
- // {{{ constructor
- /**
- * Constructor
- *
- * @param string $syntaxFile Name of XML file
- * with syntax highlighting rules
- *
- * @access public
- */
- function __construct($syntaxFile = '')
- {
- XML_Parser::XML_Parser(null, 'func');
- $this->_errors = array();
- $this->_declareErrorMessages();
- if ($syntaxFile) {
- $this->setInputFile($syntaxFile);
- }
- }
- // }}}
- // {{{ _formatError
- /**
- * Format error message
- *
- * @param integer $code error code
- * @param string $params parameters
- * @param string $fileName file name
- * @param integer $lineNo line number
- * @return array
- * @access public
- */
- function _formatError($code, $params, $fileName, $lineNo)
- {
- $template = $this->_templates[$code];
- $ret = call_user_func_array('sprintf', array_merge(array($template), $params));
- if ($fileName) {
- $ret = '[' . $fileName . '] ' . $ret;
- }
- if ($lineNo) {
- $ret .= ' (line ' . $lineNo . ')';
- }
- return $ret;
- }
- // }}}
- // {{{ declareErrorMessages
- /**
- * Set up error message templates
- *
- * @access private
- */
- function _declareErrorMessages()
- {
- $this->_templates = array (
- TEXT_HIGHLIGHTER_EMPTY_RE => 'Empty regular expression',
- TEXT_HIGHLIGHTER_INVALID_RE => 'Invalid regular expression : %s',
- TEXT_HIGHLIGHTER_EMPTY_OR_MISSING => 'Empty or missing %s',
- TEXT_HIGHLIGHTER_EMPTY => 'Empty %s',
- TEXT_HIGHLIGHTER_REGION_REGION => 'Region %s refers undefined region %s',
- TEXT_HIGHLIGHTER_REGION_BLOCK => 'Region %s refers undefined block %s',
- TEXT_HIGHLIGHTER_BLOCK_REGION => 'Block %s refers undefined region %s',
- TEXT_HIGHLIGHTER_KEYWORD_BLOCK => 'Keyword group %s refers undefined block %s',
- TEXT_HIGHLIGHTER_KEYWORD_INHERITS => 'Keyword group %s inherits undefined block %s',
- TEXT_HIGHLIGHTER_PARSE => '%s',
- TEXT_HIGHLIGHTER_FILE_WRITE => 'Error writing file %s',
- TEXT_HIGHLIGHTER_FILE_READ => '%s'
- );
- }
- // }}}
- // {{{ setInputFile
- /**
- * Sets the input xml file to be parsed
- *
- * @param string Filename (full path)
- * @return boolean
- * @access public
- */
- function setInputFile($file)
- {
- $this->_syntaxFile = $file;
- $ret = parent::setInputFile($file);
- if (PEAR::isError($ret)) {
- $this->_error(TEXT_HIGHLIGHTER_FILE_READ, $ret->message);
- return false;
- }
- return true;
- }
- // }}}
- // {{{ generate
- /**
- * Generates class code
- *
- * @access public
- */
- function generate()
- {
- $this->_regions = array();
- $this->_blocks = array();
- $this->_keywords = array();
- $this->language = '';
- $this->_code = '';
- $this->_defClass = 'default';
- $this->_comment = '';
- $this->_inComment = false;
- $this->_authors = array();
- $this->_blockOrder = 0;
- $this->_errors = array();
- $ret = $this->parse();
- if (PEAR::isError($ret)) {
- $this->_error(TEXT_HIGHLIGHTER_PARSE, $ret->message);
- return false;
- }
- return true;
- }
- // }}}
- // {{{ getCode
- /**
- * Returns generated code as a string.
- *
- * @return string Generated code
- * @access public
- */
- function getCode()
- {
- return $this->_code;
- }
- // }}}
- // {{{ saveCode
- /**
- * Saves generated class to file. Note that {@link Text_Highlighter::factory()}
- * assumes that filename is uppercase (SQL.php, DTD.php, etc), and file
- * is located in Text/Highlighter
- *
- * @param string $filename Name of file to write the code to
- * @return boolean true on success, false on failure
- * @access public
- */
- function saveCode($filename)
- {
- $f = @fopen($filename, 'wb');
- if (!$f) {
- $this->_error(TEXT_HIGHLIGHTER_FILE_WRITE, array('outfile'=>$filename));
- return false;
- }
- fwrite ($f, $this->_code);
- fclose($f);
- return true;
- }
- // }}}
- // {{{ hasErrors
- /**
- * Reports if there were errors
- *
- * @return boolean
- * @access public
- */
- function hasErrors()
- {
- return count($this->_errors) > 0;
- }
- // }}}
- // {{{ getErrors
- /**
- * Returns errors
- *
- * @return array
- * @access public
- */
- function getErrors()
- {
- return $this->_errors;
- }
- // }}}
- // {{{ _sortBlocks
- /**
- * Sorts blocks
- *
- * @access private
- */
- function _sortBlocks($b1, $b2) {
- return $b1['order'] - $b2['order'];
- }
- // }}}
- // {{{ _sortLookFor
- /**
- * Sort 'look for' list
- * @return int
- * @param string $b1
- * @param string $b2
- */
- function _sortLookFor($b1, $b2) {
- $o1 = isset($this->_blocks[$b1]) ? $this->_blocks[$b1]['order'] : $this->_regions[$b1]['order'];
- $o2 = isset($this->_blocks[$b2]) ? $this->_blocks[$b2]['order'] : $this->_regions[$b2]['order'];
- return $o1 - $o2;
- }
- // }}}
- // {{{ _makeRE
- /**
- * Adds delimiters and modifiers to regular expression if necessary
- *
- * @param string $text Original RE
- * @return string Final RE
- * @access private
- */
- function _makeRE($text, $case = false)
- {
- if (!strlen($text)) {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_RE);
- }
- if (!strlen($text) || $text{0} != '/') {
- $text = '/' . $text . '/';
- }
- if (!$case) {
- $text .= 'i';
- }
- $php_errormsg = '';
- @preg_match($text, '');
- if ($php_errormsg) {
- $this->_error(TEXT_HIGHLIGHTER_INVALID_RE, $php_errormsg);
- }
- preg_match ('#^/(.+)/(.*)$#', $text, $m);
- if (@$m[2]) {
- $text = '(?' . $m[2] . ')' . $m[1];
- } else {
- $text = $m[1];
- }
- return $text;
- }
- // }}}
- // {{{ _exportArray
- /**
- * Exports array as PHP code
- *
- * @param array $array
- * @return string Code
- * @access private
- */
- function _exportArray($array)
- {
- $array = var_export($array, true);
- return trim(preg_replace('~^(\s*)~m',' \1\1',$array));
- }
- // }}}
- // {{{ _countSubpatterns
- /**
- * Find number of capturing suppaterns in regular expression
- * @return int
- * @param string $re Regular expression (without delimiters)
- */
- function _countSubpatterns($re)
- {
- preg_match_all('/' . $re . '/', '', $m);
- return count($m)-1;
- }
- // }}}
- /**#@+
- * @access private
- * @param resource $xp XML parser resource
- * @param string $elem XML element name
- * @param array $attribs XML element attributes
- */
- // {{{ xmltag_Default
- /**
- * start handler for <default> element
- */
- function xmltag_Default($xp, $elem, $attribs)
- {
- $this->_aliasAttributes($attribs);
- if (!isset($attribs['innerGroup']) || $attribs['innerGroup'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'innerGroup');
- }
- $this->_defClass = @$attribs['innerGroup'];
- }
- // }}}
- // {{{ xmltag_Region
- /**
- * start handler for <region> element
- */
- function xmltag_Region($xp, $elem, $attribs)
- {
- $this->_aliasAttributes($attribs);
- if (!isset($attribs['name']) || $attribs['name'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'region name');
- }
- if (!isset($attribs['innerGroup']) || $attribs['innerGroup'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'innerGroup');
- }
- $this->_element = array('name' => $attribs['name']);
- $this->_element['line'] = xml_get_current_line_number($this->parser);
- if (isset($attribs['case'])) {
- $this->_element['case'] = $attribs['case'] == 'yes';
- } else {
- $this->_element['case'] = $this->_case;
- }
- $this->_element['innerGroup'] = $attribs['innerGroup'];
- $this->_element['delimGroup'] = isset($attribs['delimGroup']) ?
- $attribs['delimGroup'] :
- $attribs['innerGroup'];
- $this->_element['start'] = $this->_makeRE(@$attribs['start'], $this->_element['case']);
- $this->_element['end'] = $this->_makeRE(@$attribs['end'], $this->_element['case']);
- $this->_element['contained'] = @$attribs['contained'] == 'yes';
- $this->_element['never-contained'] = @$attribs['never-contained'] == 'yes';
- $this->_element['remember'] = @$attribs['remember'] == 'yes';
- if (isset($attribs['startBOL']) && $attribs['startBOL'] == 'yes') {
- $this->_element['startBOL'] = true;
- }
- if (isset($attribs['endBOL']) && $attribs['endBOL'] == 'yes') {
- $this->_element['endBOL'] = true;
- }
- if (isset($attribs['neverAfter'])) {
- $this->_element['neverafter'] = $this->_makeRE($attribs['neverAfter']);
- }
- }
- // }}}
- // {{{ xmltag_Block
- /**
- * start handler for <block> element
- */
- function xmltag_Block($xp, $elem, $attribs)
- {
- $this->_aliasAttributes($attribs);
- if (!isset($attribs['name']) || $attribs['name'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'block name');
- }
- if (isset($attribs['innerGroup']) && $attribs['innerGroup'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY, 'innerGroup');
- }
- $this->_element = array('name' => $attribs['name']);
- $this->_element['line'] = xml_get_current_line_number($this->parser);
- if (isset($attribs['case'])) {
- $this->_element['case'] = $attribs['case'] == 'yes';
- } else {
- $this->_element['case'] = $this->_case;
- }
- if (isset($attribs['innerGroup'])) {
- $this->_element['innerGroup'] = @$attribs['innerGroup'];
- }
- $this->_element['match'] = $this->_makeRE($attribs['match'], $this->_element['case']);
- $this->_element['contained'] = @$attribs['contained'] == 'yes';
- $this->_element['multiline'] = @$attribs['multiline'] == 'yes';
- if (isset($attribs['BOL']) && $attribs['BOL'] == 'yes') {
- $this->_element['BOL'] = true;
- }
- if (isset($attribs['neverAfter'])) {
- $this->_element['neverafter'] = $this->_makeRE($attribs['neverAfter']);
- }
- }
- // }}}
- // {{{ cdataHandler
- /**
- * Character data handler. Used for comment
- */
- function cdataHandler($xp, $cdata)
- {
- if ($this->_inComment) {
- $this->_comment .= $cdata;
- }
- }
- // }}}
- // {{{ xmltag_Comment
- /**
- * start handler for <comment> element
- */
- function xmltag_Comment($xp, $elem, $attribs)
- {
- $this->_comment = '';
- $this->_inComment = true;
- }
- // }}}
- // {{{ xmltag_PartGroup
- /**
- * start handler for <partgroup> element
- */
- function xmltag_PartGroup($xp, $elem, $attribs)
- {
- $this->_aliasAttributes($attribs);
- if (!isset($attribs['innerGroup']) || $attribs['innerGroup'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'innerGroup');
- }
- $this->_element['partClass'][$attribs['index']] = @$attribs['innerGroup'];
- }
- // }}}
- // {{{ xmltag_PartClass
- /**
- * start handler for <partclass> element
- */
- function xmltag_PartClass($xp, $elem, $attribs)
- {
- $this->xmltag_PartGroup($xp, $elem, $attribs);
- }
- // }}}
- // {{{ xmltag_Keywords
- /**
- * start handler for <keywords> element
- */
- function xmltag_Keywords($xp, $elem, $attribs)
- {
- $this->_aliasAttributes($attribs);
- if (!isset($attribs['name']) || $attribs['name'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'keyword group name');
- }
- if (!isset($attribs['innerGroup']) || $attribs['innerGroup'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'innerGroup');
- }
- if (!isset($attribs['inherits']) || $attribs['inherits'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'inherits');
- }
- $this->_element = array('name'=>@$attribs['name']);
- $this->_element['line'] = xml_get_current_line_number($this->parser);
- $this->_element['innerGroup'] = @$attribs['innerGroup'];
- if (isset($attribs['case'])) {
- $this->_element['case'] = $attribs['case'] == 'yes';
- } else {
- $this->_element['case'] = $this->_case;
- }
- $this->_element['inherits'] = @$attribs['inherits'];
- if (isset($attribs['otherwise'])) {
- $this->_element['otherwise'] = $attribs['otherwise'];
- }
- if (isset($attribs['ifdef'])) {
- $this->_element['ifdef'] = $attribs['ifdef'];
- }
- if (isset($attribs['ifndef'])) {
- $this->_element['ifndef'] = $attribs['ifndef'];
- }
- }
- // }}}
- // {{{ xmltag_Keyword
- /**
- * start handler for <keyword> element
- */
- function xmltag_Keyword($xp, $elem, $attribs)
- {
- if (!isset($attribs['match']) || $attribs['match'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'match');
- }
- $keyword = @$attribs['match'];
- if (!$this->_element['case']) {
- $keyword = strtolower($keyword);
- }
- $this->_element['match'][$keyword] = true;
- }
- // }}}
- // {{{ xmltag_Contains
- /**
- * start handler for <contains> element
- */
- function xmltag_Contains($xp, $elem, $attribs)
- {
- $this->_element['contains-all'] = @$attribs['all'] == 'yes';
- if (isset($attribs['region'])) {
- $this->_element['contains']['region'][$attribs['region']] =
- xml_get_current_line_number($this->parser);
- }
- if (isset($attribs['block'])) {
- $this->_element['contains']['block'][$attribs['block']] =
- xml_get_current_line_number($this->parser);
- }
- }
- // }}}
- // {{{ xmltag_But
- /**
- * start handler for <but> element
- */
- function xmltag_But($xp, $elem, $attribs)
- {
- if (isset($attribs['region'])) {
- $this->_element['not-contains']['region'][$attribs['region']] = true;
- }
- if (isset($attribs['block'])) {
- $this->_element['not-contains']['block'][$attribs['block']] = true;
- }
- }
- // }}}
- // {{{ xmltag_Onlyin
- /**
- * start handler for <onlyin> element
- */
- function xmltag_Onlyin($xp, $elem, $attribs)
- {
- if (!isset($attribs['region']) || $attribs['region'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'region');
- }
- $this->_element['onlyin'][$attribs['region']] = xml_get_current_line_number($this->parser);
- }
- // }}}
- // {{{ xmltag_Author
- /**
- * start handler for <author> element
- */
- function xmltag_Author($xp, $elem, $attribs)
- {
- if (!isset($attribs['name']) || $attribs['name'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'author name');
- }
- $this->_authors[] = array(
- 'name' => @$attribs['name'],
- 'email' => (string)@$attribs['email']
- );
- }
- // }}}
- // {{{ xmltag_Highlight
- /**
- * start handler for <highlight> element
- */
- function xmltag_Highlight($xp, $elem, $attribs)
- {
- if (!isset($attribs['lang']) || $attribs['lang'] === '') {
- $this->_error(TEXT_HIGHLIGHTER_EMPTY_OR_MISSING, 'language name');
- }
- $this->_code = '';
- $this->language = strtoupper(@$attribs['lang']);
- $this->_case = @$attribs['case'] == 'yes';
- }
- // }}}
- /**#@-*/
- // {{{ _error
- /**
- * Add an error message
- *
- * @param integer $code Error code
- * @param mixed $message Error message or array with error message parameters
- * @param integer $lineNo Source code line number
- * @access private
- */
- function _error($code, $params = array(), $lineNo = 0)
- {
- if (!$lineNo && !empty($this->parser)) {
- $lineNo = xml_get_current_line_number($this->parser);
- }
- $this->_errors[] = $this->_formatError($code, $params, $this->_syntaxFile, $lineNo);
- }
- // }}}
- // {{{ _aliasAttributes
- /**
- * BC trick
- *
- * @param array $attrs attributes
- */
- function _aliasAttributes(&$attrs)
- {
- if (isset($attrs['innerClass']) && !isset($attrs['innerGroup'])) {
- $attrs['innerGroup'] = $attrs['innerClass'];
- }
- if (isset($attrs['delimClass']) && !isset($attrs['delimGroup'])) {
- $attrs['delimGroup'] = $attrs['delimClass'];
- }
- if (isset($attrs['partClass']) && !isset($attrs['partGroup'])) {
- $attrs['partGroup'] = $attrs['partClass'];
- }
- }
- // }}}
- /**#@+
- * @access private
- * @param resource $xp XML parser resource
- * @param string $elem XML element name
- */
- // {{{ xmltag_Comment_
- /**
- * end handler for <comment> element
- */
- function xmltag_Comment_($xp, $elem)
- {
- $this->_inComment = false;
- }
- // }}}
- // {{{ xmltag_Region_
- /**
- * end handler for <region> element
- */
- function xmltag_Region_($xp, $elem)
- {
- $this->_element['type'] = 'region';
- $this->_element['order'] = $this->_blockOrder ++;
- $this->_regions[$this->_element['name']] = $this->_element;
- }
- // }}}
- // {{{ xmltag_Keywords_
- /**
- * end handler for <keywords> element
- */
- function xmltag_Keywords_($xp, $elem)
- {
- $this->_keywords[$this->_element['name']] = $this->_element;
- }
- // }}}
- // {{{ xmltag_Block_
- /**
- * end handler for <block> element
- */
- function xmltag_Block_($xp, $elem)
- {
- $this->_element['type'] = 'block';
- $this->_element['order'] = $this->_blockOrder ++;
- $this->_blocks[$this->_element['name']] = $this->_element;
- }
- // }}}
- // {{{ xmltag_Highlight_
- /**
- * end handler for <highlight> element
- */
- function xmltag_Highlight_($xp, $elem)
- {
- $conditions = array();
- $toplevel = array();
- foreach ($this->_blocks as $i => $current) {
- if (!$current['contained'] && !isset($current['onlyin'])) {
- $toplevel[] = $i;
- }
- foreach ((array)@$current['onlyin'] as $region => $lineNo) {
- if (!isset($this->_regions[$region])) {
- $this->_error(TEXT_HIGHLIGHTER_BLOCK_REGION,
- array(
- 'block' => $current['name'],
- 'region' => $region
- ));
- }
- }
- }
- foreach ($this->_regions as $i=>$current) {
- if (!$current['contained'] && !isset($current['onlyin'])) {
- $toplevel[] = $i;
- }
- foreach ((array)@$current['contains']['region'] as $region => $lineNo) {
- if (!isset($this->_regions[$region])) {
- $this->_error(TEXT_HIGHLIGHTER_REGION_REGION,
- array(
- 'region1' => $current['name'],
- 'region2' => $region
- ));
- }
- }
- foreach ((array)@$current['contains']['block'] as $region => $lineNo) {
- if (!isset($this->_blocks[$region])) {
- $this->_error(TEXT_HIGHLIGHTER_REGION_BLOCK,
- array(
- 'block' => $current['name'],
- 'region' => $region
- ));
- }
- }
- foreach ((array)@$current['onlyin'] as $region => $lineNo) {
- if (!isset($this->_regions[$region])) {
- $this->_error(TEXT_HIGHLIGHTER_REGION_REGION,
- array(
- 'region1' => $current['name'],
- 'region2' => $region
- ));
- }
- }
- foreach ($this->_regions as $j => $region) {
- if (isset($region['onlyin'])) {
- $suits = isset($region['onlyin'][$current['name']]);
- } elseif (isset($current['not-contains']['region'][$region['name']])) {
- $suits = false;
- } elseif (isset($current['contains']['region'][$region['name']])) {
- $suits = true;
- } else {
- $suits = @$current['contains-all'] && @!$region['never-contained'];
- }
- if ($suits) {
- $this->_regions[$i]['lookfor'][] = $j;
- }
- }
- foreach ($this->_blocks as $j=>$region) {
- if (isset($region['onlyin'])) {
- $suits = isset($region['onlyin'][$current['name']]);
- } elseif (isset($current['not-contains']['block'][$region['name']])) {
- $suits = false;
- } elseif (isset($current['contains']['block'][$region['name']])) {
- $suits = true;
- } else {
- $suits = @$current['contains-all'] && @!$region['never-contained'];
- }
- if ($suits) {
- $this->_regions[$i]['lookfor'][] = $j;
- }
- }
- }
- foreach ($this->_blocks as $i=>$current) {
- unset ($this->_blocks[$i]['never-contained']);
- unset ($this->_blocks[$i]['contained']);
- unset ($this->_blocks[$i]['contains-all']);
- unset ($this->_blocks[$i]['contains']);
- unset ($this->_blocks[$i]['onlyin']);
- unset ($this->_blocks[$i]['line']);
- }
- foreach ($this->_regions as $i=>$current) {
- unset ($this->_regions[$i]['never-contained']);
- unset ($this->_regions[$i]['contained']);
- unset ($this->_regions[$i]['contains-all']);
- unset ($this->_regions[$i]['contains']);
- unset ($this->_regions[$i]['onlyin']);
- unset ($this->_regions[$i]['line']);
- }
- foreach ($this->_keywords as $name => $keyword) {
- if (isset($keyword['ifdef'])) {
- $conditions[$keyword['ifdef']][] = array($name, true);
- }
- if (isset($keyword['ifndef'])) {
- $conditions[$keyword['ifndef']][] = array($name, false);
- }
- unset($this->_keywords[$name]['line']);
- if (!isset($this->_blocks[$keyword['inherits']])) {
- $this->_error(TEXT_HIGHLIGHTER_KEYWORD_INHERITS,
- array(
- 'keyword' => $keyword['name'],
- 'block' => $keyword['inherits']
- ));
- }
- if (isset($keyword['otherwise']) && !isset($this->_blocks[$keyword['otherwise']]) ) {
- $this->_error(TEXT_HIGHLIGHTER_KEYWORD_BLOCK,
- array(
- 'keyword' => $keyword['name'],
- 'block' => $keyword['inherits']
- ));
- }
- }
- $syntax=array(
- 'keywords' => $this->_keywords,
- 'blocks' => array_merge($this->_blocks, $this->_regions),
- 'toplevel' => $toplevel,
- );
- uasort($syntax['blocks'], array(&$this, '_sortBlocks'));
- foreach ($syntax['blocks'] as $name => $block) {
- if ($block['type'] == 'block') {
- continue;
- }
- if (is_array(@$syntax['blocks'][$name]['lookfor'])) {
- usort($syntax['blocks'][$name]['lookfor'], array(&$this, '_sortLookFor'));
- }
- }
- usort($syntax['toplevel'], array(&$this, '_sortLookFor'));
- $syntax['case'] = $this->_case;
- $this->_code = <<<CODE
- <?php
- /**
- * Auto-generated class. {$this->language} syntax highlighting
- CODE;
- if ($this->_comment) {
- $comment = preg_replace('~^~m',' * ',$this->_comment);
- $this->_code .= "\n * \n" . $comment;
- }
- $this->_code .= <<<CODE
-
- *
- * PHP version 4 and 5
- *
- * LICENSE: This source file is subject to version 3.0 of the PHP license
- * that is available through the world-wide-web at the following URI:
- * http://www.php.net/license/3_0.txt. If you did not receive a copy of
- * the PHP License and are unable to obtain it through the web, please
- * send a note to license@php.net so we can mail you a copy immediately.
- *
- * @copyright 2004-2006 Andrey Demenev
- * @license http://www.php.net/license/3_0.txt PHP License
- * @link http://pear.php.net/package/Text_Highlighter
- * @category Text
- * @package Text_Highlighter
- * @version generated from: $this->_syntaxFile
- CODE;
- foreach ($this->_authors as $author) {
- $this->_code .= ' * @author ' . $author['name'];
- if ($author['email']) {
- $this->_code .= ' <' . $author['email'] . '>';
- }
- $this->_code .= "\n";
- }
- $this->_code .= <<<CODE
- *
- */
- /**
- * Auto-generated class. {$this->language} syntax highlighting
- *
- CODE;
- foreach ($this->_authors as $author) {
- $this->_code .= ' * @author ' . $author['name'];
- if ($author['email']) {
- $this->_code .= ' <' . $author['email']. '>';
- }
- $this->_code .= "\n";
- }
- $this->_code .= <<<CODE
- * @category Text
- * @package Text_Highlighter
- * @copyright 2004-2006 Andrey Demenev
- * @license http://www.php.net/license/3_0.txt PHP License
- * @version Release: 0.7.1
- * @link http://pear.php.net/package/Text_Highlighter
- */
- class Text_Highlighter_{$this->language} extends Text_Highlighter
- {
-
- CODE;
- $this->_code .= 'var $_language = \'' . strtolower($this->language) . "';\n\n";
- $array = var_export($syntax, true);
- $array = trim(preg_replace('~^(\s*)~m',' \1\1',$array));
- // \$this->_syntax = $array;
- $this->_code .= <<<CODE
- /**
- * Constructor
- *
- * @param array \$options
- * @access public
- */
- function __construct(\$options=array())
- {
- CODE;
- $this->_code .= <<<CODE
- \$this->_options = \$options;
- CODE;
- $states = array();
- $i = 0;
- foreach ($syntax['blocks'] as $name => $block) {
- if ($block['type'] == 'region') {
- $states[$name] = $i++;
- }
- }
- $regs = array();
- $counts = array();
- $delim = array();
- $inner = array();
- $end = array();
- $stat = array();
- $keywords = array();
- $parts = array();
- $kwmap = array();
- $subst = array();
- $re = array();
- $ce = array();
- $rd = array();
- $in = array();
- $st = array();
- $kw = array();
- $sb = array();
- foreach ($syntax['toplevel'] as $name) {
- $block = $syntax['blocks'][$name];
- if ($block['type'] == 'block') {
- $kwm = array();
- $re[] = '(' . $block['match'] . ')';
- $ce[] = $this->_countSubpatterns($block['match']);
- $rd[] = '';
- $sb[] = false;;
- $st[] = -1;
- foreach ($syntax['keywords'] as $kwname => $kwgroup) {
- if ($kwgroup['inherits'] != $name) {
- continue;
- }
- $gre = implode('|', array_keys($kwgroup['match']));
- if (!$kwgroup['case']) {
- $gre = '(?i)' . $gre;
- }
- $kwm[$kwname][] = $gre;
- $kwmap[$kwname] = $kwgroup['innerGroup'];
- }
- foreach ($kwm as $g => $ma) {
- $kwm[$g] = '/^(' . implode(')|(', $ma) . ')$/';
- }
- $kw[] = $kwm;
- } else {
- $kw[] = -1;
- $re[] = '(' . $block['start'] . ')';
- $ce[] = $this->_countSubpatterns($block['start']);
- $rd[] = $block['delimGroup'];
- $st[] = $states[$name];
- $sb[] = $block['remember'];
- }
- $in[] = $block['innerGroup'];
- }
- $re = implode('|', $re);
- $regs[-1] = '/' . $re . '/';
- $counts[-1] = $ce;
- $delim[-1] = $rd;
- $inner[-1] = $in;
- $stat[-1] = $st;
- $keywords[-1] = $kw;
- $subst[-1] = $sb;
- foreach ($syntax['blocks'] as $ablock) {
- if ($ablock['type'] != 'region') {
- continue;
- }
- $end[] = '/' . $ablock['end'] . '/';
- $re = array();
- $ce = array();
- $rd = array();
- $in = array();
- $st = array();
- $kw = array();
- $pc = array();
- $sb = array();
- foreach ((array)@$ablock['lookfor'] as $name) {
- $block = $syntax['blocks'][$name];
- if (isset($block['partClass'])) {
- $pc[] = $block['partClass'];
- } else {
- $pc[] = null;
- }
- if ($block['type'] == 'block') {
- $kwm = array();;
- $re[] = '(' . $block['match'] . ')';
- $ce[] = $this->_countSubpatterns($block['match']);
- $rd[] = '';
- $sb[] = false;
- $st[] = -1;
- foreach ($syntax['keywords'] as $kwname => $kwgroup) {
- if ($kwgroup['inherits'] != $name) {
- continue;
- }
- $gre = implode('|', array_keys($kwgroup['match']));
- if (!$kwgroup['case']) {
- $gre = '(?i)' . $gre;
- }
- $kwm[$kwname][] = $gre;
- $kwmap[$kwname] = $kwgroup['innerGroup'];
- }
- foreach ($kwm as $g => $ma) {
- $kwm[$g] = '/^(' . implode(')|(', $ma) . ')$/';
- }
- $kw[] = $kwm;
- } else {
- $sb[] = $block['remember'];
- $kw[] = -1;
- $re[] = '(' . $block['start'] . ')';
- $ce[] = $this->_countSubpatterns($block['start']);
- $rd[] = $block['delimGroup'];
- $st[] = $states[$name];
- }
- $in[] = $block['innerGroup'];
- }
- $re = implode('|', $re);
- $regs[] = '/' . $re . '/';
- $counts[] = $ce;
- $delim[] = $rd;
- $inner[] = $in;
- $stat[] = $st;
- $keywords[] = $kw;
- $parts[] = $pc;
- $subst[] = $sb;
- }
- $this->_code .= "\n \$this->_regs = " . $this->_exportArray($regs);
- $this->_code .= ";\n \$this->_counts = " .$this->_exportArray($counts);
- $this->_code .= ";\n \$this->_delim = " .$this->_exportArray($delim);
- $this->_code .= ";\n \$this->_inner = " .$this->_exportArray($inner);
- $this->_code .= ";\n \$this->_end = " .$this->_exportArray($end);
- $this->_code .= ";\n \$this->_states = " .$this->_exportArray($stat);
- $this->_code .= ";\n \$this->_keywords = " .$this->_exportArray($keywords);
- $this->_code .= ";\n \$this->_parts = " .$this->_exportArray($parts);
- $this->_code .= ";\n \$this->_subst = " .$this->_exportArray($subst);
- $this->_code .= ";\n \$this->_conditions = " .$this->_exportArray($conditions);
- $this->_code .= ";\n \$this->_kwmap = " .$this->_exportArray($kwmap);
- $this->_code .= ";\n \$this->_defClass = '" .$this->_defClass . '\'';
- $this->_code .= <<<CODE
- ;
- \$this->_checkDefines();
- }
-
- }
- CODE;
- }
- // }}}
- }
- /*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * c-hanging-comment-ender-p: nil
- * End:
- */
- ?>
|