diff options
author | ahriman <ahriman@falte.red> | 2019-01-02 04:57:35 +0000 |
---|---|---|
committer | ahriman <ahriman@falte.red> | 2019-01-02 04:57:35 +0000 |
commit | 2bd7f83a6495011ada78ca8a9f2af417caf01760 (patch) | |
tree | f9acdb7f09e011c65330ab993d4db3620787dbfb /wiki/inc/parser/lexer.php | |
parent | bcb215c3a7e914d05f166846a33860e48bba64fb (diff) | |
download | site-2bd7f83a6495011ada78ca8a9f2af417caf01760.tar.gz |
removed dokuwiki
Diffstat (limited to 'wiki/inc/parser/lexer.php')
-rw-r--r-- | wiki/inc/parser/lexer.php | 614 |
1 files changed, 0 insertions, 614 deletions
diff --git a/wiki/inc/parser/lexer.php b/wiki/inc/parser/lexer.php deleted file mode 100644 index ba6a653..0000000 --- a/wiki/inc/parser/lexer.php +++ /dev/null @@ -1,614 +0,0 @@ -<?php -/** - * Author Markus Baker: http://www.lastcraft.com - * Version adapted from Simple Test: http://sourceforge.net/projects/simpletest/ - * For an intro to the Lexer see: - * https://web.archive.org/web/20120125041816/http://www.phppatterns.com/docs/develop/simple_test_lexer_notes - * @author Marcus Baker - * @package Doku - * @subpackage Lexer - * @version $Id: lexer.php,v 1.1 2005/03/23 23:14:09 harryf Exp $ - */ - -/** - * Init path constant - */ -if(!defined('DOKU_INC')) die('meh.'); - -/**#@+ - * lexer mode constant - */ -define("DOKU_LEXER_ENTER", 1); -define("DOKU_LEXER_MATCHED", 2); -define("DOKU_LEXER_UNMATCHED", 3); -define("DOKU_LEXER_EXIT", 4); -define("DOKU_LEXER_SPECIAL", 5); -/**#@-*/ - -/** - * Compounded regular expression. Any of - * the contained patterns could match and - * when one does it's label is returned. - * - * @package Doku - * @subpackage Lexer - */ -class Doku_LexerParallelRegex { - var $_patterns; - var $_labels; - var $_regex; - var $_case; - - /** - * Constructor. Starts with no patterns. - * - * @param boolean $case True for case sensitive, false - * for insensitive. - * @access public - */ - function __construct($case) { - $this->_case = $case; - $this->_patterns = array(); - $this->_labels = array(); - $this->_regex = null; - } - - /** - * Adds a pattern with an optional label. - * - * @param mixed $pattern Perl style regex. Must be UTF-8 - * encoded. If its a string, the (, ) - * lose their meaning unless they - * form part of a lookahead or - * lookbehind assertation. - * @param bool|string $label Label of regex to be returned - * on a match. Label must be ASCII - * @access public - */ - function addPattern($pattern, $label = true) { - $count = count($this->_patterns); - $this->_patterns[$count] = $pattern; - $this->_labels[$count] = $label; - $this->_regex = null; - } - - /** - * Attempts to match all patterns at once against a string. - * - * @param string $subject String to match against. - * @param string $match First matched portion of - * subject. - * @return boolean True on success. - * @access public - */ - function match($subject, &$match) { - if (count($this->_patterns) == 0) { - return false; - } - if (! preg_match($this->_getCompoundedRegex(), $subject, $matches)) { - $match = ""; - return false; - } - - $match = $matches[0]; - $size = count($matches); - for ($i = 1; $i < $size; $i++) { - if ($matches[$i] && isset($this->_labels[$i - 1])) { - return $this->_labels[$i - 1]; - } - } - return true; - } - - /** - * Attempts to split the string against all patterns at once - * - * @param string $subject String to match against. - * @param array $split The split result: array containing, pre-match, match & post-match strings - * @return boolean True on success. - * @access public - * - * @author Christopher Smith <chris@jalakai.co.uk> - */ - function split($subject, &$split) { - if (count($this->_patterns) == 0) { - return false; - } - - if (! preg_match($this->_getCompoundedRegex(), $subject, $matches)) { - if(function_exists('preg_last_error')){ - $err = preg_last_error(); - switch($err){ - case PREG_BACKTRACK_LIMIT_ERROR: - msg('A PCRE backtrack error occured. Try to increase the pcre.backtrack_limit in php.ini',-1); - break; - case PREG_RECURSION_LIMIT_ERROR: - msg('A PCRE recursion error occured. Try to increase the pcre.recursion_limit in php.ini',-1); - break; - case PREG_BAD_UTF8_ERROR: - msg('A PCRE UTF-8 error occured. This might be caused by a faulty plugin',-1); - break; - case PREG_INTERNAL_ERROR: - msg('A PCRE internal error occured. This might be caused by a faulty plugin',-1); - break; - } - } - - $split = array($subject, "", ""); - return false; - } - - $idx = count($matches)-2; - list($pre, $post) = preg_split($this->_patterns[$idx].$this->_getPerlMatchingFlags(), $subject, 2); - $split = array($pre, $matches[0], $post); - - return isset($this->_labels[$idx]) ? $this->_labels[$idx] : true; - } - - /** - * Compounds the patterns into a single - * regular expression separated with the - * "or" operator. Caches the regex. - * Will automatically escape (, ) and / tokens. - * - * @internal array $_patterns List of patterns in order. - * @return null|string - * @access private - */ - function _getCompoundedRegex() { - if ($this->_regex == null) { - $cnt = count($this->_patterns); - for ($i = 0; $i < $cnt; $i++) { - - /* - * decompose the input pattern into "(", "(?", ")", - * "[...]", "[]..]", "[^]..]", "[...[:...:]..]", "\x"... - * elements. - */ - preg_match_all('/\\\\.|' . - '\(\?|' . - '[()]|' . - '\[\^?\]?(?:\\\\.|\[:[^]]*:\]|[^]\\\\])*\]|' . - '[^[()\\\\]+/', $this->_patterns[$i], $elts); - - $pattern = ""; - $level = 0; - - foreach ($elts[0] as $elt) { - /* - * for "(", ")" remember the nesting level, add "\" - * only to the non-"(?" ones. - */ - - switch($elt) { - case '(': - $pattern .= '\('; - break; - case ')': - if ($level > 0) - $level--; /* closing (? */ - else - $pattern .= '\\'; - $pattern .= ')'; - break; - case '(?': - $level++; - $pattern .= '(?'; - break; - default: - if (substr($elt, 0, 1) == '\\') - $pattern .= $elt; - else - $pattern .= str_replace('/', '\/', $elt); - } - } - $this->_patterns[$i] = "($pattern)"; - } - $this->_regex = "/" . implode("|", $this->_patterns) . "/" . $this->_getPerlMatchingFlags(); - } - return $this->_regex; - } - - /** - * Accessor for perl regex mode flags to use. - * @return string Perl regex flags. - * @access private - */ - function _getPerlMatchingFlags() { - return ($this->_case ? "msS" : "msSi"); - } -} - -/** - * States for a stack machine. - * @package Lexer - * @subpackage Lexer - */ -class Doku_LexerStateStack { - var $_stack; - - /** - * Constructor. Starts in named state. - * @param string $start Starting state name. - * @access public - */ - function __construct($start) { - $this->_stack = array($start); - } - - /** - * Accessor for current state. - * @return string State. - * @access public - */ - function getCurrent() { - return $this->_stack[count($this->_stack) - 1]; - } - - /** - * Adds a state to the stack and sets it - * to be the current state. - * @param string $state New state. - * @access public - */ - function enter($state) { - array_push($this->_stack, $state); - } - - /** - * Leaves the current state and reverts - * to the previous one. - * @return boolean False if we drop off - * the bottom of the list. - * @access public - */ - function leave() { - if (count($this->_stack) == 1) { - return false; - } - array_pop($this->_stack); - return true; - } -} - -/** - * Accepts text and breaks it into tokens. - * Some optimisation to make the sure the - * content is only scanned by the PHP regex - * parser once. Lexer modes must not start - * with leading underscores. - * @package Doku - * @subpackage Lexer - */ -class Doku_Lexer { - var $_regexes; - var $_parser; - var $_mode; - var $_mode_handlers; - var $_case; - - /** - * Sets up the lexer in case insensitive matching - * by default. - * @param Doku_Parser $parser Handling strategy by - * reference. - * @param string $start Starting handler. - * @param boolean $case True for case sensitive. - * @access public - */ - function __construct($parser, $start = "accept", $case = false) { - $this->_case = $case; - /** @var Doku_LexerParallelRegex[] _regexes */ - $this->_regexes = array(); - $this->_parser = $parser; - $this->_mode = new Doku_LexerStateStack($start); - $this->_mode_handlers = array(); - } - - /** - * Adds a token search pattern for a particular - * parsing mode. The pattern does not change the - * current mode. - * @param string $pattern Perl style regex, but ( and ) - * lose the usual meaning. - * @param string $mode Should only apply this - * pattern when dealing with - * this type of input. - * @access public - */ - function addPattern($pattern, $mode = "accept") { - if (! isset($this->_regexes[$mode])) { - $this->_regexes[$mode] = new Doku_LexerParallelRegex($this->_case); - } - $this->_regexes[$mode]->addPattern($pattern); - } - - /** - * Adds a pattern that will enter a new parsing - * mode. Useful for entering parenthesis, strings, - * tags, etc. - * @param string $pattern Perl style regex, but ( and ) - * lose the usual meaning. - * @param string $mode Should only apply this - * pattern when dealing with - * this type of input. - * @param string $new_mode Change parsing to this new - * nested mode. - * @access public - */ - function addEntryPattern($pattern, $mode, $new_mode) { - if (! isset($this->_regexes[$mode])) { - $this->_regexes[$mode] = new Doku_LexerParallelRegex($this->_case); - } - $this->_regexes[$mode]->addPattern($pattern, $new_mode); - } - - /** - * Adds a pattern that will exit the current mode - * and re-enter the previous one. - * @param string $pattern Perl style regex, but ( and ) - * lose the usual meaning. - * @param string $mode Mode to leave. - * @access public - */ - function addExitPattern($pattern, $mode) { - if (! isset($this->_regexes[$mode])) { - $this->_regexes[$mode] = new Doku_LexerParallelRegex($this->_case); - } - $this->_regexes[$mode]->addPattern($pattern, "__exit"); - } - - /** - * Adds a pattern that has a special mode. Acts as an entry - * and exit pattern in one go, effectively calling a special - * parser handler for this token only. - * @param string $pattern Perl style regex, but ( and ) - * lose the usual meaning. - * @param string $mode Should only apply this - * pattern when dealing with - * this type of input. - * @param string $special Use this mode for this one token. - * @access public - */ - function addSpecialPattern($pattern, $mode, $special) { - if (! isset($this->_regexes[$mode])) { - $this->_regexes[$mode] = new Doku_LexerParallelRegex($this->_case); - } - $this->_regexes[$mode]->addPattern($pattern, "_$special"); - } - - /** - * Adds a mapping from a mode to another handler. - * @param string $mode Mode to be remapped. - * @param string $handler New target handler. - * @access public - */ - function mapHandler($mode, $handler) { - $this->_mode_handlers[$mode] = $handler; - } - - /** - * Splits the page text into tokens. Will fail - * if the handlers report an error or if no - * content is consumed. If successful then each - * unparsed and parsed token invokes a call to the - * held listener. - * @param string $raw Raw HTML text. - * @return boolean True on success, else false. - * @access public - */ - function parse($raw) { - if (! isset($this->_parser)) { - return false; - } - $initialLength = strlen($raw); - $length = $initialLength; - $pos = 0; - while (is_array($parsed = $this->_reduce($raw))) { - list($unmatched, $matched, $mode) = $parsed; - $currentLength = strlen($raw); - $matchPos = $initialLength - $currentLength - strlen($matched); - if (! $this->_dispatchTokens($unmatched, $matched, $mode, $pos, $matchPos)) { - return false; - } - if ($currentLength == $length) { - return false; - } - $length = $currentLength; - $pos = $initialLength - $currentLength; - } - if (!$parsed) { - return false; - } - return $this->_invokeParser($raw, DOKU_LEXER_UNMATCHED, $pos); - } - - /** - * Sends the matched token and any leading unmatched - * text to the parser changing the lexer to a new - * mode if one is listed. - * @param string $unmatched Unmatched leading portion. - * @param string $matched Actual token match. - * @param bool|string $mode Mode after match. A boolean - * false mode causes no change. - * @param int $initialPos - * @param int $matchPos - * Current byte index location in raw doc - * thats being parsed - * @return boolean False if there was any error - * from the parser. - * @access private - */ - function _dispatchTokens($unmatched, $matched, $mode = false, $initialPos, $matchPos) { - if (! $this->_invokeParser($unmatched, DOKU_LEXER_UNMATCHED, $initialPos) ){ - return false; - } - if ($this->_isModeEnd($mode)) { - if (! $this->_invokeParser($matched, DOKU_LEXER_EXIT, $matchPos)) { - return false; - } - return $this->_mode->leave(); - } - if ($this->_isSpecialMode($mode)) { - $this->_mode->enter($this->_decodeSpecial($mode)); - if (! $this->_invokeParser($matched, DOKU_LEXER_SPECIAL, $matchPos)) { - return false; - } - return $this->_mode->leave(); - } - if (is_string($mode)) { - $this->_mode->enter($mode); - return $this->_invokeParser($matched, DOKU_LEXER_ENTER, $matchPos); - } - return $this->_invokeParser($matched, DOKU_LEXER_MATCHED, $matchPos); - } - - /** - * Tests to see if the new mode is actually to leave - * the current mode and pop an item from the matching - * mode stack. - * @param string $mode Mode to test. - * @return boolean True if this is the exit mode. - * @access private - */ - function _isModeEnd($mode) { - return ($mode === "__exit"); - } - - /** - * Test to see if the mode is one where this mode - * is entered for this token only and automatically - * leaves immediately afterwoods. - * @param string $mode Mode to test. - * @return boolean True if this is the exit mode. - * @access private - */ - function _isSpecialMode($mode) { - return (strncmp($mode, "_", 1) == 0); - } - - /** - * Strips the magic underscore marking single token - * modes. - * @param string $mode Mode to decode. - * @return string Underlying mode name. - * @access private - */ - function _decodeSpecial($mode) { - return substr($mode, 1); - } - - /** - * Calls the parser method named after the current - * mode. Empty content will be ignored. The lexer - * has a parser handler for each mode in the lexer. - * @param string $content Text parsed. - * @param boolean $is_match Token is recognised rather - * than unparsed data. - * @param int $pos Current byte index location in raw doc - * thats being parsed - * @return bool - * @access private - */ - function _invokeParser($content, $is_match, $pos) { - if (($content === "") || ($content === false)) { - return true; - } - $handler = $this->_mode->getCurrent(); - if (isset($this->_mode_handlers[$handler])) { - $handler = $this->_mode_handlers[$handler]; - } - - // modes starting with plugin_ are all handled by the same - // handler but with an additional parameter - if(substr($handler,0,7)=='plugin_'){ - list($handler,$plugin) = explode('_',$handler,2); - return $this->_parser->$handler($content, $is_match, $pos, $plugin); - } - - return $this->_parser->$handler($content, $is_match, $pos); - } - - /** - * Tries to match a chunk of text and if successful - * removes the recognised chunk and any leading - * unparsed data. Empty strings will not be matched. - * @param string $raw The subject to parse. This is the - * content that will be eaten. - * @return array Three item list of unparsed - * content followed by the - * recognised token and finally the - * action the parser is to take. - * True if no match, false if there - * is a parsing error. - * @access private - */ - function _reduce(&$raw) { - if (! isset($this->_regexes[$this->_mode->getCurrent()])) { - return false; - } - if ($raw === "") { - return true; - } - if ($action = $this->_regexes[$this->_mode->getCurrent()]->split($raw, $split)) { - list($unparsed, $match, $raw) = $split; - return array($unparsed, $match, $action); - } - return true; - } -} - -/** - * Escapes regex characters other than (, ) and / - * - * @TODO - * - * @param string $str - * - * @return mixed - */ -function Doku_Lexer_Escape($str) { - //$str = addslashes($str); - $chars = array( - '/\\\\/', - '/\./', - '/\+/', - '/\*/', - '/\?/', - '/\[/', - '/\^/', - '/\]/', - '/\$/', - '/\{/', - '/\}/', - '/\=/', - '/\!/', - '/\</', - '/\>/', - '/\|/', - '/\:/' - ); - - $escaped = array( - '\\\\\\\\', - '\.', - '\+', - '\*', - '\?', - '\[', - '\^', - '\]', - '\$', - '\{', - '\}', - '\=', - '\!', - '\<', - '\>', - '\|', - '\:' - ); - return preg_replace($chars, $escaped, $str); -} - -//Setup VIM: ex: et ts=4 sw=4 : |