将Yacc文件链接到符号表的问题

时间:2016-03-06 23:38:53

标签: parsing compiler-construction yacc lex

我正在构建一个编译器,并且在将我的解析器链接到我的SymbolTable时遇到了一些问题。 我正在尝试编译简单的表达式,如:

a = 3 + 2;

输出();

我没有得到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 个答案:

答案 0 :(得分: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;}