Регулярное выражение для захвата символов директивы препроцессора в исходном коде C# - PullRequest
1 голос
/ 17 июня 2020

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

...

#define SYMBOL_1                                          // Match 1, 1 group

#undef   SYMBOL_2                                         // Match 2, 1 group

#pragma warning disable 649

// #undef NO_MATCH

// #undef !NO_MATCH

#if(SYMBOL_3 && SYMBOL_4)                                 // Match 3, 2 groups

#if SYMBOL_3 && SYMBOL_4                                  // Match 4, 2 groups

#elif SYMBOL_3                                            // Match 5, 1 group

#elif   !SYMBOL_3                                         // Match 6, 1 group

   #if (SYMBOL_1 && SYMBOL_2) || !SYMBOL_3 || SYMBOL_4    // Match 7, 4 groups

   #elif SYMBOL_1                                         // Match 8, 1 group

   #elif    !SYMBOL_2                                     // Match 9, 1 group

   #if (SYMBOL_1&&SYMBOL_2) || !SYMBOL_3// || NO_MATCH    // Match 10, 3 groups

   #if (SYMBOL_1&&!SYMBOL_2) || !SYMBOL_3 //|| NO_MATCH   // Match 11, 3 groups

...

Я пробовал ряд вещей, но я ' м не совсем там. Следующее выражение фиксирует первый символ в каждой совпадающей строке (включены глобальные и многострочные параметры):

^[\t ]*#(?>if|elif|define|undef)(?> |\t|\(|\)|!|&|\|)*(\w*)

Где:

  • ^[\t ]*#(?>if|elif|define|undef) определяет строки, начинающиеся с #define, #undef, #if и #elif, которые не закомментированы. Предшествующие пробелы и все другие директивы препроцессора, такие как #pragma, игнорируются.
  • (?: |\t|\(|\)|!|&|\|)* не захватывает, но разрешает определенные символы (space, tab, (, ) , !, & и |) перед символом.
  • и, наконец, (\w*) захватывает символ как группу. Все символы "SYMBOL_ #" захватываются, а символы "NO_MATCH" не связаны с предшествующими знаками комментария.

regex101 fiddle

Текущие результаты:

  • Соответствие 1> Группа 1: "SYMBOL_1"
  • Соответствие 2> Группа 1: "SYMBOL_2"
  • Соответствие 3> Группа 1: "SYMBOL_3", но есть нет Группа 2, содержащая "SYMBOL_4".
  • ... и так далее ...

Соответствия 3, 4, 7, 10 и 11 должны иметь несколько групп.

Осталось только повторить вторую (не захватывающую) и третью (захватывающую) части выражения до конца строки. Вот на чем я застрял. В настоящее время выполнено 11 совпадений, но захвачено только 11 групп. Групп должно быть 20.

Я пробовал просто дублировать эти части несколько раз, и это работает, но в результате получается очень длинное выражение и много пустых групп совпадений.

Например , ^[\t ]*#(?>if|elif|define|undef)(?> |\t|\(|\)|!|&|\|)*(\w*)(?> |\t|\(|\)|!|&|\|)*(\w*)(?> |\t|\(|\)|!|&|\|)*(\w*)(?> |\t|\(|\)|!|&|\|)*(\w*)(?> |\t|\(|\)|!|&|\|)*(\w*)(?> |\t|\(|\)|!|&|\|)*(\w*) захватывает до шести символов за одно совпадение, однако большинство групп пусты, поскольку в каждой строке есть только один символ. Кроме того, в данной строке может быть более шести символов, и я хотел бы захватить их все.

Есть ли более чистый способ повторить (?> |\t|\(|\)|!|&|\|)*(\w*) до конца строки, чтобы он захватывает все символы?

Я пробовал вложить эти части выражения в другую группу, чтобы можно было применить «множественный» квантификатор, но это, похоже, не помогло. Вероятно, мне что-то не хватает.

Это вопрос с регулярным выражением, но я добавил тег C#, поскольку я использую регулярное выражение в коде C#, а другие языки могут использовать другой синтаксис препроцессора, например видно здесь: Извлечение символов препроцессора из исходного кода (C / C ++)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...