2016-08-31 5 views
4

나는 바이슨과 플렉스를 사용하여 단순화 된 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",$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

을 만드는 데 사용'의 내용 yytext' 각 경기와 변화, 그리고해야 할 수 있습니다 'strdup'와 같은 함수로 복사하십시오. – kdhp

답변

3

yytext is not guaranteed to persist의 값으로 문법 규칙 중 하나 yylval.str=strdup(yytext)을 설정하고, 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하지만이 NULL을 반환 할 수 있습니다, 래퍼 함수는 명시 적으로 그 실패

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"이후

당신이 렉스 또는 yylval.str=strdup($<pos>)