2016-08-31 6 views
4

私はbisonとflexを使って簡略化されたCパーサを構築しています。私はBisonファイルの関数を検出するための文法ルールを書いており、関数の名前をCの監視プログラムに送るようにしたい。ここで私が実装した内容の非常に単純化されたサンプルです:bisonで関数名を返す方法は?

私のモニタプログラム

/*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",$1);} 
    ; 

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 

なぜ全体の機能ブロックを返す$1バイソン変数?戻り値の型のみを取得するにはどうすればよいですか? (最終的には、戻り値の型、関数名、引数の型を出力することが目標です)

+3

を、とすべきである:これは、多くの場合、strdupを使用して行われます'strdup'のような関数でコピーしてください。 – kdhp

答えて

3

yytext is not guaranteed to persistの値として、文法規則のいずれかでyylval.str=strdup(yytext)を設定するために、そしてyytextは、それが別々にコピーする必要があります存続させる必要がある文字列です。バッファ。各試合で `yytext`変更の内容は、strdupNULLを返すことができますが、ラッパー関数は、その失敗を明示的に使用することができ

... 
"\"[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;} 
... 

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

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

OPが解決策を見つけましたが、私は完全な答えを提供しようとします。

これは、コードごとに関数を定義する文法です。

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

各記号は位置変数です。例えばTYPEは$ 1、VARは$ 2です(これは関数名と思われます)。 $$は任意のルールの戻り値です。この場合function。関数名を返すには、アクション部分に$$ = $ 2を設定する必要があります。 $$を$ 1に設定すると、関数名が返されます。あるいは、複数の$変数を保持する配列や構造体などのアクション内にデータ構造を作成し、それを返すこともできます。

効果は

function_l: function 
    | function_l function 
    ; 

非終端記号の関数は、関数の名前を保持する次のルールに見られます。このルールでは、 "function_l"は$ 1、 "function"は$ 2です。 $ 2を出力すると、ルール "function"から渡された関数名が与えられます。ターミナル「VAR」以来

あなたはLEXやyylval.str=strdup($<pos>)

関連する問題