Получение функции Содержимое и имя функции в C с регулярным выражением в python - PullRequest
4 голосов
/ 08 июня 2019

Я пытаюсь получить содержимое функции (тело), ​​если имя функции соответствует определенному шаблону

что я пробовал до сих пор:

(Step1) получить с рекурсией все тела функций в файле определения C {(?:? [^ {}] + | (R)) * +}

(Step2) найти все совпадения с именем требуемой функции

(Шаг 3) Объедините оба шага. Вот где я борюсь

Input

TASK(arg1)
{
    if (cond)
    {
      /* Comment */
      function_call();
      if(condIsTrue)
      {
         DoSomethingelse();
      }
    }
    if (cond1)
    {
      /* Comment */
      function_call1();
    }
}


void FunctionIDoNotWant(void)
{
    if (cond)
    {
      /* Comment */
      function_call();
    }
    if (cond1)
    {
      /* Comment */
      function_call1();
    }
}

Я ищу функцию ЗАДАЧА. Когда я добавляю регулярное выражение в соответствие с ЗАДАНИЕМ перед "{(?: [^ {}] + | (? R)) * +}", ничего не работает.

(TASK\s*\(.*?\)\s)({((?>[^{}]+|(?R))*)})

Желаемый выход

Group1:
   TASK(arg1)
Group2:
    if (cond)
    {
      /* Comment */
      function_call();
      if(condIsTrue)
      {
         DoSomethingelse();
      }
    }
    if (cond1)
    {
      /* Comment */
      function_call1();
    }

Ответы [ 3 ]

1 голос
/ 08 июня 2019

Вы повторяете весь шаблон с (?R), что аналогично (?0), тогда как вы хотите recurse (?2), вторая группа . Первая группа содержит ваш (TASK ... )

См. Эту демонстрацию на regex101

(TASK\s*\(.*?\)\s)({((?>[^{}]+|(?2))*)})
                  ^ here starts the second group -> recursion with (?2)
0 голосов
/ 08 июня 2019

Это невозможно сделать с помощью одного регулярного выражения - регулярное выражение не может считать открытые (и закрытые) скобки ({}).По крайней мере, без некоторых странных расширений.

Попробуйте этот код (при условии, что start - это первый символ после искомого заголовка функции):

i = start + 1
c = 1
r = re.compile('[{]|[}]')
while c > 0:
    m = r.search(test_str, i)
    if not m:
        break
    if m.group(0) == '{':
        c += 1
    else:
        c -= 1
    i = m.end(0) + 1
if c == 0:
    print(test_str[start:i])

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

0 голосов
/ 08 июня 2019

Эта проблема немного сложна, может зависеть от наших входных данных и может быть решена частично с помощью регулярных выражений и частично с помощью сценариев, например, мы будем начинать с выражения, которое проходит через новые строки, такие как:

(TASK.+)\s*({[\s\S]*})\s*void
(TASK.+)\s*({[\w\W]*})\s*void
(TASK.+)\s*({[\d\D]*})\s*void

здесь у нас есть начальная граница, которая является нашим первым желаемым выводом:

(TASK.+)

и левая и правая границы вокруг нашего второго желаемого результата:

\s*({[\s\S]*})\s*void

и правая граница, скорее всего, изменится:

\s*void

Демо

RegEx

Если это выражение не нужно и вы хотите изменить его, перейдите по этой ссылке на regex101.com .

RegEx Circuit

jex.im визуализирует регулярные выражения:

enter image description here

Test

# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility

import re

regex = r"(TASK.+)\s*({[\s\S]*})\s*void"

test_str = ("TASK(arg1)\n"
    "{\n"
    "    if (cond)\n"
    "    {\n"
    "      /* Comment */\n"
    "      function_call();\n"
    "      if(condIsTrue)\n"
    "      {\n"
    "         DoSomethingelse();\n"
    "      }\n"
    "    }\n"
    "    if (cond1)\n"
    "    {\n"
    "      /* Comment */\n"
    "      function_call1();\n"
    "    }\n"
    "}\n\n\n"
    "void FunctionIDoNotWant(void)\n"
    "{\n"
    "    if (cond)\n"
    "    {\n"
    "      /* Comment */\n"
    "      function_call();\n"
    "    }\n"
    "    if (cond1)\n"
    "    {\n"
    "      /* Comment */\n"
    "      function_call1();\n"
    "    }\n"
    "}")

matches = re.finditer(regex, test_str, re.MULTILINE)

for matchNum, match in enumerate(matches, start=1):

    print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))

    for groupNum in range(0, len(match.groups())):
        groupNum = groupNum + 1

        print ("Group {groupNum} found at {start}-{end}: {group}".format(groupNum = groupNum, start = match.start(groupNum), end = match.end(groupNum), group = match.group(groupNum)))

# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.
...