Regular Expressions 101

Save & Share

Flavor

  • PCRE2 (PHP >=7.3)
  • PCRE (PHP <7.3)
  • ECMAScript (JavaScript)
  • Python
  • Golang
  • Java 8
  • .NET 7.0 (C#)
  • Rust
  • Regex Flavor Guide

Function

  • Match
  • Substitution
  • List
  • Unit Tests

Tools

Sponsors
There are currently no sponsors. Become a sponsor today!
An explanation of your regex will be automatically generated as you type.
Detailed match information will be displayed here automatically.
  • All Tokens
  • Common Tokens
  • General Tokens
  • Anchors
  • Meta Sequences
  • Quantifiers
  • Group Constructs
  • Character Classes
  • Flags/Modifiers
  • Substitution
  • A single character of: a, b or c
    [abc]
  • A character except: a, b or c
    [^abc]
  • A character in the range: a-z
    [a-z]
  • A character not in the range: a-z
    [^a-z]
  • A character in the range: a-z or A-Z
    [a-zA-Z]
  • Any single character
    .
  • Alternate - match either a or b
    a|b
  • Any whitespace character
    \s
  • Any non-whitespace character
    \S
  • Any digit
    \d
  • Any non-digit
    \D
  • Any word character
    \w
  • Any non-word character
    \W
  • Match everything enclosed
    (?:...)
  • Capture everything enclosed
    (...)
  • Zero or one of a
    a?
  • Zero or more of a
    a*
  • One or more of a
    a+
  • Exactly 3 of a
    a{3}
  • 3 or more of a
    a{3,}
  • Between 3 and 6 of a
    a{3,6}
  • Start of string
    ^
  • End of string
    $
  • A word boundary
    \b
  • Non-word boundary
    \B

Regular Expression

/
/
ixgms

Test String

Code Generator

Generated Code

re = /(\s+)(?:abstract\s+|final\s+|private\s+|protected\s+|public\s+)?(?:static\s+)?(function)\s+(\w+)\s*(\((?>[^()]+|(?R))*\))|({(?>[^{}]+|(?R))*})/ixm str = '<?php declare(strict_types=1); namespace PHPAstVisualizer; use phpDocumentor\\GraphViz\\Edge as GraphEdge; use phpDocumentor\\GraphViz\\Graph; use phpDocumentor\\GraphViz\\Node as GraphNode; class Options { private $options = [ \'graph\' => [], \'node\' => [\'shape\' => \'rect\'], \'edge\' => [], \'childEdge\' => [\'style\' => \'dashed\',\'arrowhead\' => \'empty\'], ]; private $name; } public function __construct(string $name, array $options = []) { $this->name = $name; $this->graphOptions = array_merge($this->options, $options); } public function getName(): string { return $this->name; } public function graph(Graph $graph) { foreach ($this->options[\'graph\'] as $name => $value) { $graph->{\'set\' . $name}($value); } } public function node(GraphNode $node) { foreach ($this->options[\'node\'] as $name => $value) { $node->{\'set\' . $name}($value); } } public function childEdge(GraphEdge $edge) { $this->edge($edge); foreach ($this->options[\'childEdge\'] as $name => $value) { $edge->{\'set\' . $name}($value); } } public function edge(GraphEdge $edge) { foreach ($this->options[\'edge\'] as $name => $value) { $edge->{\'set\' . $name}($value); } } } /** * PHP file with an autoload function which will be included into the * sandbox of the InstantSVC CodeAnalyzer * @var string */ protected $autoloadFile = \'\'; /** * Sets the output driver and initializes * @param CallgraphDriver $driver output driver to use * @return PHPCallGraph */ public function __construct(CallgraphDriver $driver = null) { if ($driver != null) { $this->driver = $driver; } else { $this->driver = new TextDriver(); } $functions = get_defined_functions(); $this->internalFunctions = $functions[\'internal\']; // List of PHP keywords which could be followed by an opening parenthis // taken from PHP Manual (http://www.php.net/reserved_keywords) $this->internalKeywords = array( \'array\', \'declare\', \'die\', \'echo\', \'elseif\', \'empty\', \'eval\', \'exit\', \'for\', \'foreach\', \'global\', \'if\', \'include\', \'include_once\', \'isset\', \'list\', \'print\', \'require\', \'require_once\', \'return\', \'switch\', \'unset\', \'while\', \'catch\', \'or\', \'and\', \'xor\', \'new Exception\'); $this->constants = array_keys(get_defined_constants()); //TODO: provide setter for this //$this->ignoreList = array(\'PHPCallGraph::setDriver\', \'PHPCallGraph::__construct\', \'PHPCallGraph::setShowExternalCalls\', \'PHPCallGraph::setShowInternalFunctions\', \'PHPCallGraph::save\', \'PHPCallGraph::__toString\'); } public function setDriver(CallgraphDriver $driver = null) { if ($driver != null) { $this->driver = $driver; } } /** * Enable or disable printing of debug information * @param boolean $enabled */ public function setDebug($enabled = true) { $this->debug = $enabled; } protected function debug($string) { if ($this->debug) { print "||PHPCallGraph| ".$string."\\n"; } } protected function info($string) { if ($this->showInfo) { print "||PHPCallGraph| ".$string."\\n"; } } protected function warning($string) { if ($this->showWarnings) { print "||PHPCallGraph* *WARNING* ".$string."\\n"; } } /** * Sets a PHP file with an autoload function which will be included into * the sandbox of the InstantSVC CodeAnalyzer * @param string $filename Name of a PHP file with an autoload function * @return boolean success */ public function setAutoloadFile($filename) { $returnValue = false; if (!empty($filename) and is_file($filename) and is_readable($filename)) { $this->autoloadFile = $filename; $returnValue = true; } else { //TODO: throw exception } return $returnValue; } public function setShowExternalCalls($boolean = true) { $this->showExternalCalls = $boolean; } public function setShowInternalFunctions($boolean = true) { $this->showInternalFunctions = $boolean; } public function collectFileNames(array $filesOrDirs, $recursive = false) { $files = array(); foreach ($filesOrDirs as $fileOrDir) { if (is_file($fileOrDir)) { $files[] = $fileOrDir; } elseif (is_dir($fileOrDir)) { $globbed = glob("$fileOrDir/*"); if ($recursive) { $files = array_merge($files, $this->collectFileNames($globbed, true)); } else { foreach($globbed as $path) { if (is_file($path)) { $files[] = $path; } } } } } return $files; } public function parse(array $filesOrDirs, $recursive = false) { $files = $this->collectFileNames($filesOrDirs, $recursive); if ($this->debug) { var_dump($files); } $ca = new iscCodeAnalyzer(null); $ca->setDebug($this->debug); $ca->setAutoloadFile($this->autoloadFile); $ca->inspectFiles($files); $this->codeSummary = $ca->getCodeSummary(); $this->analyseCodeSummary(); } public function parseFile($file) { $ca = new iscCodeAnalyzer(null); $ca->setDebug($this->debug); $ca->setAutoloadFile($this->autoloadFile); $ca->inspectFiles(array($file)); $this->codeSummary = $ca->getCodeSummary(); $this->analyseCodeSummary(); } public function parseDir($dir = \'.\') { $ca = new iscCodeAnalyzer($dir); $ca->setDebug($this->debug); $ca->setAutoloadFile($this->autoloadFile); $ca->collect(); $this->codeSummary = $ca->getCodeSummary(); $this->analyseCodeSummary(); } public function analyseCodeSummary() { $this->buildLookupTables(); //TODO: analyze code in the global scope // currently a workarround is to manually wrap such code // in a dummy function called dummyFunctionForFile_filename_php() // analyze functions if (!empty($this->codeSummary[\'functions\'])) { foreach ($this->codeSummary[\'functions\'] as $functionName => $function) { $this->parseMethodBody( \'-\', $functionName, array(), array(), $function[\'file\'], $function[\'startLine\'], $function[\'endLine\'] ); } } // analyze classes if (!empty($this->codeSummary[\'classes\'])) { foreach ($this->codeSummary[\'classes\'] as $className => $class) { /* echo $className, "\\n"; var_export($class); echo "\\n\\n"; //*/ if (!empty($class[\'methods\'])) { $propertyNames = array_keys($class[\'properties\']); $methodNames = array_keys($class[\'methods\']); //var_export($propertyNames); //var_export($methodNames); foreach ($class[\'methods\'] as $methodName => $method) { $this->parseMethodBody( $className, $methodName, $propertyNames, $methodNames, $class[\'file\'], $method[\'startLine\'], $method[\'endLine\'] ); } } } } } protected function buildLookupTables() { if (!empty($this->codeSummary[\'classes\'])) { foreach ($this->codeSummary[\'classes\'] as $className => $class) { //currently unused /* if (!empty($class[\'properties\'])) { foreach ($class[\'properties\'] as $propertyName => $property) { $this->propertyLookupTable[$propertyName][] = $className; } } //*/ if (!empty($class[\'methods\'])) { foreach ($class[\'methods\'] as $methodName => $method) { $this->methodLookupTable[$methodName][] = $className; } } } } } /** * @param string $className * @param string $methodName * @param array $propertyNames * @param array $methodNames * @param string $file * @param integer $startLine * @param integer $endLine */ public function parseMethodBody( $className, $methodName, Array $propertyNames, Array $methodNames, $file, $startLine, $endLine ) { if ($className == \'-\') { // we are analyzing a function not a method if (substr($methodName, 0, strlen(\'dummyFunctionForFile_\')) == \'dummyFunctionForFile_\') { // the function has been introduced manually to encapsulate code in the global scope $callerName = str_replace(\'_\', \'.\', substr($methodName, strlen(\'dummyFunctionForFile_\'))) . \'(File)\'; } else { $callerName = $methodName . $this->generateParametersForSignature($this->codeSummary[\'functions\'][$methodName][\'params\']); } } else { //TODO: visibilities $callerName = $className . \'::\' . $methodName . $this->generateParametersForSignature($this->codeSummary[\'classes\'][$className][\'methods\'][$methodName][\'params\']); } $callerNameWithoutParameterList = substr($callerName, 0, strpos($callerName, \'(\')); if (!in_array($callerNameWithoutParameterList, $this->ignoreList)) { $this->debug(\'phpCallGraph: analyzing \' . $callerName); $offset = $startLine - 1; $length = $endLine - $startLine + 1; // obtain source code $memberCode = implode(\'\', array_slice(file($file), $offset, $length)); $memberCode = "<?php\\nclass $className {\\n" . $memberCode . "}\\n?>\\n"; //echo $memberCode; $this->debug("= Analyzing $callerName ="); $this->info(" defined in $file on line $offset"); $this->driver->startFunction($offset, $file, $callerName, $memberCode); $insideDoubleQuotedString = false; $lineNumber = $offset - 1; $blocksStarted = 0; // parse source code $tokens = token_get_all($memberCode); /* if ($methodName == \'__construct\') { print_r($tokens); } //*/ //TODO: implement a higher level API for working with PHP parser tokens (e.g. TokenIterator) foreach ($tokens as $i => $token) { //TODO: obtain method signature directly from the source file if (is_array($token)) { $lineNumber+= substr_count($token[1], "\\n"); } /* if (count($token) == 3) { echo "\\t", token_name($token[0]), "\\n"; echo "\\t\\t", $token[1], "\\n"; } else { echo "\\t", $token[0], "\\n"; } //*/ // skip call analysis for the method signature if ($blocksStarted < 2) { // method body not yet started if ($token[0] == \'{\') { ++$blocksStarted; } continue; } if (!$insideDoubleQuotedString and $token == \'"\') { $insideDoubleQuotedString = true; } elseif ($insideDoubleQuotedString and $token == \'"\') { $insideDoubleQuotedString = false; } elseif (!$insideDoubleQuotedString and $token != \'"\') { if ($token[0] == T_STRING //and ($token[1] != $className or $tokens[$i - 2][0] == T_NEW ) //and $token[1] != $methodName ) { if ( !in_array($token[1], $propertyNames) //TODO: property name equals name of a function or method and !in_array($token[1], $this->constants) //TODO: constant name equals name of a function or method and $token[1] != \'true\' and $token[1] != \'false\' and $token[1] != \'null\' ) { $previousPreviousPreviousToken = $tokens[ $i - 3 ]; $previousPreviousToken = $tokens[ $i - 2 ]; $previousToken = $tokens[ $i - 1 ]; $nextToken = $tokens[ $i + 1 ]; $tokenAfterNext = $tokens[ $i + 2 ]; $this->info($this->getTokenValues($tokens, $i)); if ($nextToken[0] == T_DOUBLE_COLON) { // beginning of a call to a static method //nop continue; } elseif ( ( $tokens[ $i - 4][0] == T_CATCH and $previousPreviousPreviousToken[0] == T_WHITESPACE and $previousPreviousToken == \'(\' and $previousToken[0] == T_WHITESPACE ) or ( $previousPreviousPreviousToken[0] == T_CATCH and $previousPreviousToken[0] == T_WHITESPACE and $previousToken == \'(\' ) or ( $previousPreviousToken[0] == T_CATCH and $previousToken == \'(\' ) ){ // catch block continue; } elseif ($previousPreviousToken[0] == T_NEW){ $this->debug(\'Found object creation with new operator\'); if (!$this->showExternalCalls) { continue; } $calleeClass = $token[1]; if (isset($this->codeSummary[\'classes\'][$calleeClass])) { // find constructor method if (isset($this->codeSummary[\'classes\'][$calleeClass][\'methods\'][\'__construct\'])) { $calleeName = "$calleeClass::__construct" . $this->generateParametersForSignature($this->codeSummary[\'classes\'][$calleeClass][\'methods\'][\'__construct\'][\'params\']); } elseif (isset($this->codeSummary[\'classes\'][$calleeClass][\'methods\'][$calleeClass])) { $calleeName = "$calleeClass::$calleeClass" . $this->generateParametersForSignature($this->codeSummary[\'classes\'][$calleeClass][\'methods\'][$calleeClass][\'params\']); } else { $calleeName = "$calleeClass::__construct()"; } $calleeFile = $this->codeSummary[\'classes\'][$calleeClass][\'file\']; } else { // TODO: decide how this case should be handled (could be a PEAR class or a class of a PHP extension, e.g. GTK) //if ($this->showInternalFunctions) $calleeName = "$calleeClass::__construct()"; // TODO: it could also be $calleeClass::$calleeClass() implemented in PHP4-style, however if we don\'t have the code, we can\'t now $calleeFile = \'\'; } $this->info($this->getTokenValues($tokens, $i)); $this->recordVariableAsType($calleeClass, $tokens[$i-6][1]); } elseif ( ( isset($previousPreviousToken[1]) and $previousPreviousToken[1] == \'$this\' and $previousToken[0] == T_OBJECT_OPERATOR and in_array($token[1], $methodNames) ) or ( isset($previousPreviousToken[1]) and $previousPreviousToken[1] == \'self\' and $previousToken[0] == T_DOUBLE_COLON and in_array($token[1], $methodNames) ) ){ $this->info(\'internal method call ($this-> and self:: and $className::)\'); $calleeName = "$className::{$token[1]}" . $this->generateParametersForSignature($this->codeSummary[\'classes\'][$className][\'methods\'][$token[1]][\'params\']); $calleeFile = $file; } elseif ($previousToken[0] == T_OBJECT_OPERATOR) { $this->debug(\'External method call or property access\'); //TODO: what if a object holds another instance of its class if (!$this->showExternalCalls) { continue; } if ($nextToken == \'(\' or ($nextToken[0] == T_WHITESPACE and $tokenAfterNext == \'(\')) { $calleeName = $token[1]; $this->debug("Calling for $calleeName"); $variable = $tokens[$i-2][1]; $this->debug("Variable = $variable"); $calleeClass = $this->lookupTypeForVariable($variable); $this->debug(\'found as \' . $calleeClass); if ($calleeClass) { $calleeParams = $this->generateParametersForSignature( $this->codeSummary[\'classes\'][$calleeClass][\'methods\'][$calleeName][\'params\'] ); $calleeFile = $this->codeSummary[\'classes\'][$calleeClass][\'file\']; } else { if ( isset($this->methodLookupTable[$calleeName]) and count($this->methodLookupTable[$calleeName]) == 1 ) { // there is only one class having a method with this name // SMELL: but if the user only registers part of a system the only one hit // is not necessarily valid. $calleeClass = $this->methodLookupTable[$calleeName][0]; if (isset($this->codeSummary[\'classes\'][$calleeClass])) { $calleeParams = $this->generateParametersForSignature( $this->codeSummary[\'classes\'][$calleeClass][\'methods\'][$calleeName][\'params\'] ); $calleeFile = $this->codeSummary[\'classes\'][$calleeClass][\'file\']; $this->info("RECORDING CLASS OF $previousPreviousToken[1] VARIABLE to be $calleeClass\\n"); $this->info($this->getTokenValues($tokens, $i)); } else { $this-warning("calleeClass is unset"); $calleeParams = null; $calleeFile = null; } } else { $numEntries = count($this->methodLookupTable[$calleeName]); if ($numEntries == 0) { $this->warning("method $calleeName was called, but I have no record for that"); } else { $this->warning("I have $numEntries for $calleeName!"); } $this->info($this->getTokenValues($tokens, $i)); $calleeClass = \'\'; $calleeParams = \'()\'; $calleeFile = \'\'; } } $calleeName = "$calleeClass::$calleeName$calleeParams"; } else { $this->info("Property access"); continue; } } elseif ($previousToken[0] == T_DOUBLE_COLON){ $this->debug("static external method call"); if (!$this->showExternalCalls) { continue; } if ($nextToken != \'(\' and !($nextToken[0] == T_WHITESPACE and $tokenAfterNext == \'(\')) { // constant access continue; } $calleeClass = $previousPreviousToken[1]; $calleeMethod = $token[1]; $calleeFile = \'\'; $calleeParams = \'()\'; // parent:: if ($calleeClass == \'parent\' and !empty($this->codeSummary[\'classes\'][$className][\'parentClass\'])) { $calleeClass = $this->codeSummary[\'classes\'][$className][\'parentClass\']; } if (isset($this->codeSummary[\'classes\'][$calleeClass])) { $calleeFile = $this->codeSummary[\'classes\'][$calleeClass][\'file\']; if (isset($this->codeSummary[\'classes\'][$calleeClass][\'methods\'][$calleeMethod][\'params\'])) { $calleeParams = $this->generateParametersForSignature($this->codeSummary[\'classes\'][$calleeClass][\'methods\'][$calleeMethod][\'params\']); } } $calleeName = "$calleeClass::$calleeMethod$calleeParams"; //TODO: handle self::myMethod(); $className::myMethod(); here => abolish internal method call case } else { $calledFunction = $token[1]; $calleeFile = \'\'; $calleeParams = \'()\'; $this->info("Function call: ".$calledFunction); if (in_array($calledFunction, $this->internalFunctions)) { if (!$this->showInternalFunctions) { continue; } } else { if (!$this->showExternalCalls) { continue; } if (isset($this->codeSummary[\'functions\'][$calledFunction])) { $calleeFile = $this->codeSummary[\'functions\'][$calledFunction][\'file\']; if (isset($this->codeSummary[\'functions\'][$calledFunction][\'params\'])) { $calleeParams = $this->generateParametersForSignature($this->codeSummary[\'functions\'][$calledFunction][\'params\']); } } } $calleeName = $calledFunction . $calleeParams; } $this->debug("---> $calleeName called from line $lineNumber and defined in $calleeFile"); $this->driver->addCall($lineNumber, $calleeFile, $calleeName); } } } else { //TODO: parse calls inside double quoted strings $this->info(\' ignoring code inside ""\'); } } $this->debug(\'== endFunction ==\'); $this->driver->endFunction(); } } } public function generateParametersForSignature($parameters) { $result = \'(\'; if (!empty($parameters)) { foreach($parameters as $parameterName => $parameter) { if ($parameter[\'byReference\']) { $result.= \'&\'; } $result.= \'$\' . $parameterName . \', \'; } $result = substr($result, 0, -2); } $result.= \')\'; return $result; } } public function __toString() { return $this->driver->__toString(); } public function save($file) { return file_put_contents($file, $this->__toString()); } protected function getTokenValues($tokens, $i) { $width = 10; $pad = \' \'; $out = "\\n"; $start = -5; $end = 4; $headerLine = \'\'; $rowLine = \'\'; $tokenLine = \'\'; for ($j = $start; $j <= $end; $j++) { $n = ($i + $j); $currentToken = $tokens[$n]; $tokenType = \'\'; $cell = \'\'; $header = \'\'; if (is_array($currentToken)) { $mainValue = $currentToken[1]; $mainValue = str_replace("\\n", \'\\n\', $mainValue); $mainValue = str_replace("\\t", \'\\t\', $mainValue); if ($mainVlaue = \'\') { $mainValue = \'nil\'; } $cell = $mainValue; $tokenType = token_name($currentToken[0]); } else { $cell = \'"\'.$currentToken.\'"\'; } $cell = $cell; $cell = str_pad($cell, $width, $pad); $tokenType = str_pad(substr($tokenType,0,$width), $width, $pad); $header = \'[\'.$j.\']\'; $header = str_pad($header, $width, $pad); $headerLine .= $header.\' \'; $rowLine .= $cell.\' \'; $tokenLine .= $tokenType.\' \'; } $out .= $headerLine."\\n"; $out .= $rowLine."\\n"; $out .= $tokenLine."\\n"; return $out; } protected $variableTypes = array(); protected function recordVariableAsType($class, $variable) { $this->debug("RECORDING $variable AS TYPE $class"); $this->variableTypes[$variable] = $class; } /** * Returns a recorded type for a given variable, unless the variable is named \'$self\' * in which case returns the class name. * If no match is found returns null. */ protected function lookupTypeForVariable($variable) { $recordedType = $this->variableTypes[$variable]; if ($recordedType) { $type = $recordedType; } else { $this->warning("No recorded type for $variable"); $type = null; } $this->info(\'LOOKUP FOR \'.$variable.\' returns \'.$type); return $type; } } ?> <?php /** * Implementation of a call graph generation strategy wich renders a graph with * dot. * * PHP version 5 * * This file is part of phpCallGraph. * * PHPCallGraph is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * PHPCallGraph is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * @package PHPCallGraph * @author Falko Menge <fakko at users dot sourceforge dot net> * @copyright 2007-2009 Falko Menge * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License */ // reduce warnings because of PEAR dependency error_reporting(E_ALL ^ E_NOTICE); require_once \'CallgraphDriver.php\'; require_once \'Image/GraphViz.php\'; /** * Implementation of a call graph generation strategy wich renders a graph with * dot. */ class GraphVizDriver implements CallgraphDriver { protected $outputFormat; protected $dotCommand; protected $useColor = true; protected $graph; protected $currentCaller = \'\'; protected $internalFunctions; } /** * @return CallgraphDriver */ public function __construct($outputFormat = \'png\', $dotCommand = \'dot\') { $this->initializeNewGraph(); $this->setDotCommand($dotCommand); $this->setOutputFormat($outputFormat); $functions = get_defined_functions(); $this->internalFunctions = $functions[\'internal\']; } /** * @return void */ public function reset() { $this->initializeNewGraph(); } /** * @return void */ protected function initializeNewGraph() { $this->graph = new Image_GraphViz( true, array( \'fontname\' => \'Verdana\', \'fontsize\' => 12.0, //\'fontcolor\' => \'gray5\', \'rankdir\' => \'LR\', // left-to-right ) ); $this->graph->dotCommand = $this->dotCommand; } /** * Sets path to GraphViz/dot command * @param string $dotCommand Path to GraphViz/dot command * @return void */ public function setDotCommand($dotCommand = \'dot\') { $this->dotCommand = $dotCommand; $this->graph->dotCommand = $dotCommand; } /** * Sets output format * @param string $outputFormat One of the output formats supported by GraphViz/dot * @return void */ public function setOutputFormat($outputFormat = \'png\') { $this->outputFormat = $outputFormat; } /** * Enables or disables the use of color * @param boolean $boolean True if color should be used * @return void */ public function setUseColor($boolean = true) { $this->useColor = $boolean; } /** * @param integer $line * @param string $file * @param string $name * @return void */ public function startFunction($line, $file, $name, $memberCode) { $this->addNode($name); $this->currentCaller = $name; } /** * @param integer $line * @param string $file * @param string $name * @return void */ public function addCall($line, $file, $name) { $this->addNode($name); $this->graph->addEdge(array($this->currentCaller => $name)); } /** * @return void */ protected function addNode($name) { $nameParts = explode(\'::\', $name); $cluster = \'default\'; $label = $name; $color = \'lavender\'; //lightblue2, lightsteelblue2, azure2, slategray2 if (count($nameParts) == 2) { // method call if (empty($nameParts[0])) { $cluster = \'class is unknown\'; } else { $cluster = $nameParts[0]; } // obtain method name $label = $nameParts[1]; } // remove parameter list $label = substr($label, 0, strpos($label, \'(\')); if (count($nameParts) == 1) { // function call if (in_array($label, $this->internalFunctions)) { // call to internal function $cluster = \'internal PHP functions\'; } } $this->graph->addNode( $name, array( \'fontname\' => \'Verdana\', \'fontsize\' => 12.0, //\'fontcolor\' => \'gray5\', \'label\' => $label, //\'style\' => \'rounded\' . ($this->useColor ? \',filled\' : \'\'), // produces errors in rendering \'style\' => ($this->useColor ? \'filled\' : \'rounded\'), \'color\' => ($this->useColor ? $color : \'black\'), \'shape\' => ($this->useColor ? \'ellipse\' : \'rectangle\'), ), $cluster ); //* $this->graph->addCluster( $cluster, $cluster, array( // \'style\' => ($this->useColor ? \'filled\' : \'\'), \'color\' => \'gray20\', // \'bgcolor\' => \'\', ) ); //*/ } /** * @return void */ public function endFunction() { } /** * @return string */ public function __toString() { return $this->graph->fetch($this->outputFormat); } } ?> ' # Print the match result str.scan(re) do |match| puts match.to_s end

Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for Ruby, please visit: http://ruby-doc.org/core-2.2.0/Regexp.html