Удаление многострочных комментариев в C ++ с помощью RegEx - PullRequest
0 голосов
/ 17 января 2012

Предположим, у меня есть переменная std::string sourceCode;, в которую я загрузил исходный файл cpp. Теперь я хочу удалить все комментарии с включенными классами регулярных выражений из tr1 (теперь они полностью включены, поскольку я использую компилятор Microsoft) - однострочные - это легко, а многострочные - нет. Речь идет не просто о замене комментария пробелом и т. Д. Речь идет о сохранении правильного количества строк. Предположим, мы удалили комментарий длиной 5 строк, затем это место должно быть заполнено 5 новыми строками, чтобы я мог отследить код и вычислить с правильными номерами строк.

Пока мой код:

std::regex singleLinedCommentReg("//.*");
sourceCode = std::regex_replace(sourceCode, singleLinedCommentReg, std::string(""));
std::regex multiLinedCommentReg("(/\\*([^*]|[\r\n]|(\\*+([^*/]|[\r\n])))*\\*+/)");
std::for_each(
    std::sregex_iterator(sourceCode.begin(), sourceCode.end(), multiLinedCommentReg),
    std::sregex_iterator(),
    [&](const std::match_results<std::string::const_iterator>& match) -> bool {
        // TODO: Replace the current match with an appropriate number of newlines.
        return true;
    }
);

Может кто-нибудь дать мне совет по этому поводу?

РЕДАКТИРОВАТЬ # 1

Я НЕ хочу спровоцировать комментарии о дискуссии, имеет ли смысл использовать RegEx для такого рода действий! Пожалуйста, просто примите во внимание, что ввод чистый и как ожидалось.

Ответы [ 2 ]

4 голосов
/ 17 января 2012

Ваш подход с использованием регулярных выражений слишком сложный и сложный. Вы пытаетесь использовать обычный язык (регулярные выражения) для анализа ситуации, которая по меньшей мере столь же сложна, как и контекстно-свободная грамматика. Если вы разделите вещи и сделаете часть обработки в C ++, вы это сделаете, но это будет выглядеть грязно.

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

Это заняло менее 5 минут, чтобы создать и функционально то, что вы ищете. Вы можете изменить это по своему усмотрению. Он сгенерирует лексер с flex 2.5.4 или flex 2.5.35

%{
    #include <stdio.h>
%}


cbeg    "/*"
cend    "*/"
cppc    "//"
nl  "\n"|"\r\n"

%option noyywrap
%x mlc 
%%
{nl}        { fputs(yytext, stdout); }
{cbeg}      { BEGIN(mlc); }
{cend}      { fprintf(stderr, "Error: found end of comment without a beginning\n"); return -1; }
{cppc}.*    /* eat up the comment */
.       { fputs(yytext, stdout); }

<mlc>{cend} { BEGIN(INITIAL); }
<mlc>{cbeg}     { fprintf(stderr, "Error: Found /* inside another /* comment"); return -1; }
<mlc>.      /* eat up everything else */

%%

int main(int argc, char* argv[])
{
        yylex();
}

Добавление:

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

flex -t foo.l > foo.c

и вы можете скомпилировать его, используя

cc -o foo foo.c

Теперь что-то вроде

./foo < source.c > source-sans-comments.c 

создаст новый исходный файл.

0 голосов
/ 17 января 2012

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

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

regex mlc("\\/\\*[^(\\/\\*)]*?\\*\\/");

string data = something;

match_results<std::string::const_iterator> searchresult;

while (regex_search(data, searchresult, mlc)) {
    const string& match = searchresult.str();

    auto newlinecount = std::count(match.begin(), match.end(), '\n');

    data.replace(searchresult.position(), match.length(), newlinecount, '\n');
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...