31

/ **/のようなcスタイルのコメントを消費するようにフレックスでルールを作成したい

私は以下を持っています

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

しかし、それは決して一致しません。なぜですか?私のコードがもっと必要な場合は、私に知らせてください。すべてを提出します。返信してくれた人に感謝します。

4

9 に答える 9

47

代わりに開始条件を使用することをお勧めします。

%x C_COMMENT

"/*"            { BEGIN(C_COMMENT); }
<C_COMMENT>"*/" { BEGIN(INITIAL); }
<C_COMMENT>\n   { }
<C_COMMENT>.    { }

とルールの間に空白があってはならないことに注意してください。<condition>

%x C_COMMENTC_COMMENT状態を定義し、ルール/*で開始します。開始*/すると、初期状態(事前定義済み)に戻り、INITIAL他のすべてのキャラクターは特別なアクションなしで消費されます。2つのルールが一致する場合、Flexは最も長い一致を持つルールを取得することで明確にするため、ドットルールは*/一致を妨げません。ドットは改行を除くすべてに一致するため、ルール\nが必要です。

この%x定義により、C_COMMENTは排他状態<C_COMMENT>になります。つまり、レクサーは、状態に入ると「タグ付け」されたルールにのみ一致します。

これは、内部にあるものを除くすべてを印刷することによってこの回答を実装する小さな例のレクサー/* comments */です。

于 2010-01-25T04:00:28.110 に答える
9

zneakの答えを操作する方法について誰かが混乱している場合に備えて、次の例を示します。

(基本的に、彼の役立つリンクで説明されているように、最初のセクションに「%x C_COMMENT」を配置し、残りを2番目のセクションに配置します)

foo.l

%{
// c code..
%}
%x C_COMMENT

%%
"/*"            { BEGIN(C_COMMENT); }
<C_COMMENT>"*/" { BEGIN(INITIAL); }
<C_COMMENT>.    { }

%%
// c code..

それが誰かを助けることを願っています!Tiff

于 2013-01-29T02:55:13.670 に答える
7

なぜそれが取り上げられないのかはわかりませんが、そのようなパターンが大きな語彙要素を生成する可能性があることは知っています。開始コメントマーカーだけを検出し、終了マーカーが見つかるまでビットバケット内のすべてを投げる方が効率的です。

このサイトには、それを行うコードがあります。

"/*" {
    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;
        }
    }
}
于 2010-01-25T04:01:09.577 に答える
2

この解決策はもっと簡単だと思います。

"/*"((\*+[^/*])|([^*]))*\**"*/"
于 2012-11-13T20:47:35.247 に答える
1

私は提案された解決策のいくつかを試しました、そしてここに結果があります。

  • 賛成票が最も多く、見栄えの良いC_COMMENTソリューションを実際に機能させることができませんでした(コメントの1つで、少なくとも1つの理由が説明されています)。それは反対票を投じるべきであり、確かに最高票の解決策であってはなりません
  • Mugenのソリューションは、実行したすべてのコードで機能するようでした
  • Andreyからlexでコンパイルするためのソリューションを取得できませんでした。参照されているウェブサイトを見て、そこからパターンを使用しても役に立ちませんでした
  • paxdiabloからの回答は機能し、読みやすいという利点がありました。私はさらに次のように変更しました:

    "/ *" {int c1 = 0、c2 = input();
           にとって(;;) {
             if(c2 == EOF)break;
             if(c1 =='*' && c2 =='/')
               壊す;
             c1 = c2;
             c2 = input();
           }
         }
    
于 2014-07-24T16:09:22.840 に答える
1

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++;
于 2016-09-25T09:37:42.487 に答える
1

もう一つの例:

"/*"([^*]*|(\*+[^/]))*"*/"
于 2021-01-18T10:05:24.987 に答える
0

実施例は次のとおりです。

\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/

ostermiller.orgで見つかりました

于 2013-08-08T12:28:28.210 に答える
0

スペースと改行を無視する

"/*"
  (
    "/"*
      (
        "*"*
        [^*/]
        "/"*
      )*
    "*"*
  )*
"*/"

Kenneth C. Louden-コンパイラの構築_原則と実践(1997)セクション2.2.3

于 2022-02-21T03:41:49.093 に答える