如何用bison return函数名?

How to return function name with bison?

我正在使用 bison 和 flex 构建一个简化的 C 解析器。我已经编写了一个语法规则来检测我的 Bison 文件中的函数,并且我希望解析器将函数的名称发送到我的 C 监视程序。这是我实施的一个极其简化的示例:

我的监控程序

/*monitor.h*/
#ifndef MONITOR_H
#define MONITOR_H

extern int noLig;
extern char* yytext;

#endif

/*monitor.c*/
#include <stdio.h>
#include <monitor.h>
#include <project.tab.h>

int noLig=0;

int main (int argc, char * argv[]) {
    printf("flex-\n");
    int err_code=yyparse();
    if (err_code == 0) {
        printf("It went fine\n");
    } else {printf("It didn't go well\n");}
    return 0;
}

project.l 文件

%{
#include <stdio.h>
#include <monitor.h>
#include <project.tab.h>
%}

%%
"\"[a-zA-Z0-9]+"\"  {ECHO; yylval.str=yytext; return STR;}
[.,;=()\[\]\{\}]        { return yytext[0]; }

"char"      {ECHO; printf("-"); yylval.str=yytext; return TYPE;}
"int"       {ECHO; printf("-");yylval.str=yytext; return TYPE;}
"float"     {ECHO; printf("-");yylval.str=yytext; return TYPE;}
"double"    {ECHO; printf("-");yylval.str=yytext;return TYPE;}

[a-zA-Z][a-zA-Z0-9]* {ECHO; printf("-");yylval.str = yytext; return VAR;}

[ \t\n\b]+  {noLig++;}
"//".*      {}
.       {printf(":%cwhat is this",yytext[0]);}
%%

project.y 文件

%{
#include    <stdio.h>
#include    <monitor.h>
int yylex();
int yyerror ();
%}
%union {
    char *str;
    int i;
}
%define parse.error verbose
%type <i> INT
%type <str> TYPE STR VAR

%token TYPE INT STR VAR

%start Program
%%
Program: function_l
    ;

function_l: function
    | function_l function
    ;

function: TYPE VAR '(' param_prototype_ld ')' '{' instruction_l '}'
    {printf("\n\nbison-\n%s\n",);}
    ;

param_prototype_ld: /*empty*/
    | param_prototype_l
    ;

param_prototype_l: param_prototype
    | param_prototype_l ',' param_prototype
    ;

param_prototype: TYPE VAR
    ;

instruction_l: /*empty*/
    | VAR ';'
    | VAR instruction_l
    ;
%%
int yyerror (char* s) {
    fprintf(stderr, "Compilator3000:l.%d: %s\n", noLig, s);
}

test.c 文件

int main (int arg) {
    a;
}

编译正常,没有警告。但是,当我 运行 ./monitor < test.c 时,我得到以下输出:

flex-
int-main-int-arg-a-

bison-
int main (int arg) {
    a;
}
It went fine

为什么 bison 变量 return 是整个功能块?我怎样才能只得到 return 类型? (最后,我的目标是打印 return 类型、函数名称和参数类型)

尽管 OP 已经找到了解决方案,但我会尝试提供一个完整的答案。

这是根据您的代码定义函数的语法。

function: TYPE VAR '(' param_prototype_ld ')' '{' instruction_l '}'
    {printf("\n\nbison-\n%s\n",);}
    ;

每个符号都是一个位置变量。例如,TYPE 是 $1,VAR 是 $2(我相信这是函数名称)。 $$ 是任何规则的 return 值。在这种情况下 function。为了 return 您需要在操作部分设置 $$=$2 的函数名称。将 $$ 设置为 $1 将 return 函数名称。或者,您可以在操作中创建一个数据结构,例如数组或结构来保存多个 $ 变量,然后 return 它。

效果看下面的规则

function_l: function
    | function_l function
    ;

非终结符号函数将保留函数的名称。在此规则中,"function_l" 是 $1,"function" 是 $2。如果你打印 $2 它会给你从规则 "function".

传递过来的函数名

由于终端 "VAR" 是一个字符串,您需要在 lex 或语法规则中将 yylval.str=strdup(yytext) 设置为 yylval.str=strdup($<pos>)

yytext is not guaranteed to persist 的值,要使 yytext 持久化,必须将其复制到单独的缓冲区。这通常使用 strdup:

...
"\"[a-zA-Z0-9]+"\"  {ECHO; yylval.str=strdup(yytext); return STR;}
[.,;=()\[\]\{\}]    { return yytext[0]; }

"char"      {ECHO; printf("-"); yylval.str=strdup(yytext); return TYPE;}
"int"       {ECHO; printf("-");yylval.str=strdup(yytext); return TYPE;}
"float"     {ECHO; printf("-");yylval.str=strdup(yytext); return TYPE;}
"double"    {ECHO; printf("-");yylval.str=strdup(yytext);return TYPE;}

[a-zA-Z][a-zA-Z0-9]* {ECHO; printf("-");yylval.str = strdup(yytext); return VAR;}
...

虽然 strdup 可以 return NULL,但可以使用包装函数来显式显示该失败

char *
strdup_checked(char *str)
{
        char *p;

        if ((p = strdup(str)) == NULL) {
                perror("strdup");
                exit(EXIT_FAILURE);
        }
        return (p);
}