Сопоставить тело функции с помощью 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';
 TemporalWolf30 июн. 2016 г., 01:13
@MagnusEriksson В базовом случае, однако, вы можете, если знаете, какой будет ваш вклад. В любом случае, я ошибся -> php поддерживает рекурсивные регулярные выражения ... так что не все так ужасно, как доказывает ответ revo.
 Magnus Eriksson30 июн. 2016 г., 01:18
@TemporalWolf - его ответ легко терпит неудачу (как я прокомментировал). Если вы знаете, какой будет ввод, зачем тогда вообще его анализировать? Тогда просто жесткий код это?
 Magnus Eriksson30 июн. 2016 г., 01:20
@TemporalWolf - в любом случае. Это обсуждение является спорным, так как ФП не предоставила нам обратную связь по нашим первоначальным вопросам. Мы все просто принимаем вещи, на данный момент.
 SamWhan30 июн. 2016 г., 11:17
 TemporalWolf30 июн. 2016 г., 01:04
@MagnusEriksson Выполнимо, просто требуется еще больше регулярных выражений. Как я уже сказал, это, вероятно, не правильный инструмент для работы. То, что он ищет, этоpushdown automaton что регулярное выражение не может сделать. Он может подделать его для достаточно простых задач, но в конечном итоге регулярное выражение будет бесконечно длинным, чтобы охватить все случаи.
 user55784630 июн. 2016 г., 00:08
в каком юниверсе нужно извлечь содержимое функции с помощью регулярного выражения (или любым другим способом)
 Mulkave30 июн. 2016 г., 10:20
@TemporalWolf нет ограничений на количество вложенных уровней в теле, в какие секунды вы говорите. Я хотел бы узнать больше оpushdown automaton и как он может решить такую ​​проблему, никогда раньше не слышал об этом термине (обязательно проведу некоторое исследование, но также оценим ваши знания по этому вопросу).
 Magnus Eriksson30 июн. 2016 г., 00:46
@TemporalWolf - Не забывайте, что вам также нужно учитывать и игнорировать любые фигурные скобки, которые заключены в одинарные / двойные кавычки, heredoc и т. Д ...
 Jan30 июн. 2016 г., 00:30
В самом деле, попробуйте ответить на вопрос @ Дагона здесь - какова ваша цель?
 Mulkave30 июн. 2016 г., 10:17
@MagnusEriksson Спасибо за то, что указали, что это не правильный подход к решению, одна из главных причин, почему я разместил этот вопрос. Мое намерение состоит в том, чтобы прочитать содержимое тела функции и отобразить его как есть (строка), ничего кроме этого. Дагон, это отвечает на твой вопрос?
 Magnus Eriksson30 июн. 2016 г., 01:10
@TemporalWolf - я согласен, что регулярное выражение не является правильным инструментом для этого. Я бы на самом деле утверждал, что вы не можете сделать это на 100% безопасным (от ошибок) с помощью регулярных выражений. Учтите, что вам также нужно игнорировать одинарные кавычки внутри двойных кавычек (чтобы он не думал, что вы все еще в кавычках, когда вы не т. Д.), Экранированные кавычки внутри кавычек и так далее. Вы наверняка всегда будете пропускать несколько разных комбинаций.
 Magnus Eriksson30 июн. 2016 г., 00:20
Я бы переосмыслил то, что я делаю, если бы я был тобой. Проблема здесь заключается в том, что если вы не знаете, что может содержать тело функции, регулярное выражение должно быть чудовищным, не поддерживаемым и склонным к 100000 ошибок. Представьте, что у вас есть строка, содержащая{ или же} (без соответствующей начальной или конечной скобки), тогда ваш рекурсивный шаблон не будет работать. И это только первая ситуация, о которой я подумал.
 TemporalWolf30 июн. 2016 г., 00:41
Это не то, что регулярное выражение хорошо подходит для: я могу сделать один, но в конечном счете, чем глубже вы хотите, чтобы это соответствовало, тем дольше регулярное выражение. Для каждого уровня вам нужна отдельная группировка, если вы хотите иметь возможность их сопоставлять: регулярное выражение, поддерживающее до 4 вложенных{{{{}}}} сломается на{{{{{}}}}} вложение 5.

Ответы на вопрос(2)

ных блоков (.c)

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

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

Заменить:

$1;

Для ввода:

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

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

void bar(int var);

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

$2

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

    foo(var);
    foo2();
Решение Вопроса
Обновление № 2

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

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

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

Так долго RegEx, в чемзлой случаи это работает?У тебя есть[{}] в строке между кавычками["']У вас есть эти кавычки внутри друг другаУ тебя есть[{}] в блоке комментариев.//... или же/*...*/ или же#...У тебя есть[{}] в наследство или в настоящее время<<<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'sRegexFormatter программного обеспечения.

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

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

 TemporalWolf30 июн. 2016 г., 18:24
За проголосовали - В нашем проекте, который использует SquishAPI (и, следовательно, сильно зависит от"{...}" строки для идентификации объектов), у нас есть только 63 вхождения в 80kLOC{/} внутри строк ... Я думаю, что это будет работать денди в большинстве случаев.
 Mulkave30 июн. 2016 г., 11:45
@revo впечатляет! Спасибо за это решение, оно сработало.
 Magnus Eriksson30 июн. 2016 г., 01:14
Сбой, если этоучебный класс или если у нас естьстрока со скобой
 revo30 июн. 2016 г., 10:31
Тоже подумай, я никогда не говорилТолько RegEx и я никогда этого не скажу. Если у вас есть инструмент, который выполнил большую часть тяжелых и неприятных заданий в фоновом режиме, не стесняйтесь показать его OP. И ... не голосуйте за комментарии друг друга тоже. Подтверждение друг друга не помогает. @MagnusEriksson
 revo30 июн. 2016 г., 10:30
Вы не должны говорить об этом парню из RegEx, так как он это хорошо знает. Регулярные выражения какмощная обработка текста Это не простая утилита для выполнения только дешевых работ, ее цель - идеально выполнять тяжелые текстовые операции. Если бы в этом не было необходимости, мы бы придерживались подстановочных знаков UNIX и простых шаблонов файлов. Кстати, я ничего не исправляю, этого короткого RegEx сначала было достаточно для того, чего хочет OP. Но пока кто-то вроде тебя пытается показать мне, что может быть не так, я буду исправлять ошибки. @MagnusEriksson
 Magnus Eriksson30 июн. 2016 г., 08:27
Опять же, регулярное выражение - неправильный инструмент, и, как я и @Dagon уже сказал, этого нельзя сделать с помощью регулярного выражения, поскольку вы не сможете учесть все ситуации и варианты. В основном вы проведете остаток своей жизни, исправляя регулярное выражение. Строки - это всего лишь одна ситуация ... тогда есть комментарии, с которыми вам нужно разобраться, и так далее ...

Ваш ответ на вопрос