複数のバッファを使うというアイデアを理解するための手助けとして、
インクルードすべきファイルを探すCのスキャナの一部を以下に示します。
これはCの#includeのうち、
引用符で囲まれた文字列のみを受け付けます。
例えば、
#include"file1.c"
#include "file2.c"
#include " file3.c"
は、 最後の例のファイル名が空白を含むことになりますが、 いずれも正当な入力です。 ここでの例はまた、 EOFルールとスタート状態の使用法を実演する良い例でもあります。
/*
* eof_rules.lex : 複数バッファ、EOFルール、スタート状態
* の使い方の例
*/
%{
#define MAX_NEST 10
YY_BUFFER_STATE include_stack[MAX_NEST];
int include_count = -1;
%}
%x INCLUDE
%%
^"#include"[ \t]*\" BEGIN(INCLUDE);
<INCLUDE>\" BEGIN(INITIAL);
<INCLUDE>[^\"]+ { /* インクルード・ファイルの名前を獲得する */
if ( include_count >= MAX_NEST){
fprintf( stderr, "Too many include files" );
exit( 1 );
}
include_stack[++include_count] = YY_CURRENT_BUFFER;
yyin = fopen( yytext, "r" );
if ( ! yyin ){
fprintf(stderr,"Unable to open \"%s\"\n",yytext);
exit( 1 );
}
yy_switch_to_buffer(
yy_create_buffer(yyin,YY_BUF_SIZE));
BEGIN(INITIAL);
}
<INCLUDE><<EOF>> {
fprintf( stderr, "EOF in include" );
yyterminate();
}
<<EOF>> {
if ( include_count <= 0 ){
yyterminate();
} else {
yy_delete_buffer(include_stack[include_count--] );
yy_switch_to_buffer(include_stack[include_count] );
BEGIN(INCLUDE);
}
}
[a-z]+ ECHO;
.|\n ECHO;
スタート状態を使ってファイル名のスキャナを生成する方法や、
バッファの切り替えを発生させる方法に注目してください。
ほかに注目すべき重要な点は、
<<EOF>>を取り扱うセクション、
および、
古いバッファに復帰する際にBEGINを使って確実に正しい状態に遷移するようにする点です。
これを怠ると、
状態はINITIALにリセットされ、
#includeの最後の`"'がECHOされてしまいます。
注:<<EOF>>機能は次の節で説明します。 <<EOF>>が何であり、 何を行うものかという点に関する詳細な議論については、 See Start States。