Подтвердить что ты не робот

Сложность получения комментариев в стиле c в flex/lex

Я хочу сделать правило в flex, чтобы использовать комментарий в стиле c, например /* */

i имеет следующий

c_comment "/*"[\n.]*"*/"

Но он никогда не подстраивается. Любая идея почему? если вам нужно больше моего кода, пожалуйста, дайте мне знать, и я отправлю все это. Спасибо всем, кто отвечает.

4b9b3361

Ответ 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)"*/" измените свое регулярное выражение на это, оно будет работать точно.