Использование C# и регулярного выражения для анализа исходного кода и поиска вызовов функций с аргументами

У меня есть список вызовов функций, хранящихся в базе данных, и для некоторых вызовов функций меня интересуют аргументы вызова функции. Я анализирую исходный код C с помощью своей программы (которая находится на C#). Я пытаюсь найти лучший способ получить вызовы функций с аргументами. Я считываю исходный код в строку перед ее синтаксическим анализом (так что я не использую средство чтения потока для файла). Я попытался использовать какое-то регулярное выражение (которое для меня несколько в новинку) для анализа исходного файла, но при использовании такой строки регулярного выражения получал больше, чем просто вызов функции: functionCall + ". * \\)"; (Я избегаю открытия (в вызове функции)

Вызов функций хранится в БД в следующем формате:

Function Call
============
some_Call(

Есть причина, по которой они хранятся таким образом и не изменятся.

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

Сообщите мне, если необходимы какие-либо разъяснения.

Ответов (3)

Решение

Одна из причин, по которой ваше решение не удалось, заключается в том, что вам, вероятно, следовало использовать .*?) вместо жадного сопоставления.

Полный ответ должен следовать, по крайней мере, следующим образом:

Игнорировать круглые скобки в строках и символах (что вы можете сделать с регулярным выражением, хотя с экранированием это может быть немного сложно)

functionCall("\")", ')')

Игнорировать круглые скобки в комментариях (что можно сделать с регулярным выражением)

functionCall(/*)*/ 1, // )
2)

Не сопоставляйте слишком много (что можно сделать с помощью регулярного выражения)

functionCall(1) + functionCall(2) + (2 * 3) // Don't match past the first )

но также придется игнорировать сбалансированные круглые скобки

functionCall((1+(1))*(2+2))

Последнее - то, что вы не можете сделать с обычным регулярным выражением, потому что оно включает подсчет скобок и, как правило, это то, для чего регулярные выражения не подходят. Однако похоже, что в .NET есть способы сделать это .

(И технически вам придется обрабатывать макросы, я могу представить

#define close_paren )

испортит тебе день ...)

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

Не для того, чтобы вас испортить, но ... в C я верю (смутно), что вы можете сделать это:

void secondFunction() { /* no-op */ }

void firstFunction()
{
    void* xyz = secondFunction;

    xyz(); // this should call secondFunction
}

Это возможный сценарий? А как же другие варианты использования указателя?!?

Скажем, литье типа в функциональном стиле?!?

int a;
float b = float(a); // call to the "float" function?!? NO! it's a type casting

Использовать список предопределенных типов? Что, если преобразование было в пользовательские структуры, а что насчет определений типов? Теперь вам тоже нужно разобрать их!

Серьезно, воспользуйтесь парсером !! Уже есть несколько доступных опций, которые могут анализировать C.

Я думаю, что Regex - довольно плохой инструмент для работы.

Я написал быстрое регулярное выражение и протестировал его, проверьте следующее:

            string tst = "some_function(type<whatever> tesxt_112,type<whatever> tesxt_113){";

        Regex r = new Regex(".*\\((.*)\\)");
        Match m = r.Match(tst);
        if (m.Success)
        {
            string[] arguments = m.Groups[1].Value.Split(',');
            for (int i = 0; i < arguments.Length; i++)
            {
                Console.WriteLine("Argument " + (i + 1) + " = " + arguments[i]);
            }
        }

        Console.ReadKey();

Таким образом, вывод для указанной выше строки будет:

Аргумент 1 = тип <whatever> tesxt_112

Аргумент 2 = тип <что угодно> tesxt_113

Надеюсь это поможет:

Эндрю :-)