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、带引号的字符串或枚举常量。此代码应将文件中的 SECTION_NAMEs 和 OPTION_NAMEs 提供给控制台输出。但事实并非如此。相反,它会打印整个文件。如果我将 $1 更改为 $2,它可以正常工作并打印 SECTION_NAMEs 和 VALUES。它出什么问题了?如何访问 OPTION_NAME 令牌值?提前致谢。

UPD。Flex 部分工作正常。{printf(yylval.val_char); return OPTION_NAME;} 为控制台提供正确的令牌值。也许是野牛部分的问题。

4

1 回答 1

2

问题是您要yytext为令牌语义值返回指针。 yytext是 flex 用于匹配标记的内部缓冲区,它仅在下一次调用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;}

ETC

于 2012-11-09T21:30:16.083 回答