⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yufa.cpp

📁 本程序是实现C-的一个小型编译器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
#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 + -