Сложность получения комментариев в стиле c в flex/lex
Я хочу сделать правило в flex, чтобы использовать комментарий в стиле c, например /* */
i имеет следующий
c_comment "/*"[\n.]*"*/"
Но он никогда не подстраивается. Любая идея почему? если вам нужно больше моего кода, пожалуйста, дайте мне знать, и я отправлю все это. Спасибо всем, кто отвечает.
Ответы
Ответ 1
Я предлагаю вместо этого использовать условия запуска.
%x C_COMMENT
"/*" { BEGIN(C_COMMENT); }
<C_COMMENT>"*/" { BEGIN(INITIAL); }
<C_COMMENT>\n { }
<C_COMMENT>. { }
Заметьте, что не должно быть пробелом между <condition>
и правилом.
%x C_COMMENT
определяет состояние C_COMMENT, и правило /*
запускает его. После того, как он запустится, */
вернет его в исходное состояние (INITIAL
предопределено), и все остальные символы будут уничтожены без какого-либо конкретного действия. Когда два правила совпадают, Flex устраняет неоднозначность, беря ту, которая имеет самое длинное совпадение, поэтому правило точки не препятствует сопоставлению */
. Правило \n
необходимо, потому что точка соответствует всем, кроме новой строки.
Определение %x
делает C_COMMENT исключительным состоянием, что означает, что lexer будет соответствовать правилам, которые "помечены" <C_COMMENT>
после входа в состояние.
Вот крошечный пример lexer, который реализует этот ответ, печатая все, кроме того, что внутри /* comments */
.
Ответ 2
Вот пример на всякий случай, когда кто-то путается о том, как работать zneak answer:
(В основном вы помещаете "% x C_COMMENT" в первом разделе, а остальные во втором разделе, как объясняется его полезной ссылкой)
foo.l
%{
// c code..
%}
%x C_COMMENT
%%
"/*" { BEGIN(C_COMMENT); }
<C_COMMENT>"*/" { BEGIN(INITIAL); }
<C_COMMENT>. { }
%%
// c code..
Надеюсь, что кто-то поможет!
Tiff
Ответ 3
Не уверен, почему он не подхвачен, но я знаю, что такой шаблон может создавать большие лексические элементы. Более эффективно обнаруживать только маркер стартового комментария и бросать все в битбакет, пока не найдете маркер конца.
Этот сайт имеет код, который будет делать это:
"/*" {
for (;;) {
while ((c = input()) != '*' && c != EOF)
; /* eat up text of comment */
if (c == '*') {
while ((c = input()) == '*')
;
if (c == '/')
break; /* found the end */
}
if (c == EOF) {
error ("EOF in comment");
break;
}
}
}
Ответ 4
Я считаю, что это решение проще:
"/*"((\*+[^/*])|([^*]))*\**"*/"
Ответ 5
Вот как работает руководство по Flex, в котором правильны красноватые случаи:
<INITIAL>"/*" BEGIN(IN_COMMENT);
<IN_COMMENT>"*/" BEGIN(INITIAL);
<IN_COMMENT>[^*\n]+ // eat comment in chunks
<IN_COMMENT>"*" // eat the lone star
<IN_COMMENT>\n yylineno++;
Ответ 6
Проработанный пример:
\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/
который найден в ostermiller.org
Ответ 7
Я попробовал несколько предлагаемых решений, и вот результаты.
- Я не мог получить решение C_COMMENT, которое имеет самые высокие голоса и отлично выглядит, чтобы работать практически на практике (один из комментариев к нему объясняет хотя бы одну причину). Он должен быть занижен и, безусловно, не должен быть самым высоким голосованием.
- Решение от Mugen, похоже, работало во всем коде, на котором я его запускал.
- Не удалось получить решение от Андрея даже для компиляции в lex. Я посмотрел сайт, на который ссылался, и использование шаблонов оттуда не помогло
-
Ответ от paxdiablo работал и имел преимущество в том, что его легко читать. Я дополнительно модифицировал следующим образом:
"/*" { int c1 = 0, c2 = input();
for(;;) {
if(c2 == EOF) break;
if(c1 == '*' && c2 == '/')
break;
c1 = c2;
c2 = input();
}
}
Ответ 8
"/*"(.|\n)"*/"
измените свое регулярное выражение на это, оно будет работать точно.