使用 RegEx 去除 C++ 中的多行注释

Posted

技术标签:

【中文标题】使用 RegEx 去除 C++ 中的多行注释【英文标题】:Stripping multiline comments in C++ with RegEx 【发布时间】:2012-02-11 18:31:39 【问题描述】:

假设我有一个 var std::string sourceCode; 我在其中加载了一个 cpp 源文件。现在我想从 tr1 中删除所有包含正则表达式类的 cmets(现在它们完全包含在内,因为我使用 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

我确实想激起 cmets 讨论使用 RegEx 来做这种事情是否有意义!请假设输入是干净且符合预期的。

【问题讨论】:

这并不像你想象的那么容易。考虑来源string s = "not // a /* comment ..."; 这是一个非常大胆的假设,考虑到您在问题中发布的代码会破坏您的正则表达式。 您可能需要执行一些翻译阶段。行延续在大多数其他内容甚至被 lexed 之前执行:codepad.org/LbarZgMg 【参考方案1】:

您使用正则表达式的方法太离谱而且太复杂了。您正在尝试使用常规语言 (regex) 来解析至少与上下文无关语法一样复杂的情况。如果你把事情分开并在 C++ 中进行部分处理,你会完成它,但它会看起来很乱。

如果您的目标是编写一个在不丢失换行符的情况下剥离所有 cmets 的函数,我建议您使用众多可用的解析工具之一生成解析。

这需要不到 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 

将生成新的源文件。

【讨论】:

【参考方案2】:

最好的方法是使用两个正则表达式。第一个将删除所有单行 cmets(这些不会影响行号)。

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

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

【讨论】:

以上是关于使用 RegEx 去除 C++ 中的多行注释的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式去除 phpdoc 多行注释

使用VSCode去除代码中注释

Python中的多行注释[重复]

vim中多行注释和多行删除命令

linux多行注释

lua注释