Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/lexer.php
Go to the documentation of this file.
00001 <?php
00002 
00017     define("LEXER_ENTER", 1);
00019     define("LEXER_MATCHED", 2);
00021     define("LEXER_UNMATCHED", 3);
00023     define("LEXER_EXIT", 4);
00025     define("LEXER_SPECIAL", 5);
00026     
00035     class ParallelRegex {
00036         var $_patterns;
00037         var $_labels;
00038         var $_regex;
00039         var $_case;
00040         
00047         function ParallelRegex($case) {
00048             $this->_case = $case;
00049             $this->_patterns = array();
00050             $this->_labels = array();
00051             $this->_regex = null;
00052         }
00053         
00062         function addPattern($pattern, $label = true) {
00063             $count = count($this->_patterns);
00064             $this->_patterns[$count] = $pattern;
00065             $this->_labels[$count] = $label;
00066             $this->_regex = null;
00067         }
00068         
00078         function match($subject, &$match) {
00079             if (count($this->_patterns) == 0) {
00080                 return false;
00081             }
00082             if (!preg_match($this->_getCompoundedRegex(), $subject, $matches)) {
00083                 $match = "";
00084                 return false;
00085             }
00086             $match = $matches[0];
00087             for ($i = 1; $i < count($matches); $i++) {
00088                 if ($matches[$i]) {
00089                     return $this->_labels[$i - 1];
00090                 }
00091             }
00092             return true;
00093         }
00094         
00102         function _getCompoundedRegex() {
00103             if ($this->_regex == null) {
00104                 for ($i = 0; $i < count($this->_patterns); $i++) {
00105                     $this->_patterns[$i] = '(' . str_replace(
00106                             array('/', '(', ')'),
00107                             array('\/', '\(', '\)'),
00108                             $this->_patterns[$i]) . ')';
00109                 }
00110                 $this->_regex = "/" . implode("|", $this->_patterns) . "/" . $this->_getPerlMatchingFlags();
00111             }
00112             return $this->_regex;
00113         }
00114         
00120         function _getPerlMatchingFlags() {
00121             return ($this->_case ? "msS" : "msSi");
00122         }
00123     }
00124     
00132     class StateStack {
00133         var $_stack;
00134         
00140         function StateStack($start) {
00141             $this->_stack = array($start);
00142         }
00143         
00149         function getCurrent() {
00150             return $this->_stack[count($this->_stack) - 1];
00151         }
00152         
00159         function enter($state) {
00160             array_push($this->_stack, $state);
00161         }
00162         
00170         function leave() {
00171             if (count($this->_stack) == 1) {
00172                 return false;
00173             }
00174             array_pop($this->_stack);
00175             return true;
00176         }
00177     }
00178     
00190     class Lexer {
00191         var $_regexes;
00192         var $_parser;
00193         var $_mode;
00194         var $_mode_handlers;
00195         var $_case;
00196         
00206         function Lexer(&$parser, $start = "accept", $case = false) {
00207             $this->_case = $case;
00208             $this->_regexes = array();
00209             $this->_parser = &$parser;
00210             $this->_mode = new StateStack($start);
00211             $this->_mode_handlers = array();
00212         }
00213         
00225         function addPattern($pattern, $mode = "accept") {
00226             if (!isset($this->_regexes[$mode])) {
00227                 $this->_regexes[$mode] = new ParallelRegex($this->_case);
00228             }
00229             $this->_regexes[$mode]->addPattern($pattern);
00230         }
00231         
00245         function addEntryPattern($pattern, $mode, $new_mode) {
00246             if (!isset($this->_regexes[$mode])) {
00247                 $this->_regexes[$mode] = new ParallelRegex($this->_case);
00248             }
00249             $this->_regexes[$mode]->addPattern($pattern, $new_mode);
00250         }
00251         
00260         function addExitPattern($pattern, $mode) {
00261             if (!isset($this->_regexes[$mode])) {
00262                 $this->_regexes[$mode] = new ParallelRegex($this->_case);
00263             }
00264             $this->_regexes[$mode]->addPattern($pattern, "__exit");
00265         }
00266         
00278         function addSpecialPattern($pattern, $mode, $special) {
00279             if (!isset($this->_regexes[$mode])) {
00280                 $this->_regexes[$mode] = new ParallelRegex($this->_case);
00281             }
00282             $this->_regexes[$mode]->addPattern($pattern, "_$special");
00283         }
00284         
00291         function mapHandler($mode, $handler) {
00292             $this->_mode_handlers[$mode] = $handler;
00293         }
00294         
00305         function parse($raw) {
00306             if (!isset($this->_parser)) {
00307                 return false;
00308             }
00309             $length = strlen($raw);
00310             while (is_array($parsed = $this->_reduce($raw))) {
00311                 list($unmatched, $matched, $mode) = $parsed;
00312                 if (!$this->_dispatchTokens($unmatched, $matched, $mode)) {
00313                     return false;
00314                 }
00315                 if (strlen($raw) == $length) {
00316                     return false;
00317                 }
00318                 $length = strlen($raw);
00319             }
00320             if (!$parsed) {
00321                 return false;
00322             }
00323             return $this->_invokeParser($raw, LEXER_UNMATCHED);
00324         }
00325         
00339         function _dispatchTokens($unmatched, $matched, $mode = false) {
00340             if (!$this->_invokeParser($unmatched, LEXER_UNMATCHED)) {
00341                 return false;
00342             }
00343             if ($mode === "__exit") {
00344                 if (!$this->_invokeParser($matched, LEXER_EXIT)) {
00345                     return false;
00346                 }
00347                 return $this->_mode->leave();
00348             }
00349             if (strncmp($mode, "_", 1) == 0) {
00350                 $mode = substr($mode, 1);
00351                 $this->_mode->enter($mode);
00352                 if (!$this->_invokeParser($matched, LEXER_SPECIAL)) {
00353                     return false;
00354                 }
00355                 return $this->_mode->leave();
00356             }
00357             if (is_string($mode)) {
00358                 $this->_mode->enter($mode);
00359                 return $this->_invokeParser($matched, LEXER_ENTER);
00360             }
00361             return $this->_invokeParser($matched, LEXER_MATCHED);
00362         }
00363         
00372         function _invokeParser($content, $is_match) {
00373             if (($content === "") || ($content === false)) {
00374                 return true;
00375             }
00376             $handler = $this->_mode->getCurrent();
00377             if (isset($this->_mode_handlers[$handler])) {
00378                 $handler = $this->_mode_handlers[$handler];
00379             }
00380             return $this->_parser->$handler($content, $is_match);
00381         }
00382         
00397         function _reduce(&$raw) {
00398             if (!isset($this->_regexes[$this->_mode->getCurrent()])) {
00399                 return false;
00400             }
00401             if ($raw === "") {
00402                 return true;
00403             }
00404             if ($action = $this->_regexes[$this->_mode->getCurrent()]->match($raw, $match)) {
00405                 $count = strpos($raw, $match);
00406                 $unparsed = substr($raw, 0, $count);
00407                 $raw = substr($raw, $count + strlen($match));
00408                 return array($unparsed, $match, $action);
00409             }
00410             return true;
00411         }
00412     }
00413 ?>
 All Data Structures Namespaces Files Functions Variables Enumerations