我正在构建一个编译器,并且在将我的解析器链接到我的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;
}
答案 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;}