TEST_Compiler

前言

闲来无事,整理一下上个学期做过的编译原理实验,主要是代码,细节等以后有时间再回顾,希望能帮助到大家。

TEST 语言介绍

TEST 是 C语言的子集,比 C语言简单的多

  1. 变量:整形 int
  2. 控制语句:if、while、for 等
  3. 注释:/* 注释内容 */
  4. 表达式:算数表达式、布尔表达式

拓展功能

  1. 函数形参实现
  2. 数组实现
  3. 值传递
  4. 函数返回值
  5. 定义变量并赋初值
  6. 局部变量

词法分析

词法规则

< ID > ::= < letter >|< ID >< letter >|< ID >< digit >
< NUM > ::= < digit >|< NUM >< digit >
< letter > ::= a | b |…| z | A | B |…| Z
< digit > ::= 1|2|…|9|0
< singleword > ::= + | - | * | ( | ) | { | } | ; | : | [ | ] | !
< doubleword > ::= >= |<= | == | != | || | &&
保留字:{“return”,“call”,“main”,“function”,“if”,“else”,“for”,“while”,“do”,“int”,“read”,“write”,“do”,“switch”,“case”,“break”,“continue”};

原理

状态图法
大致流程图如下
在这里插入图片描述

实现

scan.h

#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<malloc.h> 

#define keywordSum 17
#define singleMax 50
#define doubleMax 10
#define file_length 300
#define tokenMax 40
#define ERR_NUM 20

void sort(char *begin[]);
char* lower(char *temp,char *low);
int binselect(char *target,char **set,int low,int high);
char* str_copy(char *des,char *sour);
//保留字 
char *keyword[keywordSum]={"return","call","main","function","if","else","for","while","do","int","read","write","do","switch","case","break","continue"};
//单分界符
char singleword[singleMax]="+-*(){};,:[]";
//双分界符首字符
char doubleword[doubleMax]="><=!";
char doubleword_add[doubleMax]="|&";//短路与 与 
//输入输出文件名 
char Scanin[file_length],Scanout[file_length]; 
//输入输出文件指针
FILE *fin_scan,*fout_scan;

int scanTEST(char *in,char *out){
	//ch为每次读入的字符,token用于保存识别出的单词,es为错误代码 
	char ch,token[tokenMax];
	char *err[ERR_NUM];
	int  errLine[ERR_NUM];
	//错误行号 错误总数
	int rowLine=1;//注释中也可能有换行符 
	int errSum=0; 
	int es=0;
	/*
	printf("输入源文件(路径+文件名):\n"); 
	scanf("%s",Scanin);
	printf("输入目标文件(路径+文件名):\n");
	scanf("%s",Scanout);
	*/
	if((fin_scan=fopen(in,"r"))==NULL){
		fclose(fin_scan);
		printf("\n打开词法分析输入文件错误\n");
		return -1;
	}
	
	if((fout_scan=fopen(out,"w+"))==NULL){
		fclose(fout_scan);
		printf("\n创建词法分析输出文件错误\n");
		return -1;
	}
	printf("------------------\n");
	printf("词法分析开始\n");
	
	ch = getc(fin_scan);
	while(ch!=EOF){
		while(ch==' '||ch=='\n'||ch=='\t'){
			if(ch=='\n'){
				rowLine++;
			}
			ch=getc(fin_scan);
		}
		if(isalpha(ch)){//?字母			
			int i=0;
			token[i++]=ch;
			ch=getc(fin_scan);
			
			while(isalnum(ch)){//组合保留字 
				token[i++]=ch;
				ch=getc(fin_scan);
			}			
			token[i]='\0';
			
			//查保留字//折半查找//字典序 
			sort(keyword);//排序保留字表
			char low_token[tokenMax]; 
			int err=binselect(lower(token,low_token),keyword,0,keywordSum-1);
			if(err==-1){//不是保留字 
				fprintf(fout_scan,"%s\t%s\t%d\n","ID",token,rowLine);	
			}
			else{
				fprintf(fout_scan,"%s\t%s\t%d\n",token,token,rowLine);
			} 
				 
		}
		else if(isdigit(ch)){//?数字 
			//组合整数
			int i = 0;
			token[i++]=ch;			
			ch=getc(fin_scan);				
			while(isdigit(ch)){
				token[i++]=ch;
				ch=getc(fin_scan);
			}
			token[i]='\0';
			fprintf(fout_scan,"%s\t%s\t%d\n","NUM",token,rowLine);	
		}
		else if(strchr(singleword,ch)>0){//?纯单分界符 
			int i = 0;
			token[i++]=ch;			
			token[i]='\0';
			ch=getc(fin_scan);
			fprintf(fout_scan,"%s\t%s\t%d\n",token,token,rowLine);
		}
		else if(strchr(doubleword,ch)>0){//?双分界符 
			int i = 0;
			token[i++]=ch;			
			ch=getc(fin_scan);
			if(ch=='='){
				token[i++]='=';
				token[i]='\0';
				ch=getc(fin_scan);				
			}
			else{
				token[i]='\0';	
			}			
			fprintf(fout_scan,"%s\t%s\t%d\n",token,token,rowLine);
		}
		else if(strchr(doubleword_add,ch)>0){// || &&
			int i = 0;
			char before=ch; 
			token[i++]=ch;			
			ch=getc(fin_scan);
			if(before==ch){
				token[i++]=ch;
				token[i]='\0';
				ch=getc(fin_scan);
				fprintf(fout_scan,"%s\t%s\t%d\n",token,token,rowLine);		
			}
			else{
				token[i]='\0';
				err[errSum]=(char *)malloc(10*sizeof(char));
				err[errSum]=str_copy(err[errSum],token);
				errLine[errSum++]=rowLine;	
			}			
		}
		else if(ch=='/'){//注释处理 
			int i=0;
			char ch1;
			ch=getc(fin_scan);
			if(ch=='*'){
				ch1=getc(fin_scan);
				do{
					ch=ch1;
					ch1=getc(fin_scan);
					if(ch=='\n'){
						rowLine++;
					}
				}while((ch!='*' || ch1 !='/') && ch1!=EOF);
	
			}else{
				token[i++]='/';	
				token[i]='\0';
				fprintf(fout_scan,"%s\t%s\t%d\n",token,token,rowLine);
			}	
		}
		else{//错误处理 
			if(ch==EOF){
				break;
			}
			token[0]=ch;
			token[1]='\0';
			err[errSum]=(char *)malloc(10*sizeof(char));			
			err[errSum]=str_copy(err[errSum],token);
			errLine[errSum]=rowLine;
			errSum++;
			ch=getc(fin_scan); 
			es=3;						
		}			
	}
	if(errSum>0){
		printf("词法分析发现错误,错误总数%d\n",errSum);
		fprintf(fout_scan,"%s\t%d\n","ERRSUM",errSum);
		return errSum;	
	}
	printf("词法分析成功\n");	
	for(int i=0;i<errSum;i++){
		fprintf(fout_scan,"%s\t%s\t%d\n","ERROR",err[i],errLine[i]);
	}
	fclose(fin_scan);
	fclose(fout_scan);
	return es;
}
//str_cpy
char* str_copy(char *des,char *sour){
	if(sour==NULL || des==NULL){
		printf("字符串复制出错\n");
		return NULL;
	}
	char *temp=des;
	int i;
	for(i=0;sour[i]!='\0';i++){
		temp[i]=sour[i];	
	}
	temp[i]='\0';
	return temp;	
}
//字典序排列字符串
void sort(char *begin[]){
	char *temp=NULL;
	int MIN=0; 
	for(int i=0;i<keywordSum;i++){
		MIN=i;
		for(int j=i+1;j<keywordSum;j++){
			if(strcmp(begin[MIN],begin[j])>0){
				MIN=j;
			}
		}
		temp=begin[i];
		begin[i]=begin[MIN];
		begin[MIN]=temp;			
	}
}
//大写转小写
char* lower(char *temp,char *low){
	int i=0;
	while(temp[i]!='\0'){
		low[i]=tolower(temp[i]);
		i++;
	}
	low[i]='\0';
	return low;	
} 
//折半查找 :返回-1为失败 
int binselect(char *target,char **set,int low,int high){
	int mid=(low+high)/2;
	
	if(low>high){
		return -1;
	}
	
	if(strcmp(target,set[mid])>0){
		return binselect(target,set,mid+1,high);	
	}
	else if(strcmp(target,set[mid])<0){
		return binselect(target,set,low,mid-1);
	}
	else{
		return mid;
	}	 
}  

语法分析语义分析

语法规则

< program> —>{< fun_declaration>}< main_declaration>
< fun_declaration>—>function ID ‘(’[< para_list>]’)’< function_body>
< main_declaration>—>main ‘(’ ‘)’< function_body>
< para_list>—>int ID{, int ID}
< function_body>—>’{’< declaration_list>< statement_list>’}’
< declaration_list>—>{< declaration_stat>}
< declaration_stat>—>int ID < var_stat>|< arry_stat> { , ID < var_stat>|< arry_stat> }
< arry_stat>–>’[‘NUM’]’ [=’{’[NUM {,NUM} ]’}’]
< var_stat>—>[=NUM]
< statement_list>—>{< statement >}
< statement>—>< if_stat>|< while_stat>|< for_stat>|< read_stat>|< write-stat>|< compound_stat>
|< expression_stat>|< switch_stat> |< do_while>|< break_stat>|< continue>
< return_stat>—> return < expression> ;
< switch_stat>—>switch ‘(’< exprssion>’)’{’ {case NUM :< statement> < break_stat>} ‘}’
< do_while>—>do < statement> while ‘(’ < expression>’)’
< break_stat>—>break ;
< continue_stat>---->continue ;
< if_stat>—>if ‘(’< exprssion>’)’< statement>[else < statement>]
< while_stat> —>while’(’< expression>’)’< statement>
< for_stat>—>for’(’< expression> ; < expression> ; < expression >’)’< statement>
< read>—>read ID | ID ‘[’ < expression> ‘]’
< write>—>write < exprssion>
< compound_stat>—>’{’ < statement_list> ‘}’
< expression_stat>—>< expression> ;| ;
< call_stat>—>call ID ‘(’[< expression> {,< expression> }’)’
< expression>—>ID[’[’< expression>’]’]=< bool_expr> | < bool_expr>
< bool_expr>—>[!]< additive_expr>{ (>|<|>=|<=|==|!=| && | || ) < additive_expr> }
< additive_expr>—>< term>{(+|-)< term>}
< term>—>< factor>{(*|/)< factor>}
< factor>—>’(’< additive_expr>’)’|ID|NUM| ID’[’< expression>’]’| < call_stat>

原理

语法语义:递归子程序下降法
主要实现难点说明:

  1. 语法树的递归输出
  2. 符号表数据结构的设计
  3. 栈式结构的理解
  4. 栈式虚拟机指令的设计

实现

parse.h

#include<stdio.h>
#include<stdlib.h> 
#include<ctype.h>
#include<conio.h>
#include<string.h>
#include<string>
#include<vector>
#include<map>

#define SIZE 500 
#define maxCodeIndex 1000

using namespace std;

struct node{//语法树 
	string str;//节点标识 
	vector<node*> sons;//子树
	string value;//值
	
	node* addSon(string s){
		node* son = new node();
		son->str=s;
		sons.push_back(son);
		return son;
	}
	node* addSon(string k,string v){
		node* son = new node();
		son->str=k;
		son->value=v;
		sons.push_back(son);
		return son;
	} 
}*root;

struct var{//变量 
	string name;//名字 
	int address;//偏移地址 
	int len;//长度,变量为0,数组为NUM 
	
	var(){
	}
	
	var (string n,int a,int l){
		this->name = n;
		this->address = a;
		this->len = l;
	}
};
 
struct fun{
	int address;//入口地址 
	int num;//形参个数
	int len_var;//变量总长度  
	map<string, var> vars;//变量表 
	
	fun(){
	}
	
	fun(int address){
		this->address = address;
		this->num=0;//创建函数 形参初值为0 
		this->len_var=0; //创建函数 变量总长度为0
	}
};

int cx_n=0;//codeIndex 
int offset_n=0;//当前偏移地址
int main_cx=0;//记录main的BR 

struct{//中间代码 
	char operate[10];//操作符
	int operate_data;//操作数 
}codes[maxCodeIndex];
 
string fun_n;//当前function main 
string temp_id;//记录之前id

map< string , fun > fun_list;//不同函数符号表

int insert_symbol(string name,string type,int len){//插入符号表,扫描到标识符定义出现 
	int es=0;
	if(strcmp(type.c_str(),"var")==0){
		map<string,var> &vars = fun_list[fun_n].vars;
		if(vars.find(name)==vars.end())
			vars[name] = var(name, offset_n++,len);//插入变量名,地址,长度 
		else{
			return es=31;//变量重定义 
		}			
	}
	if(strcmp(type.c_str(),"function")==0){//插入 function  
		if(fun_list.find(name)==fun_list.end()){// 之前未定义则插入 
			fun_list[name] = fun(cx_n);//插入函数入口地址 
		}
		else{
			return es=32;//函数重定义
		} 
	}
	
	return es; 
} 

int lookup(string name,int *position){//查找符号表 
	int es=0;
	map<string,var> vars = fun_list[fun_n].vars;
	if(vars.find(name)!=vars.end()){ 
		*position=vars[name].address; 
	}	
	else
		return es=33;//变量未定义 
	return es;
}

int getlen(string name){
	map<string,var> vars = fun_list[fun_n].vars;
	if(vars.find(name)!=vars.end())
		return vars[name].len;
	return -1;	
}


char ScanFile[50];//词法分析结果 
char word_k[50];//单词类别 
char word_v[50];//单词本身值
char row[30];//单词行号 
char parseFile[50];//语法分析结果 

FILE *fp_word;//单词流文件指针 
FILE *fout;
FILE *mid_code;//中间代码
FILE *sym;//符号表 

//语法分析,输出语法树 
char *space="    ";// 12个空格 
char *link ="|   ";
int  L[100];//未遍历兄弟剩余个数 

int program();
int fun_declaration(node* p);
int main_declaration(node* p);
int function_body(node* p);
int declaration_list(node* p);
int declaration_stat(node* p);
int statement_list(node* p);
int statement(node* p);
int if_stat(node* p);
int while_stat(node* p);
int for_stat(node* p);
int write_stat(node* p);
int read_stat(node* p);
int compound_stat(node* p);
int expression_stat(node* p);
int call_stat(node* p);
int expression(node* p);
int bool_expr(node* p);
int additive_expr(node* p);
int term(node* p);
int factor(node* p);
int switch_stat(node *p);
int do_while(node *p);
int break_stat(node *p);
int continue_stat(node *p);
int return_stat(node *p);
void printTree(node *root,int blk);
void read_f();
int yufa(char *cifa_r,char *yufashu_r);
/*语义分析函数*/
int program_(node* p);
int fun_declaration_(node* p);
int main_declaration_(node* p);
int function_body_(node* p);
int declaration_list_(node* p);
int declaration_stat_(node* p);
int statement_list_(node* p);
int statement_(node* p);
int if_stat_(node* p);
int while_stat_(node* p);
int for_stat_(node* p);
int write_stat_(node* p);
int read_stat_(node* p);
int compound_stat_(node* p);
int expression_stat_(node* p);
int call_stat_(node* p);
int expression_(node* p);
int bool_expr_(node* p);
int additive_expr_(node* p);
int term_(node* p);
int factor_(node* p);
int switch_stat_(node *p);
int do_while_(node *p);
int return_stat_(node *p);
int break_stat_(node *p);
int continue_stat_(node *p);
void printf_s(); 
 
int parseTEST(char *cifa_r,char *yufashu_r,char *fuhaobiao_r,char *midcodes_r){
	int es = 0;
	
	if(yufa(cifa_r,yufashu_r) == -1) return -1;//生成语法树 
	
	if((sym=fopen(fuhaobiao_r,"w"))==NULL){
		fclose(sym); 
		printf("\n打开错误\n");
		return -1;
	}
	
	if((mid_code=fopen(midcodes_r,"w+"))==NULL){
		fclose(mid_code);
		printf("\n打开错误\n");	
		return -1;
	}
	
	printf("\n------------------\n");
	printf("语义分析开始\n");
	es=program_(root);//
	if(es>0){//报错
		printf("语义分析出错\n",es);
		switch(es){
			case 31:printf("变量重定义!\n");break;
			case 32:printf("函数重定义!\n");break;
			case 33:printf("变量未定义!\n");break;
			case 34:printf("数组初始化越界!\n");break;
			case 35:printf("函数未定义!\n");break;
			case 36:printf("形参设置错误!\n");break;
		}
		return -1;
	}
	else{//输出符号表,中间代码
		printf("语义分析成功\n"); 
		printf_s();
		fclose(sym);
		fclose(mid_code);
		return 0; 
	}	
}

int yufa(char *cifa_r,char *yufashu_r){
	int es=0;
	L[0]=0;//第0层不输出空位 
	if((fp_word=fopen(cifa_r,"r"))==NULL){
		fclose(fp_word);
		printf("\n打开错误\n");
		return -1;
	}
	if((fout=fopen(yufashu_r,"w"))==NULL){
		fclose(fout);
		printf("\n打开错误\n");
		return -1;
	}
	printf("\n------------------\n");
	printf("语法分析开始\n"); 
	es=program();
	fclose(fp_word);
	if(es==0){
		printf("语法分析成功\n");
		printTree(root,0);//输出语法树
		fclose(fout);
		printf("语法树输出成功\n"); 
		return 0;
	}
	printf("语法分析终止,发现语法错误!\n错误行号:%s\t",row); 
	switch(es){
		case 1:printf("expected main !\n");break;
		case 2:printf("expected function ID !\n");break;
		case 3:printf("expected ( !\n");break;
		case 4:printf("expected ) !\n");break;
		case 5:printf("expected { !\n");break;
		case 6:printf("expected } !\n");break;
		case 7:printf("expected ID !\n");break;
		case 8:printf("expected ; !\n");break;
		case 9:printf("expected ID !\n");break;
		case 10:printf("expected NUM ID !\n");break;
		case 11:printf("main() {} is not the last !\n");break;
		case 12:printf("expected case or } !\n");break;
		case 13:printf("expected NUM after case !\n");break;
		case 14:printf("expected : !\n");break;
		case 15:printf("expected while !\n");break;
		case 16:printf("expected int !\n");break;
		case 17:printf("expected ID after int !\n");break;
		case 18:printf("expected break !\n");break;
		case 19:printf("statement error !\n");break;
		case 20:printf("expected NUM ! \n");break;
		case 21:printf("expected ] ! \n");break;
	}
	return -1;
}
//非终结符结束之前需要重新读单词流 
//非终结符开始之前需要准备好单词流
//终结符在程序中加入树
//非终结符在其自身函数内加入树 
//<program--->{<fun_declaration>}<main_declaration>有分歧时需要先读一个字符进行判别 
int program(){
	int i,es=0;
	root=new node();
	root->str="<program>";
	read_f();
	while(stricmp(word_k,"function")==0){//function
		es=fun_declaration(root);
		if(es>0)	return es;	
	}
	if(stricmp(word_k,"main")){//main
		es=1;//缺少main 
		return es;
	}
	es=main_declaration(root);
	if(es>0)	return es;
	if(stricmp(word_k,"#")){//文件结束标志 
		return es=11;
	} 
	return es; 
}
//<fun_declaration>--->function ID '('[<para_list>]')'<function_body>
//<para_list>--->int ID{, int ID}
int para_list(node *p){
	int es=0;
	node *s=p->addSon("<para_list>");
	s->addSon(word_k,word_v);//int
	read_f();
	if(stricmp(word_k,"ID")){
		return es=7; //lack ID
	}
	s->addSon(word_k,word_v);
	read_f();
	while(stricmp(word_k,",")==0){
		s->addSon(word_k,word_v);
		read_f();
		if(stricmp(word_k,"int")){
			return es=16;//expect int
		}
		s->addSon(word_k,word_v);
		read_f();
		if(stricmp(word_k,"ID")){
			return es=17;//expect ID
		}
		s->addSon(word_k,word_v);
		read_f();
	}
	return es;
}
int fun_declaration(node *p){
	int es=0;
	node *s=p->addSon("<fun_declaration>");
	s->addSon(word_k,word_v);//funtion
	read_f();
	if(stricmp(word_k,"ID")){//stricmp(word_k,"ID")!=0
		es=2;//普通函数名错误
		return es; 
	}
	s->addSon(word_k,word_v);
	read_f();
	if(stricmp(word_k,"(")){
		es=3;//缺少(
		return es; 
	}
	s->addSon(word_k,word_v);
	read_f();
	/**参数**///<para_list>--->int ID{, int ID} 
	if(stricmp(word_k,"int")==0){
		es=para_list(s);
		if(es>0) return es;
	}
	if(stricmp(word_k,")")){
		es=4;//缺少) 
		return es; 
	}
	s->addSon(word_k,word_v);
	read_f();
	es=function_body(s);
	return es;
}
//<function_body>--->'{'<declaration_list><statement_list>'}'
int function_body(node *p){
	int es=0;
	node *s=p->addSon("<function_body>");
	if(stricmp(word_k,"{")){
		es=5;//缺少{
		return es; 
	}
	s->addSon(word_k,word_v);
	read_f();
	es=declaration_list(s);//
	if(es>0)	return es;
	es=statement_list(s);// 
	if(es>0)	return es;
	if(stricmp(word_k,"}")){//如果文件结束且 } 
		es=6;//缺少}
		return es; 
	}
	s->addSon(word_k,word_v);
	read_f();
	return es; 
}
//<declaration_list>--->{<declaration_stat>}
int declaration_list(node *p){
	int es=0;
	node *s=p->addSon("<declaration_list>");
	while(stricmp(word_k,"int")==0){//First集合包含INT 
		es=declaration_stat(s);

		if(es>0)    return es;	
	}
	return es;
}
//<var_stat>--->[=NUM]
int var_stat(node *p){ 
	int es=0;
	node *s=p->addSon("<var_stat>");
	s->addSon(word_k,word_v);// = 注意p 
	read_f();
	if(stricmp(word_k,"NUM")){
		return es=20;// num
	}
	s->addSon(word_k,word_v);
	read_f();
    return es;
}
//<arry_stat>-->'['NUM']' [='{'[NUM {,NUM} ]'}']
int arry(node *p){
	int es=0;
	node *s=p->addSon("<arry>");
	s->addSon(word_k,word_v);// [
	read_f();
    if(stricmp(word_k,"NUM")){
		return es=20;// num
	}
	s->addSon(word_k,word_v);
	read_f();
    if(stricmp(word_k,"]")){
    	return es=21;// ]
	}
	s->addSon(word_k,word_v);
	read_f();
    if(stricmp(word_k,"=")==0){
    	s->addSon(word_k,word_v);
		read_f();
    	if(stricmp(word_k,"{")){
    		return es=5;// {
		} 
		s->addSon(word_k,word_v);
		read_f();
	    if(stricmp(word_k,"NUM")==0){
	    	s->addSon(word_k,word_v);// NUM
			read_f();
		    //<arry_stat>-->'['NUM']' [='{'[NUM]{,NUM}'}']
		    while(stricmp(word_k,",")==0){// ,
		    	s->addSon(word_k,word_v);
				read_f();
			    if(stricmp(word_k,"NUM")){
			    	return es=20; //NUM
				}
				s->addSon(word_k,word_v);
				read_f();
			}	
		}
		if(stricmp(word_k,"}")){
    		return es=6;// }
		} 
		s->addSon(word_k,word_v);
		read_f(); 
	}
	return es;
}
//<declaration_stat>--->int ID <var_stat>|<arry_stat> { , ID <var_stat>|<arry_stat> } ;
int declaration_stat(node *p){
	int es=0;
	node *s=p->addSon("<declaration_stat>");
	s->addSon(word_k,word_v);//int
	read_f();
	if(stricmp(word_k,"ID")){
		es=7;//缺少变量名
		return es; 
	}
	s->addSon(word_k,word_v);
	read_f();
    if(stricmp(word_k,"=")==0){
		 es=var_stat(s);
		 if(es>0)	return es;   	
	}
	else if(stricmp(word_k,"[")==0){
		es=arry(s);
		if(es>0)	return es;
	}
	while(stricmp(word_k,",")==0){
		s->addSon(word_k,word_v);// ,
		read_f();
	    if(stricmp(word_k,"ID")){
	    	return es=7; //ID
		}
		s->addSon(word_k,word_v);
		read_f();
	    if(stricmp(word_k,"=")==0){// var_stat
			 es=var_stat(s);
			 if(es>0)	return es;   	
		}
		else if(stricmp(word_k,"[")==0){// arry_stat
			es=arry(s);
			if(es>0)	return es;
		}
	}
	if(stricmp(word_k,";")){
		es=8;//缺少;
		return es; 
	}
	s->addSon(word_k,word_v);
	read_f();
	return es;
}
//<statement_list>--->{<statement>}
int statement_list(node *p){
	int es=0;
	node *s=p->addSon("<statement_list>");
	while(stricmp(word_k,"}")!=0){//staement_list的First集合不包含 } 
		es=statement(s);//文件结束:返回非0值,文件未结束,返回0值
		if(es>0)    return es;
	}
	return es;
}
//statement---><if_stat>|<while_stat>|<for_stat>|<read_stat>|<write-stat>|
//				<compound_stat>|<expression_stat>|<switch_stat>
//				|<do_while>|<break_stat>|<continue>
int statement(node *p){
	int es=0;
	node *s=p->addSon("<statement>");
	if(stricmp(word_k,"if")==0 && es==0){
		es=if_stat(s);
	}
	else if(stricmp(word_k,"while")==0 && es==0){
		es=while_stat(s);
	}
	else if(stricmp(word_k,"for")==0 && es==0){
		es=for_stat(s);
	}
	else if(stricmp(word_k,"read")==0 && es==0){
		es=read_stat(s);
	}
	else if(stricmp(word_k,"write")==0 && es==0){
		es=write_stat(s);
	}
	else if(stricmp(word_k,"{")==0 && es==0){//compound_stat
		es=compound_stat(s);
	}
	else if(es==0 && (strcmp(word_k,"ID")==0||strcmp(word_k,"NUM")==0
		||strcmp(word_k,"(")==0)||strcmp(word_k,";")==0 ||strcmp(word_k,"call")==0){//expression_stat
		es=expression_stat(s);
	}
	else if(stricmp(word_k,"switch")==0 && es==0){
		es=switch_stat(s);
	}
	else if(stricmp(word_k,"do")==0 && es==0){
		es=do_while(s);
	}
	else if(stricmp(word_k,"return")==0 && es==0){
		es=return_stat(s);
	}
	else if(stricmp(word_k,"break")==0 && es==0){
		es=break_stat(s);
	}
	else if(stricmp(word_k,"continue")==0 && es==0){	
		es=continue_stat(s);
	}
	else{
		return es=19;//statement failure
	} 
	return es;
}
//<return_stat>---> return <expression> ;
int return_stat(node *p){
	int es = 0;
	node *s=p->addSon("<return_stat>");
	s->addSon(word_k,word_v);//return
	read_f();
	
	es=expression(s);
	if(es>0) return es;
	
	if(stricmp(word_k,";")){
		es=8;// ;
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	return es;
}
//<switch_stat>--->switch '(' ID ')'{' {case NUM :<stateement> <break_stat>} '}'
//<switch_stat>--->switch '('<expr>')'{' {case NUM :<stateement> <break_stat>} '}'
int switch_stat(node *p){
	int es=0;
	node *s=p->addSon("<switch_stat>");
	s->addSon(word_k,word_v);//switch
	read_f();
	if(stricmp(word_k,"(")){
		return es=3;
	}
	s->addSon(word_k,word_v);
	read_f();
	
	es=expression(s);
	if(es>0) return es;
	
	if(stricmp(word_k,")")){
		return es=4;
	}
	s->addSon(word_k,word_v);
	read_f();
	if(stricmp(word_k,"{")){
		return es=5;
	}
	s->addSon(word_k,word_v);
	read_f();
	
	while(stricmp(word_k,"case")==0){
		s->addSon(word_k,word_v);
		read_f();
		if(stricmp(word_k,"NUM")){
			return es=13;//expect case num
		}
		s->addSon(word_k,word_v);
		read_f();
		if(stricmp(word_k,":")){
			return es=14;// expect :
		}
		s->addSon(word_k,word_v);
		read_f();
		
		es=statement(s);
		if(es>0)    return es;
		if(stricmp(word_k,"break")){
			return es=18;//expect break;
		}
		es=break_stat(s);
		if(es>0)    return es;
	}
	if(stricmp(word_k,"}")){
		return es=12;
	}
	s->addSon(word_k,word_v);
	read_f();
	return es;
}
//<do_while>--->do <statement> while '(' <expression>')'
int do_while(node *p){
	int es=0;
	node *s=p->addSon("<do_while>");
	s->addSon(word_k,word_v);//do
	read_f();
	
	es=statement(s);
	if(es>0)	return es;
	if(stricmp(word_k,"while")){
		return es=15;// expect while _do
	}
	s->addSon(word_k,word_v);
	read_f();
	if(stricmp(word_k,"(")){
		return es=3;// (
	}
	s->addSon(word_k,word_v);
	read_f();
	
	es= expression(s);
	if(es>0)	return es;
	if(stricmp(word_k,")")){
		return es=4;// (
	}
	s->addSon(word_k,word_v);
	read_f();
	return es;
}
//<break_stat>--->break ;
int break_stat(node *p){
	int es=0;
	node *s=p->addSon("<break_stat>");
	s->addSon(word_k,word_v);//break;
	read_f();
	if(stricmp(word_k,";")){
		return es=8;// ;
	}
	s->addSon(word_k,word_v);
	read_f();
	return es;
}
//continue_stat>---->continue ;
int continue_stat(node *p){
	int es=0;
	node *s=p->addSon("<continue_stat>");
	s->addSon(word_k,word_v);//break;
	read_f();
	if(stricmp(word_k,";")){
		return es=8;// ;
	}
	s->addSon(word_k,word_v);
	read_f();
	return es;
}
//<if_stat>--->if '('<exprssion>')'<statement>[else <statement>]
int if_stat(node *p){
	int es=0;
	node *s=p->addSon("<if_stat>");
	s->addSon(word_k,word_v);//if
	read_f();
	if(stricmp(word_k,"(")){
		es=3;// (
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	es=expression(s);
	if(es>0)	return es;
	if(stricmp(word_k,")")){
		es=4;// )
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	es=statement(s);
	if(es>0)	return es;
	if(stricmp(word_k,"else")==0){
		s->addSon(word_k,word_v);
		read_f();
		es=statement(s);
		if(es>0)    return es; 
	}
	return es;
}
//while_stat--->while'('<expression>')'<statement>
int while_stat(node *p){
	int es=0;
	node *s=p->addSon("<while_stat>");
	s->addSon(word_k,word_v);//while
	read_f();
	if(stricmp(word_k,"(")){
		es=3;
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	es=expression(s);
	if(es>0)	return es;
	if(stricmp(word_k,")")){
		es=4;
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	es=statement(s);
	return es;	
}
//<for_stat>--->for'('<expression> ; <expression> ; <expression>')'<statement>
int for_stat(node *p){
	int es=0;
	node *s=p->addSon("<for_stat>");
	s->addSon(word_k,word_v);//for
	read_f();
	if(stricmp(word_k,"(")){
		es=3;
		return es;	
	}
	s->addSon(word_k,word_v);
	read_f();
	es=expression(s);//1
	if(es>0)	return es;
	if(stricmp(word_k,";")){
		es=8;// ;
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	
	es=expression(s);//2
	if(es>0)	return es;
	if(stricmp(word_k,";")){
		es=8;// ;
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	
	es=expression(s);//3
	if(stricmp(word_k,")")){
		es=4;// )
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	
	es=statement(s);
	
	return es;
}
//<read>--->read ID | ID '[' <expression> ']' ;
int read_stat(node *p){
	int es=0;
	node *s=p->addSon("<read_stat>");
	s->addSon(word_k,word_v);//read
	read_f();
	if(stricmp(word_k,"ID")){
		es=9;//缺少ID
		return es; 
	}
	s->addSon(word_k,word_v);
	read_f();
	if(stricmp(word_k,"[")==0){//数组 
		s->addSon(word_k,word_v);
		read_f();
		es=expression(s);
		if(es>0) return es;
		
		if(stricmp(word_k,"]")){
			return es=21;// ]
		}
		s->addSon(word_k,word_v);
		read_f(); 
	}
	 
	if(stricmp(word_k,";")){
		es=8;// ;
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	
	return es;
}
//<write>--->write <exprssion> ;
int write_stat(node *p){
	int es=0;
	node *s=p->addSon("<write_stat>");
	s->addSon(word_k,word_v);//write
	read_f();
	es = expression(s);
	if ( es>0 ) return es;
	
	if(stricmp(word_k,";")){
		es=8;// ;
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	
	return es;
}
//<compound_stat>--->'{' <statement_list> '}'
int compound_stat(node *p){
	int es=0;
	node *s=p->addSon("<compound_stat>");
	s->addSon(word_k,word_v);// {
	read_f();
	es=statement_list(s);
	if(es>0)	return es;
	if(stricmp(word_k,"}")){
		es=6 ;// }
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	
	return es;
}
// expression_stat>---><expression> ;|;
int expression_stat(node *p){
	int es=0;
	node *s=p->addSon("<expression_stat>");
	// ID NUM ( ;
	if(stricmp(word_k,";")==0){
		s->addSon(word_k,word_v);
		read_f();
		return es;
	}
	es=expression(s);
	if(es>0)	return es;
	
	if(stricmp(word_k,";")){
		es=8;
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	
	return es;
}
//<call_stat>--->call ID '('')'
//<call_stat>--->call ID '('[<expression> {,<expression> }')' 
int call_stat(node *p){
	int es=0;
	node *s=p->addSon("<call_stat>");
	s->addSon(word_k,word_v);//call
	read_f();
	if(stricmp(word_k,"ID")){
		es=9;//ID
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	if(stricmp(word_k,"(")){
		es=3;// (
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	/**参数**/
	if(stricmp(word_k,")")!=0){
		es=expression(s);
		if(es>0) return es;
		while(stricmp(word_k,",")==0){
			s->addSon(word_k,word_v);
			read_f();
			es=expression(s);
			if(es>0) return es;
		}
	}
	if(stricmp(word_k,")")){
		es=4;// )
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();	
	return es;
}
//<expression>--->ID['['<expression>']']=<bool_expr> | <bool_expr> //非LL(1)文法 
int expression(node *p){//由于First集冲突,需多读入一个字符 fseek() ftell() 
	int es=0;
	int f_now=ftell(fp_word);//目前指针位置 
	char r_temp[30],k[50],v[50];
	strcpy(r_temp,row);
	strcpy(k,word_k);
	strcpy(v,word_v); 
	node *s=p->addSon("<expression>");
	// ID NUM ( call
	if(stricmp(word_k,"call")==0){//增加函数因子 
			//printf("%s %s %s\n",word_k,word_v,row);
			es=bool_expr(s); 
			if(es>0)	return es;
			return es;
	}
	if(stricmp(word_k,"!")!=0){
		char temp_k[40];
		char temp_v[40];
		fscanf(fp_word,"%s\t%s\t%s\n",temp_k,temp_v,row);
		
		if(stricmp(temp_k,"=")==0){
			s->addSon(word_k,word_v);
			s->addSon(temp_v);
			read_f();
		}
		else if(stricmp(temp_k,"[")==0){// 数组 
			s->addSon(word_k,word_v);
			s->addSon(temp_v);
			char t_k[40],t_v[40];
			fscanf(fp_word,"%s\t%s\t%s\n",word_k,word_v,row);			
			es=expression(s);//
			if(es>0) return es;
			if(stricmp(word_k,"]")) return es=21;
			fscanf(fp_word,"%s\t%s\t%s\n",t_k,t_v,row);
			if(stricmp(t_k,"=")==0){
				s->addSon(word_k);
				s->addSon(t_v);
				read_f();	
			}
			else{
				// //删除 ID[<expression> 节点
				s->sons.erase(s->sons.begin(),s->sons.begin()+3);
				strcpy(row,r_temp);
				strcpy(word_k,k);
				strcpy(word_v,v);	
				fseek(fp_word,f_now,0);//指针回读 	
			} 
		} 
		else{
			fseek(fp_word,f_now,0);//指针回读 
		}	
	}
	es=bool_expr(s); 
	if(es>0) return es;	
}
//<bool_expr>---><additive_expr>{ (>|<|>=|<=|==|!=) <additive_expr> }
//<bool_expr>--->[!]<additive_expr>{ (>|<|>=|<=|==|!=| && | || ) <additive_expr> } 
int bool_expr(node *p){
	int es=0;
	node *s=p->addSon("<bool_expr>");
	if(stricmp(word_k,"!")==0){
		s->addSon(word_k,word_v);
		read_f();
	}
	es=additive_expr(s);
	if(es>0)	return es;
	while(stricmp(word_k,">")==0 ||stricmp(word_k,"<")==0 
		||stricmp(word_k,">=")==0 ||stricmp(word_k,"<=")==0 
			||stricmp(word_k,"==")==0 ||stricmp(word_k,"!=")==0 
				||stricmp(word_k,"||")==0 ||stricmp(word_k,"&&")==0 ){
		s->addSon(word_k,word_v);
		read_f();
		if(stricmp(word_k,"!")==0){
			s->addSon(word_k,word_v);
			read_f();
		}
		es=additive_expr(s);
		if(es>0)    return es;
	}
	return es;
}
//<additive_expr>---><term>{(+|-)<term>}
int additive_expr(node *p){
	int es=0;
	node *s=p->addSon("<additive_expr>");
	es=term(s);
	if(es>0){
		return es; 
	}
	while(stricmp(word_k,"+")==0 || stricmp(word_k,"-")==0){
		s->addSon(word_k,word_v);
		read_f();
		es=term(s);
		if(es>0)    return es;
	}
	return es;	
}
//<term>---><factor>{(*|/)<factor>}
int term(node *p){
	int es=0;
	node *s=p->addSon("<term>");
	es=factor(s);
	if(es>0)	return es;
	while(stricmp(word_k,"*")==0||stricmp(word_k,"/")==0){
		s->addSon(word_k,word_v);
		read_f();
		es=factor(s);
		if(es>0)    return es;
	}
	return es;
}
//<factor>--->'('<additive_expr>')'|ID|NUM 
//<factor>--->'('<additive_expr>')'|ID|NUM| ID'['<expression>']'| <call_stat> //一维数组 
int factor(node *p){
	int es=0;
	node *s=p->addSon("<factor>");
	if(stricmp(word_k,"(")==0){
		s->addSon(word_k,word_v);
		read_f();
		es=additive_expr(s);
		if(stricmp(word_k,")")){
			es=4;
			return es;// )
		}
		s->addSon(word_k,word_v);
		read_f();
		return es;
	}
	else if(stricmp(word_k,"call")==0){
		es=call_stat(s);
		if(es>0) return es;	
	}
	else{
		if(stricmp(word_k,"NUM")==0){
			s->addSon(word_k,word_v);
			read_f();
			return es;
		}
		else if(stricmp(word_k,"ID")==0){
			s->addSon(word_k,word_v);
			read_f();
			if(stricmp(word_k,"[")==0){//数组 
				s->addSon(word_k,word_v);
				read_f();
				
           		es=expression(s);
           		if(es>0) return es;
           		
           		if(stricmp(word_k,"]")){
           			return es=21; // ]	
				}
				s->addSon(word_k,word_v);
				read_f();
			}	
		}
		else{
			es=10;//缺少ID NUM  
			return es;
		}
	}
	return es;
}
//<main_declaration>--->main '(' ')'<function_body> 
int main_declaration(node *p){
	int es=0;
	node *s=p->addSon("<main_declaration>");
	s->addSon(word_k,word_v);//main
	read_f();
	if(stricmp(word_k,"(")){
		es=3;// (
		return es;
	}
	s->addSon(word_k,word_v);
	read_f();
	if(stricmp(word_k,")")){
		es=4;
		return es;// )
	}
	s->addSon(word_k,word_v);
	read_f();
	
	es=function_body(s);
	
	return es;
}
 
void read_f(){
    if(feof(fp_word)==0){
    	fscanf(fp_word,"%s\t%s\t%s\n",word_k,word_v,row);
    }   
    else{
    	strcpy(word_k,"#");strcpy(word_v,"#");
    }
}
 
void printTree(node *now,int blk){//flag用来标记是否是最后一个孩子 
	int size=now->sons.size();
	int i;
	if(size==0){
		for(i=0;i<blk;i++){
			if(L[i]==0){
				fprintf(fout,"%s",space);
			}
			if(L[i]>0){
				fprintf(fout,"%s",link);	
			} 
		}
		char temp[50];
		fprintf(fout,"|+ %s\n",strcpy(temp,now->str.c_str()));
		return ;
	}
	for(int j=0;j<blk;j++){
		if(L[j]==0){
			fprintf(fout,"%s",space);
		}	
		if(L[j]>0){
			fprintf(fout,"%s",link);	
		} 
	}
	char temp[50];
	fprintf(fout,"|-%s\n",strcpy(temp,now->str.c_str()));
	for(i=0;i<size;i++){
		L[blk+1]=size-i-1;
		printTree(now->sons[i],blk+1);
	}
}
//
//call ID ( <expr> ... ) 
int call_stat_(node *p){
	int es=0;
	int size=p->sons.size();//根据孩子数量判断分支 
	int i=0;
	node *temp=p->sons[i];
	//获取ID
	temp=p->sons[1];
	//查找函数 入口地址
	int entry=0; 
	if(fun_list.find(temp->value)==fun_list.end())
		return es=35;//函数未定义
	else 
		entry=fun_list[temp->value].address;
		
	if(fun_list[temp->value].num != (size-4+1)/2 )//形参个数
		return es=36;//形参设置错误 
		
	strcpy(codes[cx_n].operate,"ENTER");
	codes[cx_n++].operate_data = 2;	
	if(size>4){//<expression>
		for(int j=3;j<size;j++){
			node *temp_1=p->sons[j];
			if(temp_1->str=="<expression>"){
				es=expression_(temp_1);
				if(es>0) return es;
				//设置形参		
			} 
		}
	}
	strcpy(codes[cx_n].operate,"CALL");
	codes[cx_n++].operate_data = fun_list[temp->value].num;//形参个数 
	strcpy(codes[cx_n].operate,"ENTER");
	codes[cx_n++].operate_data=fun_list[temp->value].len_var-fun_list[temp->value].num;//局部变量个数 
	strcpy(codes[cx_n].operate,"IPJMP");
	codes[cx_n++].operate_data = entry;
	  
	return es;
}

int factor_(node *p){
	int es=0;
	int size=p->sons.size();//根据孩子数量判断分支 
	int i=0;
	node *temp=p->sons[i];
	//printf("%d %s\n",es,temp->value.c_str());
	// 孩子 个数 4 ( ID[<expr>] )  个数 3 ( (additive) )  个数 1 (ID NUM CALL) 
	if(size==3){
		temp=p->sons[++i];//<additive>
		es=additive_expr_(temp);//
		if(es>0) return es;
	}
	else if(size==4){//数组新增指令 GET 根据栈顶地址找到数,将地址变成数值 
		int start=0;//数组起始地址
		es=expression_(p->sons[2]);//<experssion>
		if(es>0) return es;
		temp=p->sons[0];//ID
		es=lookup(temp->value,&start);
		if(es>0) return es;
		strcpy(codes[cx_n].operate,"LOADI");
		codes[cx_n++].operate_data=start;
		strcpy(codes[cx_n++].operate,"ADD");
		strcpy(codes[cx_n++].operate,"GET");
	}
	else if(size==1){
		temp=p->sons[0];//
		int add=0;
		if(temp->str=="ID"){
			es=lookup(temp->value,&add);
			//printf("tempID %s\n",temp->value.c_str());
			if(es>0) return es;
			strcpy(codes[cx_n].operate,"LOAD");
			codes[cx_n++].operate_data=add;
		} 
		else if(temp->str=="NUM"){
			strcpy(codes[cx_n].operate,"LOADI");
			codes[cx_n++].operate_data=atoi(temp->value.c_str());
		}
		else if(temp->str=="<call_stat>"){
			es=call_stat_(temp);
			if(es>0) return es;	
		}
	} 
	return es;
}

int term_(node *p){
	int es=0;
	int size=p->sons.size();//根据孩子数量判断分支 
	int i=0;
	node *temp=p->sons[i];
	es=factor_(temp);
	if(es>0) return es;
	if(size>1){
		string opr;
		while(i<size-2){//
			temp=p->sons[++i];
			opr=temp->str;// * /
			temp=p->sons[++i];// FACTOR
			es=factor_(temp);
			if(es>0) return es;
			if(opr=="*")
				strcpy(codes[cx_n++].operate,"MULT");
			if(opr=="/")
				strcpy(codes[cx_n++].operate,"DIV");
		}
	}
	return es;
}

int additive_expr_(node *p){
	int es=0;
	int size=p->sons.size();//根据孩子数量判断分支 
	int i=0;
	//printf("%d\n",size);
	node *temp=p->sons[i];
	es=term_(temp);//<term>
	if(es>0) return es;
	if(size>1){
		string opr;
		while(i<size-2){//
			temp=p->sons[++i];
			opr=temp->str;// + -
			temp=p->sons[++i];// term
			es=term_(temp);
			if(es>0) return es;
			if(opr=="+")
				strcpy(codes[cx_n++].operate,"ADD");
			if(opr=="-")
				strcpy(codes[cx_n++].operate,"SUB");
		}
	}
	return es;
} 

int bool_expr_(node *p){
	int es=0;
	int size=p->sons.size();//根据孩子数量判断分支 
	int i=0;
	node *temp=p->sons[i];
	if(temp->str=="!"){// 2
		temp=p->sons[++i];//<additive>
		es=additive_expr_(temp);
		if(es>0) return es;
		strcpy(codes[cx_n++].operate,"NOT");//求反 
	}
	else{// 1
		es=additive_expr_(temp);
		if(es>0) return es;	
	}
	if(size>2){
		string opr;
		while(i<size-2){// { }
			temp=p->sons[++i];// >= <= > < || &&
			opr=temp->str;//保留运算符
			temp=p->sons[++i];
			if(temp->str=="!"){
				temp=p->sons[++i];//<additive>
				es=additive_expr_(temp);
				if(es>0) return es;
				strcpy(codes[cx_n++].operate,"NOT");//求反 
			}
			else{
				es=additive_expr_(temp);
				if(es>0) return es;	
			}
			if(opr==">")
				strcpy(codes[cx_n++].operate,"GT");//
			if(opr=="<")
				strcpy(codes[cx_n++].operate,"LES");//
			if(opr==">=")
				strcpy(codes[cx_n++].operate,"GE");//
			if(opr=="<=")
				strcpy(codes[cx_n++].operate,"LE");//
			if(opr=="==")
				strcpy(codes[cx_n++].operate,"EQ");//
			if(opr=="!=")
				strcpy(codes[cx_n++].operate,"NOTEQ");//
			if(opr=="||")
				strcpy(codes[cx_n++].operate,"OR");//
			if(opr=="&&")
				strcpy(codes[cx_n++].operate,"AND");//	
		}		
	}
	return es;
}

int expression_(node *p){//每个expression执行完毕,栈顶都有一个结果数据 
	int es=0;
	int size=p->sons.size();//根据孩子数量判断分支
	node *temp=p->sons[0]; 
	if(size==1){//bool
		es=bool_expr_(p->sons[0]);
		if(es>0) return es;	
	}
	else {
		if(size==3){//id = bool
			temp=p->sons[2];//<bool>
			//printf("%d\n",es);
			es=bool_expr_(temp);
			if(es>0) return es;
			temp=p->sons[0];// id
			int add=0;
			es=lookup(temp->value,&add);
			if(es>0) return es;
			strcpy(codes[cx_n].operate,"STO");
			codes[cx_n++].operate_data = add;
			strcpy(codes[cx_n].operate,"ENTER");
			codes[cx_n++].operate_data = 1;//栈顶向上移动一个单位 
		}
		if(size==6){//id [<expression>] = bool
			temp=p->sons[5];
			es=bool_expr_(temp);//bool
			if(es>0) return es;
			temp=p->sons[2];
			//printf("%s\n",temp->str.c_str());
			es=expression_(temp);//expr
			if(es>0) return es;
			temp=p->sons[0];//id
			int add=0;
			es=lookup(temp->value,&add);
			if(es>0) return es;
			strcpy(codes[cx_n].operate,"LOADI");
			codes[cx_n++].operate_data = add;
			strcpy(codes[cx_n++].operate,"ADD");
			strcpy(codes[cx_n++].operate,"PUT");
		}
	}
	return es;
}

int expression_stat_(node *p){
	int es=0;
	int size=p->sons.size();
	if(size==2){//<expression> ;
		es=expression_(p->sons[0]);
		if(es>0) return es;
		//清空expr
		strcpy(codes[cx_n].operate,"DOWN");
		codes[cx_n++].operate_data = 1; 
	}
	
	return es;
} 
 
int if_stat_(node *p){
	int es=0;
	int brf=0;
	int br=0; 
	int i=0;
	int size=p->sons.size();
	
	es=expression_(p->sons[2]);//<expr>
	if(es>0) return es;
	
	strcpy(codes[cx_n++].operate,"BRF");
	brf=cx_n-1;//返填 

	es=statement_(p->sons[4]);//<stat>
	if(es>0) return es;
	
	if(size==5){ //没有else 
		codes[brf].operate_data=cx_n;
	}
	else{ //有 else 
		strcpy(codes[cx_n++].operate,"BR");
		br=cx_n-1;//返填
		
		codes[brf].operate_data=cx_n;//
		es=statement_(p->sons[6]);
		if(es>0) return es;
		
		codes[br].operate_data=cx_n;// 
	}
	return es;
}

int read_stat_(node *p){// read (ID | ID [ <EX> ])  ;
	int es=0;
	int offset=0;
	int size = p->sons.size();
	
	node *temp=p->sons[1]; //ID
	
	es=lookup(temp->value,&offset);
	if(es>0) return es;
	
	if(size==3){
		strcpy(codes[cx_n++].operate,"IN");
		strcpy(codes[cx_n].operate,"STO");
		codes[cx_n++].operate_data=offset;	
	}
	else if(size==6){
		temp = p->sons[3];//<expr>
		
		strcpy(codes[cx_n++].operate,"IN");
		es=expression_(temp);
		if(es>0) return es;
		strcpy(codes[cx_n].operate,"LOADI");
		codes[cx_n++].operate_data=offset;
		strcpy(codes[cx_n++].operate,"ADD");
		strcpy(codes[cx_n++].operate,"PUT");
	} 
	
	return es;
}

int while_stat_(node *p){
	int es=0;
	node *ex=p->sons[2];
	node *s=p->sons[4];
	int cxEntry=0,brf=0;
	
	cxEntry=cx_n;
	es=expression_(ex);
	if(es>0) return es;
	strcpy(codes[cx_n++].operate,"BRF");
	brf=cx_n-1;
	
	es=statement_(s);
	if(es>0) return es;
	strcpy(codes[cx_n].operate,"BR");
	codes[cx_n++].operate_data=cxEntry;
	
	codes[brf].operate_data=cx_n;
	return es;
}

int for_stat_(node *p){
	int es=0;
	node *ex_1=p->sons[2];
	node *ex_2=p->sons[4];
	node *ex_3=p->sons[6];
	node *s=p->sons[8];
	int brf=0,cxEntry_2=0;
	
	es=expression_(ex_1);
	if(es>0) return es;
	//清除expr
	strcpy(codes[cx_n].operate,"DOWN");
	codes[cx_n++].operate_data = 1;
	 
	cxEntry_2=cx_n;///
	es=expression_(ex_2);
	if(es>0) return es;
	strcpy(codes[cx_n++].operate,"BRF");
	brf=cx_n-1;///
	
	es=statement_(s);
	if(es>0) return es;
	
	es=expression_(ex_3);
	if(es>0) return es;
	
	strcpy(codes[cx_n].operate,"DOWN");
	codes[cx_n++].operate_data = 1;
	
	strcpy(codes[cx_n].operate,"BR");
	codes[cx_n++].operate_data=cxEntry_2;
	
	codes[brf].operate_data=cx_n;
	return es;
	
}
//<switch_stat>--->switch '(' <expr> ')'{' {case NUM :<statement> <break>} '}'
int switch_stat_(node *p){
	int es=0;
	int size = p->sons.size(); // 6 // >6 
	node *temp;
	node *ex=p->sons[2];
	int br[100]; // 无条件转移
	int count=0; //记录break数量 
	
	es = expression_(ex);
	if(es>0) return es;
	
	if(size>6){//有case的情况  按顺序扫描扫描到 NUM时 处理 
		for(int i=4;i<size;i++){
			temp=p->sons[i];
			if(temp->str=="case"){
				node *num=p->sons[++i];//NUM
				i++;// :
				node *s=p->sons[++i];//statement
				node *bre=p->sons[++i];//break
				
				strcpy(codes[cx_n++].operate,"CPY");//新增指令 CPY
				strcpy(codes[cx_n].operate,"LOADI");
				codes[cx_n++].operate_data = atoi(num->value.c_str());
				strcpy(codes[cx_n++].operate,"EQ");
				strcpy(codes[cx_n++].operate,"BRF");
				int brf = cx_n-1;
				
				es=statement_(s);
				if(es>0) return es;
				
				strcpy(codes[cx_n++].operate,"BR");// 语法规则 break 
				br[count++]=cx_n-1;//反填 
				
				codes[brf].operate_data=cx_n;
			}
		}
		for(int j=0;j<count;j++){//反填 br 
			codes[br[j]].operate_data = cx_n;	
		} 
	}
	//清除<expr>
	strcpy(codes[cx_n].operate,"DOWN");// top = top - 1 
	codes[cx_n++].operate_data = 1; 
	return es;
}

int do_while_(node *p){
	int es=0;
	node *s=p->sons[1];//<stat>
	node *ex=p->sons[4];//<expr>
	
	int sEntry=cx_n;
	es=statement_(s);
	if(es>0) return es;
	
	es=expression_(ex);
	if(es>0) return es;
	
	strcpy(codes[cx_n++].operate,"NOT");
	strcpy(codes[cx_n].operate,"BRF");
	codes[cx_n++].operate_data = sEntry;
	 
	return es;
}

int write_stat_(node *p){
	int es=0;
	node *ex=p->sons[1];//<expr>
	
	es=expression_(ex);
	if(es>0) return es;
	
	strcpy(codes[cx_n++].operate,"OUT");
	 
	return es;
}

int compound_stat_(node *p){
	int es=0;
	
	es=statement_list_(p->sons[1]);//
	if(es>0) return es;
	
	return es;
}

int main_declaration_(node *p){
	int es=0;
	
	codes[main_cx].operate_data = cx_n;//反填 
	
	fun_n="main";
	strcpy(codes[cx_n].operate,"ENTER");
	codes[cx_n++].operate_data = 2; // enter
	
	es=insert_symbol(fun_n,"function",1);//插入函数符号表  
	if(es>0) return es;	 

	es=function_body_(p->sons[3]);//
	if(es>0) return es;
	
	return es;
}

int return_stat_(node *p){
	int es = 0;
	
	es=expression_(p->sons[1]);//<expr>
	if(es>0) return es;//此处不需要清空<expr> 
	
	strcpy(codes[cx_n].operate,"RETURN");
	codes[cx_n++].operate_data = 1; //主动return 
	
	return es;	
}

int statement_(node *p){
	int es=0; 
	int size=p->sons.size();
	for(int i=0;i<size;i++){
		node *temp = p -> sons[i];
		if(temp->str=="<if_stat>"){
			es=if_stat_(temp);
			if(es>0) return es; 
		}
		else if(temp->str=="<while_stat>"){
			es=while_stat_(temp);
			if(es>0) return es;
		}
		else if(temp->str=="<return_stat>"){
			//printf("retu\n");
			es=return_stat_(temp);
			if(es>0) return es;
		}
		else if(temp->str=="<for_stat>"){
			es=for_stat_(temp);
			if(es>0) return es;
		}
		else if(temp->str=="<do_while>"){
			es=do_while_(temp);
			if(es>0) return es;
		}
		else if(temp->str=="<switch_stat>"){
			es=switch_stat_(temp);
			if(es>0) return es;
		}
		else if(temp->str=="<read_stat>"){
			es=read_stat_(temp);
			if(es>0) return es;
		}
		else if(temp->str=="<write_stat>"){
			es=write_stat_(temp);
			if(es>0) return es;
		}
		else if(temp->str=="<compound_stat>"){
			es=compound_stat_(temp);
			if(es>0) return es;
		}
		else if(temp->str=="<expression_stat>"){
			//printf("expr\n");
			es=expression_stat_(temp);
			if(es>0) return es;
		}
	}
	return es;
}

int statement_list_(node *p){
	int es=0; 
	int size=p->sons.size();
	//printf("%d\n",size);
	for(int i=0;i<size;i++){
		node *temp = p -> sons[i];
		if(temp->str=="<statement>"){
			//printf("%d\n",size);
			es=statement_(temp);
			if(es>0) return es;
		}
	}
	return es;
}
 
int arry_(node *p){
	int es=0;
	int count=0;//计数NUM出现次数 
	int offset=0;//数组首地址
	int len=0; 
	int size=p->sons.size();
	for(int i=0;i<size;i++){
		node *temp = p -> sons[i];
		if(temp->str=="NUM"){
			count++;
			if(count==1){
				//es=insert_symbol(temp_id,"var",atoi(temp->value.c_str()));//
				fun_list[fun_n].vars[temp_id].len=atoi(temp->value.c_str());// 数组长度 
				lookup(temp_id,&offset);//获取数组首地址
				len = atoi(temp->value.c_str());// 数组长度
				if(fun_n=="main"){
					strcpy(codes[cx_n].operate,"ENTER");
					codes[cx_n++].operate_data = len - 1; // enter	
				}
				offset_n=offset_n + atoi(temp->value.c_str()) - 1;// 数组 
				if(es>0) return es;	
			}
			else{	
				//count - 2
				if(count-1>len) return es=34;//数组初始化越界 
				strcpy(codes[cx_n].operate,"LOADI");
				codes[cx_n++].operate_data=atoi(temp->value.c_str());//操作数
				strcpy(codes[cx_n].operate,"STO");
				codes[cx_n++].operate_data = offset+count-2; 
				if(es>0) return es;
			}
		} 
	}
	return es; 
}

int var_stat_(node *p){
	int es=0; 
	int size=p->sons.size();
	for(int i=0;i<size;i++){
		node *temp = p -> sons[i];
		if(temp->str=="NUM"){
			strcpy(codes[cx_n].operate,"LOADI");
			codes[cx_n++].operate_data=atoi(temp->value.c_str());//操作数
			strcpy(codes[cx_n].operate,"STO");
			es=lookup(temp_id, &codes[cx_n++].operate_data);//temp_id 为上次存储 id_name 
			if(es>0) return es;
		}
	}
	return es;
}

int declaration_stat_(node *p){
	int es=0; 
	int size=p->sons.size();
	for(int i=0;i<size;i++){
		node *temp = p -> sons[i];
		if(temp->str=="ID"){
			temp_id=temp->value;//变量名保存
			if(fun_n=="main"){
				strcpy(codes[cx_n].operate,"ENTER");
				codes[cx_n++].operate_data = 1; // enter
			}
			
			es=insert_symbol(temp_id,"var",1);// 
			if(es>0) return es;		 
		} 
		else if(temp->str=="<var_stat>"){
			es=var_stat_(temp);
			if(es>0) return es;
		}
		else if(temp->str=="<arry>"){
			es=arry_(temp);
			if(es>0) return es;
		}
	}
	return es;
}

int declaration_list_(node *p){
	int es=0;
	int size=p->sons.size();
	for(int i=0;i<size;i++){
		node *temp = p -> sons[i];
		if(temp->str=="<declaration_stat>"){
			es=declaration_stat_(temp);
			if(es>0) return es;
		}
	}
	//此时变量和形参个数已经确定下来
	fun_list[fun_n].len_var = offset_n;//记录形参加局部变量个数
	 
	return es;
}

int function_body_(node *p){
	int es=0;
	int size=p->sons.size();
	for(int i=0;i<size;i++){
		node *temp = p -> sons[i];
		if(temp->str=="<declaration_list>"){
			es=declaration_list_(temp);
			if(es>0) return es;	
		}
		else if(temp->str=="<statement_list>"){
			es=statement_list_(temp);
			if(es>0) return es;
		}
	}
	//函数返回 return 0
	strcpy(codes[cx_n].operate,"RETURN"); //主动return 操作数设为 1 ,默认return 操作数为0 
	codes[cx_n++].operate_data = 0;//默认函数表达式返回 0
	 
	return es;
}
 
int para_list_(node *p){
	int es=0;
	int count=0;//记录形参个数 
	int size=p->sons.size();
	for(int i=0;i<size;i++){
		node *temp = p -> sons[i];
		if(temp->str=="ID"){//插入符号表
			count++; 
			es=insert_symbol(temp->value,"var",1);//插入符号表 
			if(es>0) return es;
		}
	}
	fun_list[fun_n].num=count;//设置形参个数 
	return es;
}

int fun_declaration_(node *p){
	int es=0;
	int size=p->sons.size();
	for(int i=0;i<size;i++){
		node *temp = p -> sons[i];
		if(temp->str == "ID"){//函数名
			//printf("%s\n",temp->value.c_str()); 
			fun_n = temp->value;//当前函数名
			//printf("%d\n",cx_n);  
			es=insert_symbol(fun_n,"function",1);//插入函数符号表  
			if(es>0) return es;
		}
		else if(temp->str=="<para_list>"){
			es=para_list_(temp);
			if(es>0) return es;
		}
		else if(temp->str=="<function_body>"){
			es= function_body_(temp);
			if(es>0) return es;
		} 
	}
	return es;
}

int program_(node *p){
	int es=0;
	int size=p->sons.size();
	main_cx=cx_n;//记录 main 
	strcpy(codes[cx_n++].operate,"BR");//操作数等待返填 
	
	for(int i=0;i<size;i++){//遍历孩子
		node *temp = p -> sons[i]; 
		if(temp->str=="<fun_declaration>"){
			offset_n = 0;//每次进入 新函数 置0 
			es = fun_declaration_(temp);
			if (es > 0) return es;
		}
		else if(temp->str=="<main_declaration>"){
			offset_n = 0;//每次进入 新函数 置0
			es = main_declaration_(temp);
			if (es > 0) return es;
		} 
	}
	return es;
}

void printf_s(){
	map< string , fun > ::iterator iter;
	iter=fun_list.begin();	
	while(iter != fun_list.end()) {
	    string name_f = iter->first;
		fun _f = iter->second;
		fprintf(sym,"=======================================\n");
		fprintf(sym,"函数名\t函数地址\t函数总长\t函数形参数\n");
		fprintf(sym,"%s\t%d\t%d\t%d\n",name_f.c_str(),_f.address,_f.len_var,_f.num);
		fprintf(sym,"-----------------------------------------------------------------\n");
		
		map<string, var> _vars = _f.vars;
		map<string, var> ::iterator it;
		it=_vars.begin();
		fprintf(sym,"变量名\t变量地址\t变量长度\n");
		while(it != _vars.end()){
			string name_v = it->first;
			var _v = it->second;
			fprintf(sym,"%s\t%d\t%d\n",name_v.c_str(),_v.address,_v.len);
			it++;
		}
		fprintf(sym,"=======================================\n");
        iter++;
	}
	    //输出code数组 
 	for(int i=0;i<cx_n;i++){
		fprintf(mid_code,"%s\t%d\n",codes[i].operate,codes[i].operate_data);
	} 
}

栈式虚拟机

虚拟机指令

见实现

原理

栈式动态内存分配
在这里插入图片描述

实现

#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string>
#include<string.h>
#include<map>

using namespace std;

map<string,int> Map;
typedef struct Code{
	char opt[10];
	int operand;
}Code;

enum e_opt{
	LOAD,LOADI,STO,ADD,SUB,MULT,DIV,BR,BRF,EQ,NOTEQ,GT,LES,GE,LE,AND,OR,NOT,IN,OUT,
	ENTER,RETURN,CALL,
	IPJMP,CPY,GET,PUT,DOWN
};

void init(){
	Map["LOAD"] = LOAD;
	Map["LOADI"] = LOADI;
	Map["STO"] = STO;
	Map["ADD"] = ADD;
	Map["SUB"] = SUB;
	Map["MULT"] = MULT;
	Map["DIV"] = DIV;
	Map["BR"] = BR;
	Map["BRF"] = BRF;
	Map["EQ"] = EQ;
	Map["NOTEQ"] = NOTEQ;
	Map["GT"] = GT;
	Map["LES"] = LES;
	Map["GE"] = GE;
	Map["LE"] = LE;
	Map["AND"] = AND;
	Map["OR"] = OR;
	Map["NOT"] = NOT;
	Map["IN"] = IN;
	Map["OUT"] = OUT;
	Map["ENTER"] = ENTER;
	Map["RETURN"] = RETURN;
	Map["CALL"] = CALL;
	Map["IPJMP"] = IPJMP;
	Map["CPY"] = CPY;
	Map["GET"] = GET;
	Map["PUT"] = PUT;
	Map["DOWN"] = DOWN;
}
int runTEST(char *midcodes_r,char *stack_r){
	int es = 0;
	int numcodes=0;
	Code c[1000];
	FILE *fin_m;
	FILE *fout_m;
	Code instruction;
	init();
	
	if((fin_m=fopen(midcodes_r,"r"))==NULL){
		fclose(fin_m);
		printf("\n打开错误\n");
		return -1;
	}
	
	if((fout_m=fopen(stack_r,"w"))==NULL){
		fclose(fout_m);
		printf("\n打开错误\n");
		return -1;
	}
	printf("\n------------------\n");
	printf("虚拟机开始\n");
	while(feof(fin_m)==0){
		char temp[10];
		fscanf(fin_m,"%s\t%s\n",c[numcodes++].opt,temp);
		c[numcodes-1].operand = atoi(temp);
		//printf("count:%d |%s|%d\n",numcodes-1,c[numcodes-1].opt,c[numcodes-1].operand);
	}
	
	int stack[150],top=0,base=0,ip=0;
	for(int i=0;i<150;i++){
		stack[i] = 0;
	}
	stack[0]=0;
	stack[1]=0;
	
	
	do{
		instruction = c[ip];
		char str[10];
		int n=c[ip].operand;
		strcpy(str,c[ip].opt);
		
		ip++;
		switch(Map[instruction.opt]){
			case LOAD:{
				stack[top++]=stack[base+2+instruction.operand];
				break;
			}
			case LOADI:{
				stack[top++]=instruction.operand;
				break;
			}
			case STO:{
				stack[base+2+instruction.operand]=stack[--top];
				break;
			}
			case ADD:{
				top--;
				stack[top-1]=stack[top-1]+stack[top];
				break;
			}
			case SUB:{
				top--;
				stack[top-1]=stack[top-1]-stack[top];
				break;
			}
			case MULT:{
				top--;
				stack[top-1]=stack[top-1]*stack[top];
				break;
			}
			case DIV:{
				top--;
				stack[top-1]=stack[top-1]/stack[top];
				break;
			}
			case BR:{
				ip=instruction.operand;
				break;
			}
			case BRF:{
				top--;
				if(stack[top]==0)
					ip=instruction.operand;
				break;
			}
			case EQ:{
				top--;
				stack[top-1]=(stack[top-1]==stack[top]);
				break;
			}
			case NOTEQ:{
				top--;
				stack[top-1]=(stack[top-1]!=stack[top]);
				break;
			}
			case GT:{
				top--;
				stack[top-1]=(stack[top-1]>stack[top]);
				break;
			}
			case LES:{
				top--;
				stack[top-1]=(stack[top-1]<stack[top]);
				break;
			}
			case GE:{
				top--;
				stack[top-1]=(stack[top-1]>=stack[top]);
				break;
			}
			case LE:{
				top--;
				stack[top-1]=(stack[top-1]<=stack[top]);
				break;
			}
			case AND:{
				top--;
				stack[top-1]=(stack[top-1] && stack[top]);
				break;
			}
			case OR:{
				top--;
				stack[top-1]=(stack[top-1]||stack[top]);
				break;
			}
			case NOT:{
				stack[top-1]= !stack[top-1];
				break;
			}
			case IN:{
				printf("输入数据\n");
				scanf("%d",&stack[top++]);
				break;
			}
			case OUT:{
				printf("程序输出:%d\n",stack[--top]);
				break;
			}
			case ENTER:{
				top = top + instruction.operand;
				break;
			}
			case RETURN:{//函数返回指令 函数可以作为表达式 
				if(instruction.operand==0){//默认return 
					top=base;
					ip=stack[top+1];
					base = stack[top];
					stack[top++] = 0;
				}
				if(instruction.operand==1){
					int temp = stack[top-1];
					top=base;
					ip=stack[top+1];
					base = stack[top];
					stack[top++] = temp;
				}	
				break;
			}
			case CALL:{ //函数调用指令 
				stack[top-2-instruction.operand]=base;
				base=top-2-instruction.operand; 
				break;
			}
			case GET:{//将栈顶(地址)换成地址对应局部变量数据 
				stack[top-1]=stack[stack[top-1]+base+2];
				break;
			}
			case IPJMP:{//IP跳转 
				stack[base+1]=ip; 
				ip=instruction.operand;
				break;
			}
			case PUT:{//取 次栈顶数据 放入 栈顶(地址)对应的空间里 
				top--;
				stack[stack[top]+base+2]=stack[top-1];
				break;
			}
			case CPY:{//复制栈顶元素 
				stack[top]=stack[top-1];
				top++;
				break;
			}
			case DOWN:{//清除栈顶元素 
				top = top - instruction.operand;
				break;
			} 
		}
		fprintf(fout_m,"#%s\t%d#",str,n);
		for(int i=0;i<=top;i++){
			fprintf(fout_m,"\t|%d|",stack[i]);
		}
		fprintf(fout_m,"\n");		
	}while(ip != 0);
	
	fclose(fin_m);
	fclose(fout_m);
	printf("虚拟机结束\n");
	return es;
} 

MAIN

踩过的坑:文件流打开后,不用时一定要关闭文件流

#include "scan.h"
#include "parse.h"
#include "mashine.h"

char *WORK_PATH[6] = {	"C:\\Users\\Desktop\\compile_results\\source_3.txt",//源文件
						"C:\\Users\\Desktop\\compile_results\\word_3.txt",//词法分析结果 
						"C:\\Users\\Desktop\\compile_results\\result_3.txt",//语法树结果
						"C:\\Users\\Desktop\\compile_results\\symbol_3.txt",//符号表结果
						"C:\\Users\\Desktop\\compile_results\\codes_3.txt",//中间代码结果
						"C:\\Users\\Desktop\\compile_results\\stack_3.txt"//虚拟机栈运行结果
					 }; 

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

void printTEST(){
	printf("\t\t*******************************************\n"); 
	printf("\t\t\t\tTEST_Compiler\n");
	printf("\t\t*******************************************\n"); 
}

int main(int argc, char** argv) {
	printTEST();
	
	if(scanTEST(WORK_PATH[0],WORK_PATH[1]) != -1){//源文件	词法分析结果
		if(parseTEST(WORK_PATH[1],WORK_PATH[2],WORK_PATH[3],WORK_PATH[4]) != -1){//词法分析结果	语法树结果	符号表结果	中间代码结果 
			return runTEST(WORK_PATH[4],WORK_PATH[5]);//中间代码结果	虚拟机栈运行结果
		}
	}
		 
	return -1;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值