Compiles the pattern into one suitable for regex.

@return string   The regex pattern
970268
protected function compile()
	{
		if ($this->compiled !== false)
		{
			return $this->compiled;
		}

		if ($this->isStatic())
		{
			$this->compiled = '~^'.$this->pattern.'$~';
			return $this->compiled;
		}

		$compiled = $this->pattern;
		foreach ($this->getSegments($compiled) as $segment)
		{
			$compiled = \str_replace($segment['token'], $segment['regex'], $compiled);
		}

		$this->compiled = "~^{$compiled}$~";
		return $this->compiled;
	}
850865
protected function getTemplateRegexPattern()
    {
        $parts = explode('@', $this->template);
        if (count($parts) === 2) {
            $parts[0]    = str_replace('*', self::$nameRegex, $parts[0]);
            $topTLDIndex = strrpos($parts[1], '.');


            if ($topTLDIndex !== FALSE) {
                $secondTLD = substr($parts[1], 0, $topTLDIndex);
                $secondTLD = str_replace('*', self::$domainSecondTLDRegex, $secondTLD);

                $topTLD   = substr($parts[1], $topTLDIndex);
                $topTLD   = str_replace('*', self::$domainTLDRegex, $topTLD);
                $template = $parts[0] . '@' . $secondTLD . $topTLD;
            } else {
                $template = $parts[0] . '@' . $parts[1];
            }
        } else {
            $template = '';
        }

        //$template = str_replace(['.', '+', '-'], ['\.', '\+', '\-'], $template);

        return sprintf('/^%s$/', $template);
    }
564134
private function compileRegex()
    {
        // Prepend the prefix
        $path = $this->prefix . $this->path;

        $asserts = $this->asserts;

        // Replace placeholders in curly braces with named regex groups
        $callback = function ($matches) use ($asserts) {
            $name = $matches[1];
            $pattern = isset($asserts[$name]) ? $asserts[$name] : ".+";

            return "(?<$name>$pattern)";
        };

        $pattern = preg_replace_callback('/{([^}]+)}/', $callback, $path);

        // Avoid double slashes
        $pattern = preg_replace('/\/+/', '/', $pattern);

        // Escape slashes, used as delimiter in regex
        $pattern = str_replace('/', '\\/', $pattern);

        // Add start and and delimiters
        return "/^$pattern$/";
    }
990090
protected static function compileValidPattern()
    {
        self::compileUnencodedCharacters();

        $valid_characters = self::$unreserved_pattern . self::$sub_delims_pattern;

        $ip_v_future_pattern = '\[[\:' . $valid_characters . ']+\]';

        $reg_name_pattern = '([' . $valid_characters . ']|' . self::$pct_encoded_pattern . ')*';

        self::$part_pattern = $ip_v_future_pattern . '|'. $reg_name_pattern;

        self::$valid_pattern = '/^$|^' . //allows part to be empty
            $ip_v_future_pattern . '$|^' . $reg_name_pattern . '$/';
    }
1063741
protected function getEmbeddedRegexp()
    {
        // we need to alter the regexp we usr for std ref resolving, as it will be used to match parts of text, not the whole string
        $regexp = substr($this->getRegexp(), 1, -1);
        return '/' . preg_quote($this->beginToken). preg_replace(array('/^\^/'), array(''), $regexp) . '[^' . $this->endToken . ']+' . preg_quote($this->endToken) . '/';
    }
1351871
def _prepare_pattern(self, pattern):
        
        regex, _, rest = pattern.partition('\\;')
        try:
            return re.compile(regex, re.I)
        except re.error as e:
            warnings.warn(
                "Caught '{error}' compiling regex: {regex}"
                .format(error=e, regex=regex)
            )
            # regex that never matches:
            # http://stackoverflow.com/a/1845097/413622
            return re.compile(r'(?!x)x')
843706
protected function getRegex()
    {
        if ($this->regex === null) {
            $this->regex = $this->buildRegex($this->getTokens(), $this->constraints);
        }

        return $this->regex;
    }
477991
public function parse()
    {
        $matches = [];
        preg_match_all('@url\((.*)\)->find\(([-\.#\w]+)\)(?:->filter\(([-\.#\w]+)(?:,(.+))?\))?@', $this->get(), $matches);

        $this->url = $this->getOption('urlPrefix');
        if (!empty($matches[1][0])) {
            $this->url .= trim($matches[1][0], ' \'"');
        }
        if (!empty($matches[2][0])) {
            $this->selector = trim($matches[2][0], ' \'"');
        }
        if (!empty($matches[3][0])) {
            $this->filter->selector = trim($matches[3][0], ' \'"');
        }
        if (!empty($matches[4][0])) {
            $this->filter->length = (int) trim($matches[4][0]);
        }

        return $this;
    }
334087
protected function regexEncoding()
	{
		trigger_error('Function ' . __METHOD__ . ' not implemented yet');

		static $functionExists;

		if ($functionExists === null) {
			$functionExists = function_exists('\mb_regex_encoding');
		}

		if ($functionExists) {
			$args = func_get_args();
			return call_user_func_array('\mb_regex_encoding', $args);
		}
	}
105092
protected function getPattern()/*# : string */
    {
        if (is_null($this->reference_pattern)) {
            if ('' === $this->reference_start ||
                is_null($this->reference_end)) {
                $this->reference_pattern = '';
            } else {
                $this->reference_pattern = '~('  .
                    preg_quote($this->reference_start) .
                    '([a-zA-Z_][a-zA-Z0-9._]*+)' .
                    preg_quote($this->reference_end) . ')~';
            }
        }
        return $this->reference_pattern;
    }
454404
protected function compile()
	{		
		// Get the pattern model collection
		$colPattern = \PatternModel::findVisibleByPid($this->objElement->id);

		if ($colPattern === null)
		{
			return;
		}
		
		// Get correct content element id (included content element) see #37
		$intPid = ($this->origId) ? $this->origId : $this->id;
		
		// Get the data
		$colData = \DataModel::findByPid($intPid);

		if ($colData !== null)
		{
			foreach ($colData as $objData)
			{
				$arrData[$objData->pattern] = $objData;
			}							
		}

		// Prepare values for every pattern
		foreach($colPattern as $objPattern)
		{
			if (!Pattern::hasOutput($objPattern->type))
			{
				continue;
			}
			
			$strClass = Pattern::findClass($objPattern->type);
				
			if (!class_exists($strClass))
			{
				System::log('Pattern element class "'.$strClass.'" (pattern element "'.$objPattern->type.'") does not exist', __METHOD__, TL_ERROR);
			}
			else
			{
				$objPatternClass = new $strClass($objPattern);
				$objPatternClass->pid = $intPid;
				$objPatternClass->Template = $this->Template;
				$objPatternClass->data = $arrData[$objPattern->alias];
		
				$objPatternClass->compile();
			}
		}
	}
520047
static function compilePattern($pattern, array $options = array())
    {

        $len = strlen($pattern);
        /**
         * contains:
         *
         *   array( 'text', $text ),
         *   array( 'variable', $match[0][0][0], $regexp, $var);
         *
         */
        $tokens = array();
        $variables = array();
        $pos = 0;

        /**
         *  the path like:
         *
         *      /blog/to/:year/:month
         *
         *  will be separated like:
         *      
         *      [
         *          '/blog/to',  (text token)
         *          '/:year',    (reg exp token)
         *          '/:month',   (reg exp token)
         *      ]
         */
        $matches = self::splitTokens($pattern);


        // build tokens
        foreach ($matches as $matchIdx => $match) {
            // match[0][1] // matched position for pattern.

            /*
             * Split tokens from abstract pattern
             * to rebuild regexp pattern.
             */
            if ($text = substr($pattern, $pos, $match[0][1] - $pos)) {
                $tokens[] = array( self::TOKEN_TYPE_TEXT, $text);
            }

            // the first char from pattern (which is the seperater)
            // and the first char from the next match pattern
            $seps = array($pattern[$pos]);


            // collect the separator tokens from the next matched pattern
            if (isset($matches[$matchIdx + 1])) {
                $nextMatch = $matches[$matchIdx + 1];

                // check if the next pattern is an optional pattern
                if ($nextMatch[0][0][0] === '(') {

                    $r = self::compilePattern($nextMatch[2][0] ,array());
                    if (isset($r['tokens'][0][1])) {
                        $seps[] = $r['tokens'][0][1][0];
                    }

                } else if ($nextMatch[0][0][0] === ':') { // variable token

                } else {
                    $seps[] = $nextMatch[0][0][0];
                }
            }


            $pos = $match[0][1] + strlen($match[0][0]);


            // generate optional pattern recursively
            if ($match[0][0][0] == '(' ){
                $optional = $match[2][0];
                $subroute = self::compilePattern($optional ,array(
                    'default'   => isset($options['default']) ? $options['default'] : null,
                    'require'   => isset($options['require']) ? $options['require'] : null,
                    'variables' => isset($options['variables']) ? $options['variables'] : null,
                ));

                $tokens[] = array( 
                    self::TOKEN_TYPE_OPTIONAL,
                    $optional[0],
                    $subroute['regex'],
                );
                foreach( $subroute['variables'] as $var ) {
                    $variables[] = $var;
                }
            } else {
                // generate a variable token 
                $varName = $match[1][0];

                // if we defined a pattern for this variable, we should use the given pattern..
                if ( isset( $options['require'][$varName] ) && $req = $options['require'][$varName]) {
                    $regexp = $req;
                } else {
                    if ($pos !== $len) {
                        $seps[] = $pattern[$pos];
                    }
                    // use the default pattern (which is based on the separater charactors we got)
                    $regexp = sprintf('[^%s]+', preg_quote(implode('', array_unique($seps)), '#'));
                }

                // append token item
                $tokens[] = array(self::TOKEN_TYPE_VARIABLE, 
                    $match[0][0][0], 
                    $regexp, 
                    $varName);

                // append variable name
                $variables[] = $varName;
            }
        }

        if ($pos < $len) {
            $tokens[] = array(self::TOKEN_TYPE_TEXT, substr($pattern, $pos));
        }

        // find the first optional token
        $firstOptional = INF;
        for ($i = count($tokens) - 1; $i >= 0; $i--) {
            if ( self::TOKEN_TYPE_VARIABLE === $tokens[$i][0] 
                && isset($options['default'][ $tokens[$i][3] ]) )
            {
                $firstOptional = $i;
            } 
            else 
            {
                break;
            }
        }

        // compute the matching regexp
        $regex = '';

        // indentation level
        $indent = 1;


        // token item structure:
        //   [0] => token type,
        //   [1] => separator
        //   [2] => pattern
        //   [3] => name, 

        // first optional token and only one token.
        if (1 === count($tokens) && 0 === $firstOptional) {
            $token = $tokens[0];
            ++$indent;

            // output regexp with separator and
            $regex .= str_repeat(' ', $indent * 4) . sprintf("%s(?:\n", preg_quote($token[1], '#'));

            // regular expression with place holder name. (?P<name>pattern)
            $regex .= str_repeat(' ', $indent * 4) . sprintf("(?P<%s>%s)\n", $token[3], $token[2]);

        } else {
            foreach ($tokens as $i => $token) {

                switch ( $token[0] ) {
                case self::TOKEN_TYPE_TEXT:
                    $regex .= str_repeat(' ', $indent * 4) . preg_quote($token[1], '#')."\n";
                    break;
                case self::TOKEN_TYPE_OPTIONAL:
                    // the question mark is for optional, the optional item may contains multiple tokens and patterns
                    $regex .= str_repeat(' ', $indent * 4) . "(?:\n" . $token[2] . str_repeat(' ', $indent * 4) . ")?\n";
                    break;
                default:
                    // append new pattern group for the optional pattern
                    if ($i >= $firstOptional) {
                        $regex .= str_repeat(' ', $indent * 4) . "(?:\n";
                        ++$indent;
                    }
                    $regex .= str_repeat(' ', $indent * 4). sprintf("%s(?P<%s>%s)\n", preg_quote($token[1], '#'), $token[3], $token[2]);
                    break;
                }
            }
        }

        // close groups
        while (--$indent) {
            $regex .= str_repeat(' ', $indent * 4).")?\n";
        }

        // save variables
        $options['variables'] = $variables;
        $options['regex'] = $regex;
        $options['tokens'] = $tokens;
        return $options;
    }
705666
protected function compile()
    {
        // The URI should be considered literal except for keys and optional parts
        // Escape everything preg_quote would escape except for : ( ) < >
        $regex = preg_replace('#' . self::REGEX_ESCAPE . '#', '\\\\$0', $this->uri);

        if (strpos($regex, '(') !== false) {
            // Make optional parts of the URI non-capturing and optional
            $regex = str_replace(array('(', ')'), array('(?:', ')?'), $regex);
        }

        // Insert default regex for keys
        $regex = str_replace(array('<', '>'), array('(?P<', '>' . self::REGEX_SEGMENT . ')'), $regex);

        $search = $replace = array();
        foreach ($this->regex as $key => $value) {
            $search[] = "<$key>" . self::REGEX_SEGMENT;
            $replace[] = "<$key>$value";
        }

        // Replace the default regex with the user-specified regex
        return sprintf('#^%s$#', str_replace($search, $replace, $regex));
    }
591965
private function getDigitPattern()
    {
        if (!isset($this->digitPattern)) {
            $lengths = array_map('strlen', $this->digits->getDigits());

            if (count(array_flip($lengths)) === 1) {
                $this->digitPattern = array_pop($lengths);
            } else {
                $this->digitPattern = sprintf(
                    '(%s|.+)s%s',
                    implode('|', array_map('preg_quote', $this->digits->getDigits())),
                    $this->digits->isCaseSensitive() ? '' : 'i'
                );
            }
        }

        return $this->digitPattern;
    }
669749
def pattern(self):
        
        if self.dynamic_version_of is not None:
            return self.dynamic_version_of.pattern

        if not self._pattern:
            self._pattern = re.compile('^%s_(.+)$' % self.name)
        return self._pattern
1162154
public function regex()
    {
        // Turn "(/)" into "/?"
        $uri = preg_replace('#\(/\)#', '/?', $this->uri);

        // Create capture group for ":parameter", replaces ":parameter"
        $uri = $this->capture($uri, '/:(' . self::ALLOWED_REGEX . ')/');

        // Create capture group for '{parameter}', replaces "{parameter}"
        $uri = $this->capture($uri, '/{(' . self::ALLOWED_REGEX . ')}/');

        // Add start and end matching
        return (string) '@^' . $uri . '$@D';
    }
61223
public function compile()
	{
		//reset arrays
		$this->params     = [];
		$this->paramNames = [];
		$this->conditions = [];

		$this->compiled = true;

		$uri = $this->normalizeUri($this->getUri());

		// match patterns like /{param?:regex}
		// tested in https://regex101.com/r/gP6yH7
		$regex = preg_replace_callback(
			'#(?:(\\/)?\\{(\\w+)(\\?)?(?::((?:\\\\\\{|\\\\\\}|[^{}]|\\{\\d(?:\\,(?:\\d)?)?\\})+))?\\})#',
			[$this, 'createRegex'],
			$uri
		);

		$regex .= "/?";

		$regex = '#^' . $regex . '$#';

		if ($this->caseSensitive === false)
		{
			$regex .= 'i';
		}

		$this->pattern = $regex;

		return $this;
	}