如何用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);
}
我正在使用 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);
}