Next: , Previous: Useful Code, Up: Useful Code


9.1 コメントの処理

Flex and Cにおいて述べたように、 コメントはinput()を使って処理することができます。 これを行うためのコードは以下のようになります。

     %%
     "/*" {
             int a,b;
     
             a = input();
             while(a != EOF){
               b = input();
               if(a == '*' && b == '/'){
                 break;
                }else{
                 a = b;
                }
              }
             if(a == EOF){
               error_message("EOF in comment");
             }
           }

これは、 FlexとLexの両方で正当なコードです。 コメントは排他的スタート状態を使って処理することも可能で、 こちらの方がより美しく、 より効率的です。 スタート状態を使ってコメントを処理するコードは、 以下のようになります。

     %x COMMENT
     %%
     "/*"                  BEGIN(COMMENT);
     <COMMENT>[^\n]
     <COMMENT>\n
     <COMMENT><<EOF>>      yyerror("EOF in comment");
     <COMMENT>"*/"         BEGIN(INITIAL);

改行の1つ前までと改行とを別々に処理した方が良いのは、 そうしないと、 内部のマッチ処理用のバッファをオーバーフローさせてしまうようなルールを作ることになってしまうからです。 Lexは排他的スタート状態をサポートしていないので、 このコードはLexでは動きません。 この例は分かりやすいのですが、 実際には単一文字をマッチするのに多くの時間を無駄に消費するため、 非効率的です。 もっと長いテキストにマッチするように変更することで、 スピードをかなり向上させることができます。 例えば、 以下のように書き直すことができます。

     %x COMMENT
     %%
     "/*"                     BEGIN(COMMENT);
     <COMMENT>[^*\n]*
     <COMMENT>[^*\n]*\n
     
     <COMMENT>"*"+[^*/\n]*    /* 余分な*を探す */
     <COMMENT>"*"+[^*/\n]*\n
     <COMMENT><<EOF>>         yyerror("EOF in comment");
     <COMMENT>"*"+"/"         BEGIN(INITIAL);

これは、 Flexと一緒に配布されているflexdoc.1の中にある例とほとんど同一です。 より長いテキスト・ブロックにマッチするため、 はるかに高速ですし、 ルールの中で改行のみにマッチさせる必要もありません。