📄 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 + -