仅使用Flex / Bison的字符串

时间:2017-03-30 18:20:56

标签: bison flex-lexer

我是Flex / Bison的新手。我想只使用字符串表示值(是一个语言翻译器)。我有这个测试:

example.l:

%option noyywrap nodefault

%{
#include <string.h>
#include "example.tab.h"
%}

%%

[ \t\n] {;}
"<="    {return LEFT;}
"=>"    {return RIGHT;}
[0-9]+ { yylval=strdup(yytext); return NUMBER; }
. { return yytext[0]; }

%%

example.y:

%{
#include <stdio.h>
#define YYSTYPE char const *
%}

%token NUMBER
%token LEFT "<=" RIGHT "=>"

%%

start: %empty | start tokens

tokens:
       NUMBER "<=" NUMBER { printf("%s <= %s\n",$1,$3); }
     | NUMBER "=>" NUMBER { printf("%s => %s\n",$1,$3); }
     | NUMBER '>' NUMBER  { printf("%s > %s\n",$1,$3); }
     | NUMBER '<' NUMBER  { printf("%s < %s\n",$1,$3); }

%%

main(int argc, char **argv) { yyparse(); }
yyerror(char *s) { fprintf(stderr, "error: %s\n", s); }

编译时:

bison -d example.y
flex example.l
cc -o example example.tab.c lex.yy.c -lfl
example.l: In function ‘yylex’:
example.l:13:9: warning: assignment makes integer from pointer without a cast
 [0-9]+ { yylval=strdup(yytext); return NUMBER; }
         ^

但正在等待工作。

如果我不使用#define YYSTYPE char const *而使用%union:

%union {
   char * txt;
}

%token <txt> NUMBER

并将分配更改为[0-9]+ { yylval.txt=strdup(yytext); return NUMBER; },它没有任何警告并且有效。

我尝试过在flex文件中定义相同的YYSTYPE并转换分配但没有成功。怎么了?如何在不使用%union的情况下修复?

感谢。

2 个答案:

答案 0 :(得分:1)

您需要在#define YYSTYPE char const *之前移动#include "example.tab.h"到example.l。

如果您查看example.tab.h,您会发现类似这样的内容:

#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef int YYSTYPE;
// ...
#endif

这意味着您需要在此代码之前定义YYSTYPE,即在#include "example.tab.h之前。否则,如果此时未定义YYSTYPE,则YYSTYPE将被定义为int。

另一种可能性是使用野牛功能%define api.value.type {char const *},你需要在example.y中添加。在这种情况下,example.tab.h将使用char const *类型的YYSTYPE生成。

答案 1 :(得分:0)

最后的工作示例是:

<强> example.l:

%option noyywrap nodefault

%{
#include <string.h>
#define YYSTYPE char *
#include "example.tab.h"
%}

%%

[ \t\n] {;}
"<="    {return LEFT;}
"=>"    {return RIGHT;}
[0-9]+ { yylval=strdup(yytext); return NUMBER; }
. { return yytext[0]; }

%%

<强> example.y:

%{
#include <stdio.h>
#define YYSTYPE char *
%}

%token NUMBER
%token LEFT "<=" RIGHT "=>"

%%

start: %empty | start tokens

tokens:
       NUMBER "<=" NUMBER { 
          printf("%s <= %s\n",$1,$3);
          free($1);
          free($3);
       }
     | NUMBER "=>" NUMBER {
          printf("%s => %s\n",$1,$3);
          free($1);
          free($3);
       }
     | NUMBER '>' NUMBER  {
          printf("%s > %s\n",$1,$3);
          free($1);
          free($3);
       }
     | NUMBER '<' NUMBER  {
          printf("%s < %s\n",$1,$3);
          free($1);
          free($3);
       }

%%

main(int argc, char **argv) { yyparse(); }
yyerror(char *s) { fprintf(stderr, "error: %s\n", s); }