?? yufa.cpp
字號:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "conio.h"
#define N 5
typedef struct token
{
int LineofPro;
int code;
char name[30];
}token;
/*語法樹的數據結構*/
typedef struct CTreeNode
{
int Node_Number;//結點編號
int FID;//所用產生式編號
//int code;//終結符編號,非終結符設置為0,終結符按編號來處理
//char name[30];//終結符名稱,非終結符設置為空
struct token TOKEN;
struct CTreeNode *Leftchild;//左孩子結點
struct CTreeNode *Rightsibling;//右兄弟結點
struct CTreeNode *father;//指向父結點
}CTreeNode,*SyntaxTree;
int k=1;//結點編號依次累加
CTreeNode* m_pProgram;
//不處理數組
char stack[10];//棧,用來放括號,如果括號匹配則將高度降一格,并將上格置空
char status[5];//用來暫存數據類型或函數返回值類型,不存放形參
char variable[10];//用來暫存變量名
char function[10];//用來暫存函數名
/*變量表*/
typedef struct Variable_Table
{
char name[30];//變量名
char type[5]; //變量數據類型
int kind;//1為全局變量,2為函數形參,3為函數局部變量
int scope;//作用域,指層數 定義:10:全局變量; 11:第一個函數體第一層(最外層)
}Variable_Table;// 12:第一個函數體第二層; 21:第二個函數體第一層
/*函數表*/
typedef struct Global_function
{
char function_name[10];//函數名
char type[5];//函數返回類型
int parameter_variable;//函數第一個形參在變量表的位置
int local_variable;//函數體內的第一個局部變量在變量表里的位置
}Global_function;
/*四元式結構*/
typedef struct equ
{
char op[10];
char arg1[10];
char arg2[10];
int result;
}equ;
equ EQU[200];//用來存放四元式的結構體數組
int True_address;//用來存放真出口標號
//因為不做if_else和while的嵌套,所以當做完if和while,truelist和falselist置空
int False_address;//用來存放假出口標號
char OP[10];//用來暫存op符號,如果有必要
char ARG1[10];//用來暫存arg1,如果有必要
char ARG2[10];//用來暫存arg2,如果有必要
int RESULT;//用來暫存變量名在變量表里的地址標號或填回填標號
int nextquad=100;//起始標號,注意每次累加
char expression_stack[10][10];//棧,用來暫存求表達式的值,以便生成四元式,這里不考慮算符優先
int Top_stack=0;
FILE *TokenFile;//打開token文件
int error_count=0;//記錄語法有幾個錯誤
token CurrentToken,curToken;
token CurToken[10000];//token文件寫到結構體數祖
int Token_Number=57;//token表單詞數量,由詞法分析器提供
Variable_Table VT[20];//變量表的結構體數組
Global_function GFT[10];//函數表的結構體數組
int j=1;
int TopVT=1;//變量表的結構體數組計數
int TopGFT=1;//函數表的結構體數組計數
int flag;//判別是插入變量名表還是函數名表
int param_number=0;//形參個數
int local_number=0;//局部變量個數
int Par_number=0;//記錄{}匹配的次數
int R=0;//用來放括號'{'和'}'
int r=0;//用來放括號,如果匹配成功,減1
/*語法和語義函數聲明*/
void NextToken();
void advance();
void parser();
CTreeNode* program();
CTreeNode* declaration_list();
CTreeNode* declaration_list1();
CTreeNode* declaration();
CTreeNode* declaration1();
CTreeNode* type_specifier();
CTreeNode* params();
CTreeNode* param_list();
CTreeNode* param_list1();
CTreeNode* param();
CTreeNode* param1();
CTreeNode* compound_stmt();
CTreeNode* local_declarations();
CTreeNode* local_declarations1();
CTreeNode* statement_list();
CTreeNode* statement();
CTreeNode* expression_stmt();
CTreeNode* selection_stmt();
CTreeNode* selection_stmt1();
CTreeNode* iteration_stmt();
CTreeNode* return_stmt();
CTreeNode* return_stmt1();
CTreeNode* expression();
CTreeNode* var();
CTreeNode* var1();
CTreeNode* simple_expression();
CTreeNode* simple_expression1();
CTreeNode* relop();
CTreeNode* additive_expression();
CTreeNode* additive_expression1();
CTreeNode* addop();
CTreeNode* term();
CTreeNode* term1();
CTreeNode* mulop();
CTreeNode* factor();
CTreeNode* call();
CTreeNode* args();
CTreeNode* arg_list();
CTreeNode* arg_list1();
bool PrintTree( CTreeNode* );
void Print();
void PrintVT();
void PrintGFT();
void Symble_Table_error(int,int);
void error(int,int);
void main_error();
void BackPatch(int,int);//出口回填函數
int EquPush(char*, char*,char*,int);//生成四元式
int newtemp();//生成新結點函數
void Print_equ();//打印四元式
void expression_in();//表達式入棧
void Init_expression();//表達式棧的初始化
/*********************四元式的操作*****************************/
//出口回填函數,將當前標號cur_addr賦給上一個出口pre_addr
void BackPatch(int pre_addr,int cur_addr)
{
EQU[pre_addr].result=cur_addr;
return;
}
//生成四元式的函數,做完將標號加1,
int EquPush(char *op1,char *addr1,char *addr2,int add_line)
{
int i=nextquad;
strcpy(EQU[nextquad].op,op1);
strcpy(EQU[nextquad].arg1,addr1);
strcpy(EQU[nextquad].arg2,addr2);
EQU[nextquad].result=add_line;
nextquad++;
return i;
}
//生成一個新結點,用來存放
int newtemp()
{
int a;
a=nextquad-1;
return a;
}
//打印四元式函數
void Print_equ()
{
printf("code: op: arg1: arg2: result:\n");
for(int i=100;i<nextquad;i++)
{
printf("%-11d",i);
printf("%-11s",EQU[i].op);
printf("%-10s",EQU[i].arg1);
printf("%-10s",EQU[i].arg2);
printf("%d\n",EQU[i].result);
}
}
//表達式棧的初始化
void Init_expression()
{
strcpy(ARG1,"\0");
strcpy(ARG2,"\0");
strcpy(OP,"\0");
strcpy(expression_stack[Top_stack++],"#");
}
//表達式入棧
void expression_in(char*in_stack)
{
strcpy(expression_stack[Top_stack++],in_stack);
}
//查找變量在變量表里的位置
int lookup(char *variable_location)
{
for(int i=1;i<TopVT;i++)
if((strcmp(variable_location,VT[i].name)==0))
return i;
}
/*******************關于符號表的操作****************************/
/************符號表的查找函數*************/
//先在變量表里找,找不到先將名字存在棧里,如果確定是函數名,
//在函數表找.查找到了返回1,沒有查找到返回0.
//找到了注意將名字退棧,不要了
int st_lookup (char *pre_name,char *cur_name)
{
if(((strcmp(cur_name,";"))==0)&&(stack[R-1]!='{'))//程序體未開始,全局變量的情況
{
for(int i=1;i<TopVT;i++)
if((strcmp(pre_name,VT[i].name)!=0)&&(strcmp(status,VT[i].type)!=0))//是否重復出現
;
else
break;
if(i==TopVT)//沒有重復出現
{
flag=0;//變量名
return 0;//添加進去
}
else
{
Symble_Table_error(1,CurToken[j-1].LineofPro);//全局變量重復或者數據類型為void,報錯
return 1;
}
}//全局變量的處理
else
if((strcmp(cur_name,"("))==0)//程序開始,函數名的情況
{
for(int i=1;i<TopGFT;i++)
if((strcmp(pre_name,GFT[i].function_name)!=0))//是否重復出現
;
else
break;
if(i==TopGFT)//沒有重復出現
{
flag=1;//函數名
return 0;//添加進去
}
else
return 1;
}//對于函數名重復出現的情況
else
if(stack[R-1]=='(')//形參的情況
{
for(int i=TopVT-param_number;i<TopVT;i++)
if((strcmp(pre_name,VT[i].name)!=0))//是否重復出現
;
else
break;
if(i==TopVT)//沒有重復出現
{
flag=0;//變量名,形參名
return 0;//添加進去
}//同一個函數中不準定義相同的形參
else
{
Symble_Table_error(2,CurToken[j-1].LineofPro);//同一個函數體有兩個相同形參
return 1;
}
}
else //即將定義的局部變量的處理
if(((strcmp(cur_name,";"))==0)&&(stack[R-1]=='{'))
{
for(int i=1;i<TopVT;i++)
{
if((strcmp(pre_name,VT[i].name)!=0))
;
else
if((strcmp(pre_name,VT[i].name)==0)&&(VT[i].scope/10!=(Par_number+1)))
;//同名但作用域不同
else
break;
}
if(i==TopVT)//沒有重復出現
{
flag=0;//變量名
return 0;//添加進去
}
else
{
Symble_Table_error(3,CurToken[j-1].LineofPro);//函數體定義了相同的局部變量
return 1;
}
}
else
return 1;
}
int st_lookup(char *cur_name)//查找是否是已經定義過的局部變量或調用函數
{
for(int i=1;i<TopVT;i++)//在變量名表里面查,有的話return 1,沒有return 0.
{
if((strcmp(cur_name,VT[i].name)==0)&&(VT[i].scope/10==(Par_number+1)))//重復出現
return 1;
}
if(i==TopVT)
{
for(int j=1;j<TopGFT;i++)//在函數名表里面查
{
if((strcmp(cur_name,GFT[j].function_name)==0))
return 1;
}
if(i==TopGFT)
{
Symble_Table_error(5,CurToken[j].LineofPro);//此調用函數未定義
return 0;
}
Symble_Table_error(4,CurToken[j].LineofPro);//此局部變量未在函數體里定義
return 0;
}
else
return 0;
}
/************符號表的插入函數*************/
//如果在變量名表和函數表里都沒有找到,則需要將名字插入變量名表或函數名表
//這里要設置一個標記flag,用來分辨此名字是變量名還是函數名
//flag=0,表示是變量名;flag=1,表示是函數名,注意插入的表
void st_insert(char *name,char *TYPE,char *CUR_NAME)
{
if((st_lookup(name,CUR_NAME))==0)//沒有找到,需要插入
{
if((flag==0)&&((strcmp(CUR_NAME,";"))==0)&&(stack[R-1]!='{'))//全局變量名,插入到變量名表中
{
strcpy(VT[TopVT].name,name);
strcpy(VT[TopVT].type,TYPE);
VT[TopVT].kind=1;
VT[TopVT].scope=10;
TopVT++;
}
else
if((stack[R-1]=='(')&&(flag==0))//形參的插入
{
strcpy(VT[TopVT].name,name);
strcpy(VT[TopVT].type,TYPE);
VT[TopVT].kind=2;
VT[TopVT].scope=(Par_number+1)*10+R;
if(param_number==1)//將第一個形參位置放進相應函數里函數
{
for(int i=1;i<=TopGFT;i++)
if((strcmp(GFT[i].function_name,function))==0)
{
GFT[i].parameter_variable=TopVT;
break;
}
}
TopVT++;
}
else
if(((strcmp(CUR_NAME,";"))==0)&&(stack[R-1]=='{')&&(flag==0))//局部變量的插入
{
strcpy(VT[TopVT].name,name);
strcpy(VT[TopVT].type,TYPE);
VT[TopVT].kind=3;
VT[TopVT].scope=(Par_number+1)*10+r;
if(local_number==1)
{
for(int i=1;i<TopGFT;i++)
if((strcmp(GFT[i].function_name,function))==0)
{
GFT[i].local_variable=TopVT;
break;
}
}
TopVT++;
}
else
if((flag==1)&&((strcmp(CUR_NAME,"("))==0))//函數名的插入
{
strcpy(GFT[TopGFT].function_name,name);
strcpy(GFT[TopGFT].type,TYPE);
TopGFT++;
}
}
}
/***************函數實現及代碼*********************/
void InitTree()//語法樹的初始化
{
m_pProgram=(SyntaxTree)malloc(sizeof(CTreeNode));
m_pProgram = NULL;
}
CTreeNode* BuildSyntaxTree()
{
return (m_pProgram=program());
}
bool PrintTree( CTreeNode* m_pProgram )
{
if(m_pProgram)
{
printf("%-8d ",m_pProgram->Node_Number);
printf("%-10d ",m_pProgram->TOKEN.LineofPro);
printf("%-8d ",m_pProgram->TOKEN.code);
printf("%-8s ",m_pProgram->TOKEN.name);
if(m_pProgram->father!=NULL)
printf("%-10d",m_pProgram->father->Node_Number);
else
printf(" ");
switch(m_pProgram->FID)
{
case 1: printf("pragram->declaration_list");
break;
case 2: printf("declaration_list->declaration declaration_list1");
break;
case 3: printf("declaration_list1->declaration declaration_list1| ^");
break;
case 4: printf("declaration->type_specifier ID declaration1");
break;
case 5: printf("declaration1->;|[NUM];|(params) compound_stmt");
break;
case 6: printf("type_specifier->int|void");
break;
case 7: printf("params->param_list|void");
break;
case 8: printf("param_list->param param_list1");
break;
case 9: printf("param_list1->,param param_list1|^");
break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -