2012-01-16 3 views
0

cpp 소스 파일을로드 한 곳의 행이 std::string sourceCode; 인 것으로 가정합니다. 이제 tr1에서 포함 된 정규식 클래스를 사용하여 모든 주석을 제거하려고합니다 (이제 Microsoft 컴파일러를 사용할 때 완전히 포함되었습니다). 단일 줄은 쉽지만 여러 줄이 아닙니다. 단지 공백으로 주석을 바꾸는 것이 아니라 정확한 줄 수를 유지하는 것입니다. 우리는 5 줄의 주석을 제거한다고 가정하고,이 줄은 5 줄의 줄 바꿈으로 채워 져야하므로 코드를 역 추적하고 올바른 줄 번호로 계산할 수 있습니다. 지금까지RegEx를 사용하여 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

내가이 일을 이런 종류의 정규식을 사용하는 의미가 있는지 토론에 대한 의견을 자극 할 NOT을! 입력이 깨끗하고 예상대로라고 가정하십시오.

+9

그것은 당신이 생각하는 것처럼 쉬운 일이 아닙니다 : 더 이상 없을 때까지

그런 다음 각 개 이상의 다른 여러 줄 주석을 제거하기위한 정규식 및 루프를 사용하지 않습니다. 소스'string s = "가 아닌 // a/* comment ..."; ' –

+5

당신이 질문에 게시 한 코드가 정규 표현식을 깨뜨릴 것이라는 것을 고려하면 꽤 대담한 가정입니다. – Gerald

+1

번역의 단계를 수행해야 할 수도 있습니다. 행의 연속은 대부분의 다른 것들이 렉스되기 전에 수행됩니다 : http://codepad.org/LbarZgMg –

답변

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

최상의 방법은 두 개의 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'); 
}