lithium\analysis\Parser::find PHP Method

find() public static method

Finds a pattern in a block of code.
public static find ( string $code, string $pattern, array $options = [] ) : array
$code string
$pattern string
$options array The list of options to be used when parsing / matching `$code`: - 'ignore': An array of token names to ignore while parsing, defaults to `array('T_WHITESPACE')` - 'lineBreaks': If true, all tokens in a single pattern match must appear on the same line of code, defaults to false - 'startOfLine': If true, the pattern must match starting with the beginning of the line of code to be matched, defaults to false
return array
    public static function find($code, $pattern, array $options = array())
    {
        $defaults = array('all' => true, 'capture' => array(), 'ignore' => array('T_WHITESPACE'), 'return' => true, 'lineBreaks' => false, 'startOfLine' => false);
        $options += $defaults;
        $results = array();
        $matches = array();
        $patternMatch = array();
        $ret = $options['return'];
        $tokens = new Collection(array('data' => static::tokenize($code, $options)));
        $pattern = new Collection(array('data' => static::tokenize($pattern, $options)));
        $breaks = function ($token) use(&$tokens, &$matches, &$patternMatch, $options) {
            if (!$options['lineBreaks']) {
                return true;
            }
            if (empty($patternMatch) && !$options['startOfLine']) {
                return true;
            }
            if (empty($patternMatch)) {
                $prev = $tokens->prev();
                $tokens->next();
            } else {
                $prev = reset($patternMatch);
            }
            if (empty($patternMatch) && $options['startOfLine']) {
                return $token['line'] > $prev['line'];
            }
            return $token['line'] === $prev['line'];
        };
        $capture = function ($token) use(&$matches, &$patternMatch, $tokens, $breaks, $options) {
            if ($token === null) {
                $matches = $patternMatch = array();
                return false;
            }
            if (empty($patternMatch)) {
                $prev = $tokens->prev();
                $tokens->next();
                if ($options['startOfLine'] && $token['line'] === $prev['line']) {
                    $patternMatch = $matches = array();
                    return false;
                }
            }
            $patternMatch[] = $token;
            if (empty($options['capture']) || !in_array($token['name'], $options['capture'])) {
                return true;
            }
            if (!$breaks($token)) {
                $matches = array();
                return true;
            }
            $matches[] = $token;
            return true;
        };
        $executors = array('*' => function (&$tokens, &$pattern) use($options, $capture) {
            $closing = $pattern->next();
            $tokens->prev();
            while (($t = $tokens->next()) && !Parser::matchToken($closing, $t)) {
                $capture($t);
            }
            $pattern->next();
        });
        $tokens->rewind();
        $pattern->rewind();
        while ($tokens->valid()) {
            if (!$pattern->valid()) {
                $pattern->rewind();
                if (!empty($matches)) {
                    $results[] = array_map(function ($i) use($ret) {
                        return isset($i[$ret]) ? $i[$ret] : $i;
                    }, $matches);
                }
                $capture(null);
            }
            $p = $pattern->current();
            $t = $tokens->current();
            switch (true) {
                case static::matchToken($p, $t):
                    $capture($t) ? $pattern->next() : $pattern->rewind();
                    break;
                case isset($executors[$p['name']]):
                    $exec = $executors[$p['name']];
                    $exec($tokens, $pattern);
                    break;
                default:
                    $capture(null);
                    $pattern->rewind();
                    break;
            }
            $tokens->next();
        }
        return $results;
    }

Usage Example

Exemplo n.º 1
0
 /**
  * Gets the static and dynamic dependencies for a class or group of classes.
  *
  * @param mixed $classes Either a string specifying a class, or a numerically indexed array
  *        of classes
  * @param array $options
  * @return array An array of the static and dynamic class dependencies
  * @todo Document valid options
  */
 public static function dependencies($classes, array $options = array())
 {
     $defaults = array('type' => null);
     $options += $defaults;
     $static = $dynamic = array();
     $trim = function ($c) {
         return trim(trim($c, '\\'));
     };
     $join = function ($i) {
         return join('', $i);
     };
     foreach ((array) $classes as $class) {
         $data = explode("\n", file_get_contents(Libraries::path($class)));
         $data = "<?php \n" . join("\n", preg_grep('/^\\s*use /', $data)) . "\n ?>";
         $classes = array_map($join, Parser::find($data, 'use *;', array('return' => 'content', 'lineBreaks' => true, 'startOfLine' => true, 'capture' => array('T_STRING', 'T_NS_SEPARATOR'))));
         if ($classes) {
             $static = array_unique(array_merge($static, array_map($trim, $classes)));
         }
         $classes = static::info($class . '::$_classes', array('value'));
         if (isset($classes['value'])) {
             $dynamic = array_merge($dynamic, array_map($trim, array_values($classes['value'])));
         }
     }
     if (empty($options['type'])) {
         return array_unique(array_merge($static, $dynamic));
     }
     $type = $options['type'];
     return isset(${$type}) ? ${$type} : null;
 }
All Usage Examples Of lithium\analysis\Parser::find