Version: current

      1 <?php
      2
      3 /**
      4  * A tokenised regular expression is a parser, similar to a regular expression, that acts on tokens rather than characters.
      5  * This is a crucial component of the ManifestBuilder.
      6  * @package sapphire
      7  * @subpackage core
      8  */
      9 class TokenisedRegularExpression extends Object {
     10     /**
     11      * The regular expression definition
     12      */
     13     protected $expression;
     14
     15     function __construct($expression) {
     16         $this->expression = $expression;
     17         parent::__construct();
     18     }
     19
     20     function findAll($tokens) {
     21         $tokenTypes = array();
     22         foreach($tokens as $i => $token) {
     23             if(is_array($token)) {
     24                 $tokenTypes[$i] = $token[0];
     25             } else {
     26                 $tokenTypes[$i] = $token;
     27                 // Pre-process string tokens for matchFrom()
     28                 $tokens[$i] = array($token, $token);
     29             }
     30         }
     31
     32         $startKeys = array_keys($tokenTypes, $this->expression[0]);
     33         $allMatches = array();
     34
     35         foreach($startKeys as $startKey) {
     36             $matches = array();
     37             if($this->matchFrom($startKey, 0, $tokens, $matches)) {
     38                 $allMatches[] = $matches;
     39             }
     40         }
     41         return $allMatches;
     42     }
     43
     44     function matchFrom($tokenPos, $expressionPos, &$tokens, &$matches) {
     45         $expressionRule = $this->expression[$expressionPos];
     46         $expectation = is_array($expressionRule) ? $expressionRule[0] : $expressionRule;
     47         if(!is_array($expressionRule)) $expressionRule = array();
     48
     49         if($expectation == $tokens[$tokenPos][0]) {
     50             if(isset($expressionRule['save_to'])) {
     51                 // Append to an array
     52                 if(substr($expressionRule['save_to'],-2) == '[]') $matches[substr($expressionRule['save_to'],0,-2)][] = $tokens[$tokenPos][1];
     53                 // Regular variable setting
     54                 else $matches[$expressionRule['save_to']] = $tokens[$tokenPos][1];
     55             }
     56
     57             // End of the expression
     58             if(!isset($this->expression[$expressionPos+1])) {
     59                 return true;
     60
     61             // Process next step as normal
     62             } else if($this->matchFrom($tokenPos+1, $expressionPos+1, $tokens, $matches)) {
     63                 return true;
     64
     65             // This step is optional
     66             } else if(isset($expressionRule['optional']) && $this->matchFrom($tokenPos, $expressionPos+1, $tokens, $matches)) {
     67                 return true;
     68
     69             // Process jumps
     70             } else if(isset($expressionRule['can_jump_to'])) {
     71                 if(is_array($expressionRule['can_jump_to'])) foreach($expressionRule['can_jump_to'] as $canJumpTo) {
     72                     // can_jump_to & optional both set
     73                     if(isset($expressionRule['optional']) && $this->matchFrom($tokenPos, $canJumpTo, $tokens, $matches)) {
     74                         return true;
     75                     }
     76                     // can_jump_to set (optional may or may not be set)
     77                     if($this->matchFrom($tokenPos+1, $canJumpTo, $tokens, $matches)) {
     78                         return true;
     79                     }
     80
     81                 } else {
     82                     // can_jump_to & optional both set
     83                     if(isset($expressionRule['optional']) && $this->matchFrom($tokenPos, $expressionRule['can_jump_to'], $tokens, $matches)) {
     84                         return true;
     85                     }
     86                     // can_jump_to set (optional may or may not be set)
     87                     if($this->matchFrom($tokenPos+1, $expressionRule['can_jump_to'], $tokens, $matches)) {
     88                         return true;
     89                     }
     90                 }
     91             }
     92
     93         } else if(isset($expressionRule['optional'])) {
     94             if(isset($this->expression[$expressionPos+1])) return $this->matchFrom($tokenPos, $expressionPos+1, $tokens, $matches);
     95             else return true;
     96         }
     97
     98         return false;
     99
    100     }
    101 }

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -