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

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

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 Java, please visit: https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html