使用RegEx在C ++中剥离多行注释

时间:2012-01-16 21:20:04

标签: c++ regex comments c++11

假设我有一个var 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

NOT 想要引发关于讨论的评论是否有意义使用RegEx进行此类操作!请假设输入是干净的并且符合预期。

2 个答案:

答案 0 :(得分:4)

使用正则表达式的方法很简单,太复杂了。您正在尝试使用常规语言(正则表达式)来解析至少与无上下文语法一样复杂的情况。如果你拆分并用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 

将生成新的源文件。

答案 1 :(得分:0)

最好的方法是使用两个regexen。第一个将删除所有单行注释(这些不会影响行号)。

然后,使用另一个正则表达式删除多行注释,并循环遍历每个注释,直到不再有:

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');
}