[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/s9e/text-formatter/src/Configurator/Helpers/ -> RegexpParser.php (source)

   1  <?php
   2  
   3  /*
   4  * @package   s9e\TextFormatter
   5  * @copyright Copyright (c) 2010-2019 The s9e Authors
   6  * @license   http://www.opensource.org/licenses/mit-license.php The MIT License
   7  */
   8  namespace s9e\TextFormatter\Configurator\Helpers;
   9  use RuntimeException;
  10  abstract class RegexpParser
  11  {
  12  	public static function getAllowedCharacterRegexp($regexp)
  13      {
  14          $def = self::parse($regexp);
  15          if (\strpos($def['modifiers'], 'm') !== \false)
  16              return '//';
  17          if (\substr($def['regexp'], 0, 1) !== '^'
  18           || \substr($def['regexp'], -1)   !== '$')
  19              return '//';
  20          $def['tokens'][] = [
  21              'pos'  => \strlen($def['regexp']),
  22              'len'  => 0,
  23              'type' => 'end'
  24          ];
  25          $patterns = [];
  26          $literal = '';
  27          $pos     = 0;
  28          $skipPos = 0;
  29          $depth   = 0;
  30          foreach ($def['tokens'] as $token)
  31          {
  32              if ($token['type'] === 'option')
  33                  $skipPos = \max($skipPos, $token['pos'] + $token['len']);
  34              if (\strpos($token['type'], 'AssertionStart') !== \false)
  35              {
  36                  $endToken = $def['tokens'][$token['endToken']];
  37                  $skipPos  = \max($skipPos, $endToken['pos'] + $endToken['len']);
  38              }
  39              if ($token['pos'] >= $skipPos)
  40              {
  41                  if ($token['type'] === 'characterClass')
  42                      $patterns[] = '[' . $token['content'] . ']';
  43                  if ($token['pos'] > $pos)
  44                  {
  45                      $tmp = \substr($def['regexp'], $pos, $token['pos'] - $pos);
  46                      $literal .= $tmp;
  47                      if (!$depth)
  48                      {
  49                          $tmp = \str_replace('\\\\', '', $tmp);
  50                          if (\preg_match('/(?<!\\\\)\\|(?!\\^)/', $tmp))
  51                              return '//';
  52                          if (\preg_match('/(?<![$\\\\])\\|/', $tmp))
  53                              return '//';
  54                      }
  55                  }
  56              }
  57              if (\substr($token['type'], -5) === 'Start')
  58                  ++$depth;
  59              elseif (\substr($token['type'], -3) === 'End')
  60                  --$depth;
  61              $pos = \max($skipPos, $token['pos'] + $token['len']);
  62          }
  63          if (\preg_match('#(?<!\\\\)(?:\\\\\\\\)*\\.#', $literal))
  64          {
  65              if (\strpos($def['modifiers'], 's') !== \false
  66               || \strpos($literal, "\n") !== \false)
  67                  return '//';
  68              $patterns[] = '.';
  69              $literal = \preg_replace('#(?<!\\\\)((?:\\\\\\\\)*)\\.#', '$1', $literal);
  70          }
  71          $literal = \preg_replace('#(?<!\\\\)((?:\\\\\\\\)*)[*+?]#', '$1', $literal);
  72          $literal = \preg_replace('#(?<!\\\\)((?:\\\\\\\\)*)\\{[^}]+\\}#', '$1', $literal);
  73          $literal = \preg_replace('#(?<!\\\\)((?:\\\\\\\\)*)\\\\[bBAZzG1-9]#', '$1', $literal);
  74          $literal = \preg_replace('#(?<!\\\\)((?:\\\\\\\\)*)[$^|]#', '$1', $literal);
  75          $literal = \preg_replace('#(?<!\\\\)((?:\\\\\\\\)*)([-^\\]])#', '$1\\\\$2', $literal);
  76          if (\strpos($def['modifiers'], 'D') === \false)
  77              $literal .= "\n";
  78          if ($literal !== '')
  79              $patterns[] = '[' . $literal . ']';
  80          if (empty($patterns))
  81              return '/^$/D';
  82          $regexp = $def['delimiter'] . \implode('|', $patterns) . $def['delimiter'];
  83          if (\strpos($def['modifiers'], 'i') !== \false)
  84              $regexp .= 'i';
  85          if (\strpos($def['modifiers'], 'u') !== \false)
  86              $regexp .= 'u';
  87          return $regexp;
  88      }
  89  	public static function getCaptureNames($regexp)
  90      {
  91          $map        = [''];
  92          $regexpInfo = self::parse($regexp);
  93          foreach ($regexpInfo['tokens'] as $tok)
  94              if ($tok['type'] === 'capturingSubpatternStart')
  95                  $map[] = (isset($tok['name'])) ? $tok['name'] : '';
  96          return $map;
  97      }
  98  	public static function parse($regexp)
  99      {
 100          if (!\preg_match('#^(.)(.*?)\\1([a-zA-Z]*)$#Ds', $regexp, $m))
 101              throw new RuntimeException('Could not parse regexp delimiters');
 102          $ret = [
 103              'delimiter' => $m[1],
 104              'modifiers' => $m[3],
 105              'regexp'    => $m[2],
 106              'tokens'    => []
 107          ];
 108          $regexp = $m[2];
 109          $openSubpatterns = [];
 110          $pos = 0;
 111          $regexpLen = \strlen($regexp);
 112          while ($pos < $regexpLen)
 113          {
 114              switch ($regexp[$pos])
 115              {
 116                  case '\\':
 117                      $pos += 2;
 118                      break;
 119                  case '[':
 120                      if (!\preg_match('#\\[(.*?(?<!\\\\)(?:\\\\\\\\)*+)\\]((?:[+*][+?]?|\\?)?)#A', $regexp, $m, 0, $pos))
 121                          throw new RuntimeException('Could not find matching bracket from pos ' . $pos);
 122                      $ret['tokens'][] = [
 123                          'pos'         => $pos,
 124                          'len'         => \strlen($m[0]),
 125                          'type'        => 'characterClass',
 126                          'content'     => $m[1],
 127                          'quantifiers' => $m[2]
 128                      ];
 129                      $pos += \strlen($m[0]);
 130                      break;
 131                  case '(':
 132                      if (\preg_match('#\\(\\?([a-z]*)\\)#iA', $regexp, $m, 0, $pos))
 133                      {
 134                          $ret['tokens'][] = [
 135                              'pos'     => $pos,
 136                              'len'     => \strlen($m[0]),
 137                              'type'    => 'option',
 138                              'options' => $m[1]
 139                          ];
 140                          $pos += \strlen($m[0]);
 141                          break;
 142                      }
 143                      if (\preg_match("#(?J)\\(\\?(?:P?<(?<name>[a-z_0-9]+)>|'(?<name>[a-z_0-9]+)')#A", $regexp, $m, \PREG_OFFSET_CAPTURE, $pos))
 144                      {
 145                          $tok = [
 146                              'pos'  => $pos,
 147                              'len'  => \strlen($m[0][0]),
 148                              'type' => 'capturingSubpatternStart',
 149                              'name' => $m['name'][0]
 150                          ];
 151                          $pos += \strlen($m[0][0]);
 152                      }
 153                      elseif (\preg_match('#\\(\\?([a-z]*):#iA', $regexp, $m, 0, $pos))
 154                      {
 155                          $tok = [
 156                              'pos'     => $pos,
 157                              'len'     => \strlen($m[0]),
 158                              'type'    => 'nonCapturingSubpatternStart',
 159                              'options' => $m[1]
 160                          ];
 161                          $pos += \strlen($m[0]);
 162                      }
 163                      elseif (\preg_match('#\\(\\?>#iA', $regexp, $m, 0, $pos))
 164                      {
 165                          $tok = [
 166                              'pos'     => $pos,
 167                              'len'     => \strlen($m[0]),
 168                              'type'    => 'nonCapturingSubpatternStart',
 169                              'subtype' => 'atomic'
 170                          ];
 171                          $pos += \strlen($m[0]);
 172                      }
 173                      elseif (\preg_match('#\\(\\?(<?[!=])#A', $regexp, $m, 0, $pos))
 174                      {
 175                          $assertions = [
 176                              '='  => 'lookahead',
 177                              '<=' => 'lookbehind',
 178                              '!'  => 'negativeLookahead',
 179                              '<!' => 'negativeLookbehind'
 180                          ];
 181                          $tok = [
 182                              'pos'     => $pos,
 183                              'len'     => \strlen($m[0]),
 184                              'type'    => $assertions[$m[1]] . 'AssertionStart'
 185                          ];
 186                          $pos += \strlen($m[0]);
 187                      }
 188                      elseif (\preg_match('#\\(\\?#A', $regexp, $m, 0, $pos))
 189                          throw new RuntimeException('Unsupported subpattern type at pos ' . $pos);
 190                      else
 191                      {
 192                          $tok = [
 193                              'pos'  => $pos,
 194                              'len'  => 1,
 195                              'type' => 'capturingSubpatternStart'
 196                          ];
 197                          ++$pos;
 198                      }
 199                      $openSubpatterns[] = \count($ret['tokens']);
 200                      $ret['tokens'][] = $tok;
 201                      break;
 202                  case ')':
 203                      if (empty($openSubpatterns))
 204                          throw new RuntimeException('Could not find matching pattern start for right parenthesis at pos ' . $pos);
 205                      $k = \array_pop($openSubpatterns);
 206                      $startToken =& $ret['tokens'][$k];
 207                      $startToken['endToken'] = \count($ret['tokens']);
 208                      $startToken['content']  = \substr(
 209                          $regexp,
 210                          $startToken['pos'] + $startToken['len'],
 211                          $pos - ($startToken['pos'] + $startToken['len'])
 212                      );
 213                      $spn = \strspn($regexp, '+*?', 1 + $pos);
 214                      $quantifiers = \substr($regexp, 1 + $pos, $spn);
 215                      $ret['tokens'][] = [
 216                          'pos'  => $pos,
 217                          'len'  => 1 + $spn,
 218                          'type' => \substr($startToken['type'], 0, -5) . 'End',
 219                          'quantifiers' => $quantifiers
 220                      ];
 221                      unset($startToken);
 222                      $pos += 1 + $spn;
 223                      break;
 224                  default:
 225                      ++$pos;
 226              }
 227          }
 228          if (!empty($openSubpatterns))
 229              throw new RuntimeException('Could not find matching pattern end for left parenthesis at pos ' . $ret['tokens'][$openSubpatterns[0]]['pos']);
 230          return $ret;
 231      }
 232  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1