【问题标题】:Using only string with Flex/Bison仅对 Flex/Bison 使用字符串
【发布时间】:2017-03-30 18:20:56
【问题描述】:

我是 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 的情况下修复?

谢谢。

【问题讨论】:

  • 为避免内存泄漏,您需要将 YYSTYPE 用作 char * 并执行 free(): NUMBER "&lt;=" NUMBER { printf("%s &lt;= %s\n",$1,$3); free($1); free($3);} | | NUMBER "=&gt;" NUMBER { printf("%s =&gt; %s\n",$1,$3); free($1); free($3);} 等等。您可以使用 valgrind valgrind.org 检查您的程序是否有免费的内存泄漏
  • 太棒了!最后一个示例包括您的建议。

标签: bison flex-lexer


【解决方案1】:

您需要在#include "example.tab.h" 之前将#define YYSTYPE char const * 移动到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 生成。

【讨论】:

  • 有效!我知道插入.y 就足够了。此外,我尝试过,但在包含 example.tab.h 之后。我看到 Flex/Bison 有一些在手册中不太清楚的技巧。谢谢!
  • 顺便说一句,您的程序有内存泄漏。 strdup() 使用 malloc() 为字符串分配内存,但您的程序中没有任何 free()。
  • 是的,我知道。这不是我的程序,只是解释主要问题的一个例子。顺便说一句:在示例中, y 必须在每种情况下都执行 free($1) 和 free($3) 以确保避免内存泄漏?还有其他有用的选择吗?
  • 在你这个简单的例子中,我认为你找不到其他有用的选项。对于更高级的示例,您需要 %union,将 tokens 的类型定义为可以保存所有指向字符串的指针(char * 或列表的数组)的结构,并在 expession 结束时释放它,在这个例子中你做了' t 有一些东西来标记 expession 的结束(例如 \n;)。对于您的简单示例,最好使用 char string[20] 作为 YYSTYPE 和 strncpy() 而不是 strdup()。还有更多stackoverflow.com/questions/31104302/…
  • 好的,我明白了。我知道 %union,但我的编译器只是语言之间的翻译。我会考虑改用char string[NUM]。谢谢科马尔。
【解决方案2】:

最后的工作示例是:

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); }

【讨论】:

  • 我探索了%define api.value.type {char const *} 选项,我认为这更好,因为它只在一个地方。所以,我只在.y 中使用它,在%token 声明之前。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多