使用 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++ 中的多行注释的主要内容,如果未能解决你的问题,请参考以下文章