Flexでreentrantなlexerを作ってみた

作ってみた。
https://github.com/coiled-coil/flex-example/blob/master/lexer.l

%{
#include <string.h>
%}

%option noyywrap reentrant stack nounput
%x MODE_A MODE_B

%{
enum {
    TOK_1 = 10,
    TOK_2 = 20,
    TOK_3 = 30,
};
%}

%%

. printf("INITIAL: %s\n", yytext); yy_push_state(MODE_A, yyscanner); return TOK_1;
<MODE_A>. printf("MODE_A: %s\n", yytext); BEGIN(MODE_B); return TOK_2;
<MODE_B>. printf("MODE_B: %s\n", yytext); yy_pop_state(yyscanner); return TOK_3;

%%

int main()
{
    const char buf[] = "123456789";
    int len = strlen(buf);

    yyscan_t scanner;
    yylex_init(&scanner);
    YY_BUFFER_STATE bs = yy_scan_bytes(buf, len, scanner);
    int token_id;
    while ((token_id = yylex(scanner))) {
        printf("TOKEN: %d\n", token_id);
    }
    yy_delete_buffer(bs, scanner);
    yylex_destroy(scanner);

    return 1;
}


出力結果

====== BEGIN OUTPUT ======
INITIAL: 1
TOKEN: 10
MODE_A: 2
TOKEN: 20
MODE_B: 3
TOKEN: 30
INITIAL: 4
TOKEN: 10
MODE_A: 5
TOKEN: 20
MODE_B: 6
TOKEN: 30
INITIAL: 7
TOKEN: 10
MODE_A: 8
TOKEN: 20
MODE_B: 9
TOKEN: 30

EXIT STATUS: 1
====== END OUTPUT ======


参考にしたもの。


Start Conditions
http://flex.sourceforge.net/manual/Start-Conditions.html#Start-Conditions


Reentrant
http://flex.sourceforge.net/manual/Reentrant-Example.html#Reentrant-Example


ソースコード
https://github.com/coiled-coil/flex-example