2012-01-16 136 views
0

假設我有一個var std::string sourceCode;,我已經加載了一個cpp源文件。現在我想從tr1中刪除包含正則表達式類的所有註釋(現在它們完全包含在我使用的Microsoft編譯器中) - 單行很容易,但是多行不行。這不是僅僅用一個空格替換一個評論,而是要保持正確的行數。假設我們刪除了5行的註釋,那麼這個空間應該填充5個換行符,以便我能夠回溯代碼並使用正確的行號進行計算。用正則表達式剝離C++中的多行註釋

我迄今爲止代碼:

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

我做想挑起有關討論意見是否有意義使用正則表達式這種做的!請簡單地假設輸入是乾淨的並且如預期的那樣。

+9

它並不像想象中那麼簡單。考慮源'string s =「not // a/* comment ...」;' – 2012-01-16 21:22:11

+5

這是一個非常大膽的假設,考慮到您在問題中發佈的代碼會破壞您的正則表達式。 – Gerald 2012-01-16 21:30:11

+1

您可能需要執行一些翻譯階段。在大多數其他任何事情都是lexed之前執行行延續:http://codepad.org/LbarZgMg – 2012-01-16 21:46:26

回答

4

你使用正則表達式的方法是太多了,太複雜了。您正在嘗試使用常規語言(正則表達式)來解析至少與上下文無關語法一樣複雜的情況。如果你分裂了一些東西並用C++進行部分處理,你會完成它,但看起來很亂。

如果你的目標是編寫一個函數去掉所有的註釋而不會丟失新的行字符,我建議你使用其中一個可用的解析工具生成一個解析。

這花了不到5分鐘的時間來創建,功能上是你要找的。你可以修改這個到你的心中。這將產生具有柔性2.5.4詞法分析器或撓曲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

最好的方法是使用兩個正則表達式。第一個將刪除所有單行註釋(這些不會影響行號)。

然後,使用在各自相互正則表達式去除多行註釋,並循環,直到沒有更多:

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