2

フレックス:

%option noyywrap
%{
    #include "syntax.hpp"
    #include <cstdlib>
    extern "C" int isatty(int);
%}
%%

\#.*                                                {}
\[[A-Za-z_]*\]                                      {yylval.val_char=yytext; return SECTION_NAME;}
[A-Z_a-z[:digit:]]*[A-Z_a-z][A-Z_a-z[:digit:]]*     {yylval.val_char=yytext ;return OPTION_NAME;}
\n                                                  {}
=\".*?\"                                            {yylval.val_char=yytext+1; return VALUE_STRING;}
=[ A-Z_a-z[:digit:]]*[A-Z_a-z][A-Z_a-z[:digit:] ]*  {yylval.val_char=yytext+1; return VALUE_ENUM;}
=[ [:digit:] ]*                                     {yylval.val_int=atoi(yytext+1); return VALUE_INTEGER;}
=[ [:digit:]\.[:digit:]]+                           {yylval.val_float=atof(yytext+1); return VALUE_FLOAT;}


" "                                                 {}
%%

バイソン:

%{
    #include <iostream> 
    int yylex();
    int yyerror(const char *p) {return 0;}

%}

     %union  {
            float val_float;
            int val_int;
            char* val_char;
           };   
     %token <val_char> SECTION_NAME
     %token <val_char> OPTION_NAME
     %token <val_int> VALUE_INTEGER
     %token <val_float> VALUE_FLOAT
     %token <val_char> VALUE_STRING
     %token <val_char> VALUE_ENUM

%%
    input
        :input line
        |line
        ;
    line
       :section
       |value
       ;


    section
        :SECTION_NAME {std::cout<<$1; std::cout<<std::endl;}
        ;

    value
        :OPTION_NAME VALUE_INTEGER  {std::cout<<$1, std::cout<<std::endl;}
        |OPTION_NAME VALUE_FLOAT {std::cout<<$1; std::cout<<std::endl;}
        |OPTION_NAME VALUE_ENUM {std::cout<<$1; std::cout<<std::endl;}
        |OPTION_NAME VALUE_STRING {std::cout<<$1;std::cout<<std::endl;}
        ;
%%

小さなini構成ファイルパーサーをテストしようとしています。option = valueのペアを解析する必要があります。ここで、valueは、int、float、quoted string、または列挙型定数です。このコードは、ファイルからコンソール出力にSECTION_NAMEsとOPTION_NAMEsを提供する必要があります。しかし、そうではありません。その代わりに、ファイル全体を印刷します。$1を$2に変更すると、正常に機能し、SECTION_NAMEsとVALUESが出力されます。どうしたの?OPTION_NAMEトークン値にアクセスするにはどうすればよいですか?前もって感謝します。

UPD。フレックス部分は正常に動作します。{printf(yylval.val_char); return OPTION_NAME;}は、コンソールに正しいトークン値を提供します。おそらくバイソンの部分に問題があります。

4

1 に答える 1

2

yytext問題は、トークンのセマンティック値の ポインターを返すことです。トークンを照合するために flex が使用する内部バッファであり、次のトークンを読み取るためyytextの次の呼び出しまでのみ有効です。yylexしたがって、セマンティック値 ($1など) はすべて、後のトークンからのより多くのトークン データで上書きされているバッファーへのポインターをぶら下げることになります。

yytextより長く使用できるストレージに 文字列をコピーする必要があります。strdupこれには非常に便利です:

\[[A-Za-z_]*\]                                      {yylval.val_char=strdup(yytext); return SECTION_NAME;}
[A-Z_a-z[:digit:]]*[A-Z_a-z][A-Z_a-z[:digit:]]*     {yylval.val_char=stdrup(yytext); return OPTION_NAME;}

于 2012-11-09T21:30:16.083 に答える