Как убрать однострочные комментарии в стиле C ++ (`// ...`) - PullRequest
1 голос
/ 13 сентября 2011

Для небольшого DSL, который я пишу, я ищу регулярное выражение, совпадающее с строкой комментария в конце, например, синтаксис // C ++.Простой случай:

someVariable = 12345; // assignment

Тривиально для сопоставления, но проблема начинается, когда у меня есть строка в той же строке:

someFunctionCall("Hello // world"); // call with a string

// в строке не должно совпадатькак комментарий


РЕДАКТИРОВАТЬ - То, что компилирует DSL, не мое.Это черный ящик, который я не хочу менять, и он не поддерживает комментарии.Я просто хочу добавить тонкую оболочку, чтобы она поддерживала комментарии.

Ответы [ 2 ]

2 голосов
/ 13 сентября 2011

шош написал:

РЕДАКТИРОВАТЬ - То, что компилирует DSL, не мое. Это черный ящик, который я не хочу менять, и он не поддерживает комментарии. Я просто хочу добавить тонкую оболочку, чтобы она поддерживала комментарии.

В этом случае создайте очень простой лексер, который соответствует одному из трех токенов:

  1. // ... комментарии
  2. строковые литералы: " ... "
  3. или, если ни один из приведенных выше совпадений, не соответствует ни одному символу

Теперь, пока вы повторяете эти 3 различных типа токенов, просто выведите токены (2) и (3) на стандартный вывод (или в файл), чтобы получить некомментированную версию вашего исходного файла.

Демонстрация с GNU Flex:

пример входного файла, in.txt :

someVariable = 12345; // assignment
// only a comment
someFunctionCall("Hello // world"); // call with a string
someOtherFunctionCall("Hello // \" world"); // call with a string and 
                                            // an escaped quote

Файл грамматики лексера, demo.l :

%%
"//"[^\r\n]*             { /* skip comments */ }
"\""([^"]|[\\].)*"\""    {printf("%s", yytext);}
.                        {printf("%s", yytext);}
%%
int main(int argc, char **argv)
{
    while(yylex() != 0);
    return 0;
}

И чтобы запустить демо, сделайте:

flex demo.l 
cc lex.yy.c -lfl
./a.out < in.txt

, который выведет на консоль следующее:

someVariable = 12345; 

someFunctionCall("Hello // world"); 
someOtherFunctionCall("Hello // \" world"); 

EDIT

Я не очень знаком с C / C ++ и просто видел рекомендацию @ sehe об использовании препроцессора. Это выглядит намного лучше, чем создание собственного (маленького) лексера. Но я думаю, что я оставлю этот ответ, так как он показывает, как обрабатывать такие вещи, если нет препроцессора (по какой-то причине: возможно cpp не распознает определенные части DSL?).

2 голосов
/ 13 сентября 2011

РЕДАКТИРОВАТЬ

Поскольку вы эффективно обрабатываете исходный файл, почему бы вам не использовать существующий препроцессор?Если язык достаточно похож на C / C ++ (особенно в отношении кавычек и строковых литералов), вы сможете просто использовать cpp -P:

 echo 'int main() { char* sz="Hello//world"; /*profit*/ } // comment' | cpp -P

Вывод: int main() { char* sz="Hello//world"; }


Другие идеи:

Вместо этого используйте правильный лексер / парсер

Посмотрите на

  • CoCo / R (доступно дляJava, C ++, C # и т. Д.)
  • ANTLR (то же самое)
  • Повышение духа (с Spirit Lex для упрощения удаления комментариев)

Все комплекты поставляются с примерами грамматик, которые анализируют C, C ++ или их подмножество

...