Сопоставить тело функции с помощью Regex

Дана фиктивная функция как таковая:

public function handle()
{
if (isset($input['data']) {
switch($data) {
...
}
} else {
switch($data) {
...
}
}
}

Мое намерение состоит в том, чтобы получить содержимое этой функции, проблема заключается в сопоставлении вложенных шаблонов фигурных скобок {...},

Я сталкивался рекурсивные паттерны но я не мог разобраться с регулярным выражением, которое соответствовало бы телу функции.

Я пробовал следующее (без рекурсии):

$pattern = "/function\shandle\([a-zA-Z0-9_\$\s,]+\)?". // match "function handle(...)"'[\n\s]?[\t\s]*'. // regardless of the indentation preceding the {
'{([^{}]*)}/'; // find everything within braces.

preg_match($pattern, $contents, $match);

Этот шаблон не соответствует вообще. Я уверен, что это последний бит, который не так '{([^{}]*)}/' поскольку этот шаблон работает, когда в теле нет других фигурных скобок.

Заменив его на:

'{([^}]*)}/';

Это соответствует до закрытия } переключателя внутри if Заявление и остановился там (в том числе } выключателя, но исключая тот из if).

Как и этот шаблон, тот же результат:

'{(\K[^}]*(?=)})/m';

3

Решение

Обновление № 2

Согласно другим комментариям

^\s*[\w\s]+\(.*\)\s*\K({((?>"(?:[^"\\]*+|\\.)*"|'(?:[^'\\]*+|\\.)*'|//.*$|/\*[\s\S]*?\*/|#.*$|<<<\s*["']?(\w+)["']?[^;]+\3;$|[^{}<'"/#]++|[^{}]++|(?1))*)})

Примечание: короткий RegEx, т.е. {((?>[^{}]++|(?R))*)} достаточно, если вы знаете, что ваш ввод не содержит { или же } вне синтаксиса PHP.

Так долго RegEx, в чем злой случаи это работает?

  1. У тебя есть [{}] в строке между кавычками ["']
  2. У вас эти кавычки экранированы друг от друга
  3. У тебя есть [{}] в блоке комментариев. //... или же /*...*/ или же #...
  4. У тебя есть [{}] в наследство или в настоящее время <<<STR или же <<<['"]STR['"]

В противном случае предполагается наличие пары открывающих / закрывающих скобок, а глубина вложенных скобок не важна.

У нас есть дело, что оно терпит неудачу?

Нет, если у вас нет марсианина, который живет внутри ваших кодов.

 ^ \s* [\w\s]+ \( .* \) \s* \K               # how it matches a function definition
(                             # (1 start)
{                                      # opening brace
(                             # (2 start)
(?>                               # atomic grouping (for its non-capturing purpose only)
"(?: [^"\\]*+ | \\ . )*"     # double quoted strings
|  '(?: [^'\\]*+ | \\ . )*'     # single quoted strings
|  // .* $                      # a comment block starting with //
|  /\* [\s\S]*? \*/             # a multi line comment block /*...*/
|  \# .* $                      # a single line comment block starting with #...
|  <<< \s* ["']?                # heredocs and nowdocs
( \w+ )                      # (3) ^
["']? [^;]+ \3 ; $           # ^
|  [^{}<'"/#]++                 # force engine to backtack if it encounters special characters [<'"/#] (possessive)
|  [^{}]++                      # default matching bahaviour (possessive)
|  (?1)                         # recurse 1st capturing group
)*                                # zero to many times of atomic group
)                             # (2 end)
}                                      # closing brace
)                             # (1 end)

Форматирование выполняется @ sln’s RegexFormatter программного обеспечения.

Что я предоставил в живом демо?

Красноречивый Ларавель Model.php Файл (~ 3500 строк) случайным образом задается в качестве входных данных. Проверьте это:
Живая демо

7

Другие решения

Это работает для вывода файла заголовка (.h) из встроенных функциональных блоков (.c)

Найти регулярное выражение:

(void\s[^{};]*)\n^\{($[^}$]*)\}$

Заменить:

$1;

Для ввода:

void bar(int var)
{
foo(var);
foo2();
}

будет выводить:

void bar(int var);

Получите тело функционального блока со вторым сопоставленным шаблоном:

$2

будет выводить:

    foo(var);
foo2();
0

По вопросам рекламы [email protected]