2016-03-06 34 views
0

我建立一個編譯器,我有一些問題,我的解析器鏈接到我的符號表。 我試圖編譯簡單的表達式所示:問題的Yacc文件鏈接到符號表

一個= 3 + 2;

輸出的(a);

我沒有得到5作爲輸出,我想不出什麼我做錯了。 我把我的代碼如下:

lexor.l

%{ 
#include "y.tab.h" 
%} 


%% 


[0-9]+    {yylval.num = atoi(yytext); return number;} 

begin   {return start;} 

end    {return end;} 

output   {return print;} 

[a-zA-Z][a-zA-Z0-9]* {yylval.id = yytext; return ID;}  

[-+=*;(/)]  {return yytext[0];} 

[ \t\n]   ; //do nothing 

.   {ECHO; yyerror ("unexpected char");} 

%% 
int yywrap (void) {return 1;} 

parse.y

%{ 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 
#include "hash.h" 

void yyerror(char *s); 

%} 

%union {int num; char *id;} 
%start line 
%token print 
%token end 
%token start 
%token <num> number 
%token <id> ID 
%type <num> line exp term 
%type <id> assignment 

%% 

line : assignment ';'  {;} 
     | start ';'    {Enter_new_scope();} 
    | end ';'   {Leave_current_scope();} 
    | print '(' exp ')' ';'  {printf("Printing %d\n", $3);}  
    | line assignment ';'  {;} 
    | line print '(' exp ')' ';' {printf("Printing %d\n", $4);} 
    | line ';' end ';'  {Leave_current_scope();} 
/* | start ';' line';'   {Enter_current_scope();} */ 
    ; 

assignment : ID '=' exp   { Insert($1, $3); } 
      ; 

exp : term   {$$ = $1;} 
     | exp '+' term  {$$ = $1 + $3;} 
     | exp '-' term  {$$ = $1 - $3;} 
     | exp '*' term  {$$ = $1 * $3;} 
     | exp '/' term  {$$ = $1/$3;} 
     | exp '*' '*' term  {$$ = pow($1, $4);} 
     ;   

term  : number    {$$ = $1;} 
     | ID    {$$ = findValue($1);} 
     ;  

%% 


int main(void){ 

    scope = 0; 
    buckets = 100; 

    stack = (struct hash *)calloc(buckets, sizeof(struct hash)); 
    return yyparse(); 

} 

void yyerror (char *s) {fprintf (stderr, "%s\n", s);} 

hash.h

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 


struct hash *stack = NULL; //I am using a hashTable to store the scopes 
int buckets = 0; //a bucket represent a scope 

int temp, scope = 0; //help for switching between scopes 


struct symbol{ 
    int scope; 
    char name[100]; 
    int value; 
    struct symbol *next; 
}; 

struct hash{ 
    struct symbol *head; 
    int count; 
}; 

struct symbol *create_symbol(int scope, char *name, int value) 
{ 
    struct symbol *newSymbol; 

    newSymbol = (struct symbol *)malloc(sizeof(struct symbol)); 
    newSymbol->scope = scope; 
    strcpy(newSymbol->name, name); 
    newSymbol->value = value; 
    newSymbol->next = NULL; 

    return newSymbol; 
} 

void modSymbol(char *name, int value){ 

    int findScope; 

    findScope = Search(name); 

    int index = findScope % buckets; 

    struct symbol *mySymbol; 

    mySymbol = stack[index].head; 

    while(mySymbol != NULL){ 
     if(strcmp(mySymbol->name, name) == 0){ 
      mySymbol->value = value; 
      break; 
     } 
     mySymbol = mySymbol->next; 
    } 
return; 
} 

int findValue(char *name){ 

    int findScope, index; 
    int retValue = 0; 

    struct symbol *mySymbol; 

    findScope = Search(name); 

    index = findScope % buckets; 

    mySymbol = stack[index].head; 

    while(mySymbol != NULL){ 
     if(mySymbol->scope = findScope && strcmp(mySymbol->name, name) == 0){ 
      retValue = mySymbol->value; 
      break; 
     } 
     mySymbol = mySymbol->next; 
    } 
return retValue; 
} 


void Insert(char *name, int value) 
{ 
    int index = scope % buckets; 
    struct symbol *newSymbol = create_symbol(scope, name, value); 


    if (Search(name)){ //In case the symbol was already declared 
     modSymbol(name, value); 
     return; 
     } 

    if(!stack[index].head){ 
     stack[index].head = newSymbol; 
     stack[index].count = 1; 

     return; 
    } 

    newSymbol->next = (stack[index].head); 

    stack[index].head = newSymbol; 
    stack[index].count++; 

    return; 
} 


int search_scope(int scope, char *name) //Only search the current scope 
{ 
    int index = scope % buckets, flag = 0; 
    struct symbol *mySymbol; 

    mySymbol = stack[index].head; 
    if(!mySymbol){ 
     //printf("\nERROR: variable '%s' was not declared\n\n", name); 

     return; 
    } 

    while(mySymbol != NULL){ 
     if(mySymbol->scope == scope && strcmp(mySymbol->name, name)==0){ 
      //printf("\nVariable '%s' was found in scope '%d'\n\n", mySymbol->name, mySymbol->scope); 
      flag = 1; 
      break; 
     } 
     mySymbol = mySymbol->next; 
    } 
//  if(!flag) 
//  printf("variable is unavailable in scope"); 

    return flag; 
} 

int Search(char *name) 
{ 
    int flag = 0; 
    while(!search_scope(scope, name) && scope != 0){ 
     scope = scope-1; 

    } 

    if(search_scope(scope, name)) 
     flag = scope; 

    scope = temp; //back to the scope on the top of the stack; 

    return flag; 
} 


void display(){ 

    struct symbol *mySymbol; 
    int i; 

     printf("\nscope  Name  Type\n"); 
    printf("-----------------------------------------------\n"); 

    for(i=0; i<buckets; i++){ 

     if(stack[i].count==0) 
        continue; 

     mySymbol = stack[i].head; 

     if(!mySymbol) 
      continue; 


     while(mySymbol != NULL){ 
      printf("%d", mySymbol->scope); 
      printf("\t\t%s", mySymbol->name); 
      printf("\t\t%d\n", mySymbol->value); 

      mySymbol = mySymbol->next; 
     } 

    } 
    return; 
} 

void Leave_current_scope() 
{ 
    temp = scope; //save the position of the last scope created 

    return; 
} 

void Enter_new_scope() 
{ 
    scope++;//create a new scope by incrementing the index 

     temp = scope;//In case search() is done within a scope 
    return; 
} 

回答

1

至少有一個問題是,你的詞法分析器返回一個指針yytext,詞法分析器的內部令牌緩衝區。

[a-zA-Z][a-zA-Z0-9]* {yylval.id = yytext; return ID;} 

,直到下一個令牌讀,點令牌緩衝區將有可能被修改爲下一個標記處這是唯一有效的。如果你想讓它保持有效,你需要製作一份令牌副本:

[a-zA-Z][a-zA-Z0-9]* {yylval.id = strdup(yytext); return ID;} 
+0

It works.Thank you !!! – zuludictator