编译原理 递归下降语法分析程序

老师要求做的一个课设,但是。网上很多都不是递归下降的。

在理解编译原理基本思想的基础上,选择一个自己熟悉的程序设计语言,完成编译程序的设计和实现过程。

编译程序的设计可以采用自顶向下和自底向上两种不同的方法。由于许多高级语言(如PASCAL,C)中的语法成分都是递归定义的,所以本实验要求学生采用递归下降分析技术,这是一种自顶向下的的编译方法,其基本思想是对语言的每个(或若干个)语法成分编制一个处理子程序,从处理<程序>这个语法成分的子程序开始,在分析过程中调用一系列过程或函数,对源程序进行语法和语义分析,直到整个源程序处理完毕为止。

本上机实习是为C语言(子集)设计一个编译程序,完成词法分析、语法分析、语义分析等功能,并生成某种机器上的目标代码(汇编语言)或中间代码(四元式)。

这是老师的要求

2、C语言小子集的文法规则:

<程序>::=main(){<分程序>}

       <分程序>::=<变量说明部分>;<语句部分>

       <变量说明部分>::=<变量说明><标识符表>

<变量说明>::=int

<标识符表>::=<标识符表>,<标识符>

<标识符表>::=<标识符>

       <标识符>::=<字母>

<标识符>::=<标识符><字母>

<标识符>::=<标识符><数字>

       <语句部分>::=<语句部分><语句>;|<语句>;

<语句>::=<赋值语句>|<条件语句>|<循环语句>|

<赋值语句>::=<标识符>=<表达式>

       <条件>::=<表达式><关系运算符><表达式>

       <表达式>::=<项>|<表达式><加法运算符><项>

<项>::=<因子>|<项><乘法运算符><因子>

<因子>::=<标识符>|<常量>|(<表达式>)

<常量>::=<无符号整数>

<无符号整数>::=<数字序列>

<数字序列>::=<数字序列><数字>

<数字序列>::=<数字>

<加法运算符>::=+|-

<乘法运算符>::=*|/

<关系运算符>::=<|>|!=|>=|<=|==

<复合语句>::={<语句部分>}

<语句1>::=<语句>|<复合语句>

<条件语句>::=if(<条件>)<语句1>else<语句1>

<循环语句>::=while(<条件>)do<语句1>

<字母>::=a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z

<数字>::=0|1|2|3|4|5|6|7|8|9

输入源程序样本:(这只是一个例子,调试时可以任意修改或换其它程序)

main ()
{ int a,x,b,y,max;
a=10;  b=12;
while  (a<0) 
{ b=a+b*a;
a=a-1
};
x=a+b;  y=b+b;
if  (x>y)  max=x;
else max=y;
}

下面直接给代码(代码有点长,700行左右)

#include<stdio.h>
#include<sstream>
#include<iostream>
#include<stdlib.h>
#include<fstream>
#include<string.h>
#include<math.h>
#include<cstring>
#include <vector>
#include<iomanip>

using namespace std;
char const *keyword[7] = { "if", "else", "for", "while", "do", "int", "main"}; //关键字

class Word           //单词表类 
{ 
	public:
	char value[20];//单词自身的值 
	int type;//单词的种别(10标识符,20常数,30关键字,4-运算符(加法运算符为41,乘法为42,关系运算符43),50界符) 
	int line;//行号
};

class Genq  //四元式 
{
	public:
	string op;  //算符 
	string data1;//操作数1 
	string data2;//操作数2 
	string res; //结果 
};
 
FILE *fin,*fout;//文件流 
int line=1;	//单词所在行数 
char buff[10];//存放单词的数组 
int flag=0;//词法分析判断是否已经从文件流中获取字符 
Word new_w;
Genq four[100];//用数组表示类对象四元式 

int f_num=0;//四元式个数
int e;//错误次数 
char ch;//字符流中获取的字符 
int flag1,flag2=0;
string ys[100];//已经声明的变量 
int y_num=0;//已经声明变量的个数 
string op;  //算符 
string str1;//操作数1 
string str2;//操作数2 
string result; //结果
int f=0; //表达式中运算符的个数 
int aaa;  
int tj_x;//记录while和if条件的四元式的序号 
string a[200];
string a2;
string a3;
int a_num=1;

void P();//程序
int A(); //(){分程序}
void B();//分程序
void C();//变量说明部分
int F();//标识符表
int F1();//标识符
void D();//语句部分
int D1();//子语句部分
int H();//语句
int I();//赋值语句
int Q();//表达式
int X();//项 
int X1();//子项
int Q1(); //子表达式
int Y();//因子 
int J();//条件语句 
void K();//循环语句
int H1();//语句1
int TJ();//条件

void makeFour(string op,string d1,string d2,string r)//构造四元式 
{	
	four[f_num].op=op;
	four[f_num].data1=d1;
	four[f_num].data2=d2;
	four[f_num].res=r;
	f_num++;
}
void printFour()//输出四元式 
{
	ofstream out("ygro.txt");
    int i;
    for(i=0;i<f_num;i++)
   {
   	  cout<<i<<":\t("<<four[i].op<<",\t"<<four[i].data1<<",\t"<<four[i].data2<<",\t"<<four[i].res<<")"<<endl;
   	  
   	  out<<i<<":\t("<<four[i].op<<",\t"<<four[i].data1<<",\t"<<four[i].data2<<",\t"<<four[i].res<<")"<<endl;
   }
}
void error(char doc[])//报错,定位到错误行 
{
        cout<<"第"<<new_w.line<<"行出错!\t";
		cout<<doc<<"\n";
		e++;
}
void ise(string a)  //检查变量是否被声明
{
	int i;
    for(i=1;i<=y_num;i++)
    {
    	if(a.compare(ys[i])==0)
		{
			break;
		}
	}
	if(i>y_num)  
	{
		cout<<"第 "<<new_w.line<<" 行出错!\t";
		cout<<new_w.value<<" 没有被声明 !"<<endl;
		e++;
	}
}
int getWord()//词法分析 
{
	int i=0; //buff当前字符的位置 
	int j=0; //new_w当前字符的位置 
	if(flag==0)
	{
		ch=getc(fin);
	}
	while(ch==' '||ch=='\n'||ch=='\t')//识别空格,换行,和tab
	{
		if(ch=='\n')
		{	 
			line++;//行+1 
		}
		ch=getc(fin);
		flag=1;
	} 
	if(ch>='a'&&ch<='z')//识别字母开头的变量或者单词; 
	{
		for(i=0;i<10;i++)
		{
			buff[i]=NULL;
		}i=0;
	
		do{
			buff[i++]=ch;  //吧字符流中的字符放到buff中 
			ch=getc(fin);
			flag=1;
		}while((ch>='a' && ch<='z') || (ch>='0' && ch<='9')); 
		strcpy(new_w.value,buff);//把buff的值放到单词表 
		new_w.line=line;//行数 
		int n;
		for(n=0;n<7;n++)
		{
			if(strcmp(new_w.value,keyword[n])==0)//判断是不是关键字 
			break;
		}
		if(n<7)//是关键字 
		{
			new_w.type=30;//关键字类型为03 
		}else{
			new_w.type=10;//标识符类型为01 
		}
	return 0;
	}
	else if(ch>='0' && ch<='9')
	{
		for(i=0;i<10;i++)
		{
			buff[i]=NULL;
		}i=0;
		do{
			buff[i++]=ch;
			ch=getc(fin);
			flag=1;	
		}while(ch>='0' && ch<='9');
		strcpy(new_w.value,buff);
		new_w.type=20;//数字类型为02 
		new_w.line=line;
		
		//***************************
	//	cout<<new_w.value;
	return 0;
	}
	else if(ch=='+' || ch=='-')
	{	
		for(i=0;i<10;i++)
		{
			buff[i]=NULL;
		}i=0;
		buff[i++]=ch;
		ch=getc(fin);
		flag=1;	
		strcpy(new_w.value,buff);
		new_w.type=41;	//加法运算符 
		new_w.line=line;
		
		//**************************
	//	cout<<new_w.value;
	return 0;
	}
	else if(ch=='*'||ch=='/')
	{
		for(i=0;i<10;i++)
		{
			buff[i]=NULL;
		}i=0;
		buff[i++]=ch;
		ch=getc(fin);
		flag=1;	
		strcpy(new_w.value,buff);
		new_w.type=42;	//乘法运算符 
		new_w.line=line;
		
		//**************************
	//	cout<<new_w.value;
	return 0;
	}
	else if(ch=='='||ch=='<'||ch=='>'||ch=='!')
	{	
		for(i=0;i<10;i++)
		{
			buff[i]=NULL;
		}
		i=0;
		buff[i++]=ch;
		ch=getc(fin);
		flag=1;	
		if(ch=='=')
		{
			buff[i++]=ch;
			ch=getc(fin);
			flag=1;	
		}
		strcpy(new_w.value,buff);
		new_w.type=43;	//关系运算符 
		new_w.line=line;
		
		//**************************
	//	cout<<new_w.value;
	return 0;
	}
	else if(ch==','||ch==';'||ch=='('||ch==')'||ch=='{'||ch=='}')
	{
	   	for(i=0;i<10;i++)
		{
			buff[i]=NULL;
		}
		i=0;
	   	buff[i++]=ch;
	   	strcpy(new_w.value,buff);
	   	new_w.type=50;//界符 
	   	ch=getc(fin);
	   	flag=1;	
	   	//**************************
	   	//cout<<new_w.value;
	   	return 0;
	}
	else
	{
	   	new_w.type=00;//错误的单词类型 
	   	strcat(new_w.value," ");
	   	//*************************
	   	//cout<<new_w.value;
		return 0;
	}
}

void P()//程序 
{
	getWord();//main
	if(strcmp(new_w.value,"main"))//当new_w.value不等于main满足条件 
	{
		error("缺少main"); 
	}
	getWord();//(
	A();
}
int A() //(){分程序}
{
	if(strcmp(new_w.value,"("))
	{ error("缺少'('");}
		getWord();//)
	if(strcmp(new_w.value,")"))
	{ error("缺少')'");}
		getWord();//{
	if(strcmp(new_w.value,"{"))
	{ error("缺少'{'");}
		getWord();//int
		B();
		//getWord();
	if(strcmp(new_w.value,"} "))
	{ error("缺少'}'");}
	op="go";
	str1="";
	str2="";
	result="";
	makeFour(op,str1,str2,result); 
	cout<<"语法检查完成,共发现"<<e<<"个错误。"<<endl;	
	return 0;
}
void B()//分程序
{
	C();
	
	if(strcmp(new_w.value,";"))
	{ error("缺少';'");}
	getWord();//a=10;中的a
	D();
}
void C()//变量说明部分 
{
	if(strcmp(new_w.value,"int"))
	{ error("缺少'int'");}
		getWord();//a
		ys[++y_num]=new_w.value;
		F();
}
int F()//标识符表 
{
	if(new_w.type==10)
	{
		getWord();
	}
	F1();//标识符表,标识符 
	return 0;
}
int F1()//标识符 
{
	if(strcmp(new_w.value,";")==0)
	{
		return 0;
	}
	if(strcmp(new_w.value,","))
	{error("标识符错误");}
		getWord();//b
		ys[++y_num]=new_w.value;
	if(new_w.type!=10)
	{error("标识符错误");}
		getWord();
		F1();
	return 0;
} 
//***********************************
void D()//语句部分 
{
	H();//语句 
	D1();//子语句部分
}
int D1()//子语句部分
{	
	if(strcmp(new_w.value,"}")==0)
	{
		getWord();
		if(strcmp(new_w.value,";")==0)
		{
			return 0;
		}
		else{
			H();
	 		D1();
			return 0;
		}	
	}
	if(strcmp(new_w.value,";")==0)
	{
	 	getWord();
	 	H();
	 	D1();
	}//else error("语句错误"); 
	 return 0;
}
int H()//语句 
{/*
	for(int i=0;i<100;i++)
	{
		strcpy(b[i].bds,"???");
	}
	int b_num=0;*/
	if(new_w.type==10)//如果当前符号为标识符,则为赋值语句 
	{	
		f=0; //运算符的个数 		
		flag2=0;
		
		ise(new_w.value);//判断标识符是否定义 
		result=new_w.value;
		//strcpy(b[b_num++].bds,new_w.value);//吧等号左边的值存入数组 
		getWord();
		op=new_w.value;//op="="
	//	strcpy(b[b_num++].bds,new_w.value);
		a[a_num++]=new_w.value;//=号 
		I();//赋值语句
		makeFour(op,str1,str2,result);
		return 0; 
	}
	 else if(strcmp(new_w.value,"if")==0)//判断是否为条件语句 
	 {
	 	flag2=0;
	 	getWord();
		J();//条件语句 
		return 0; 
	 }
	 else if(strcmp(new_w.value,"while")==0)//判断为循环语句 
	 {
		aaa=f_num;
	 	flag2=1;
	 	getWord();
		K();//循环语句
		op="go";
		str1="";
		str2="";
		stringstream ss;
    	ss<<aaa;
    	ss>>result;
    	makeFour(op,str1,str2,result);
    	//修改while跳转到的序号 
    	stringstream ws;
    	ws<<f_num;
    	ws>>four[tj_x].res;
		return 0; 
	 }
	 else if(strcmp(new_w.value,";")==0)
	 {
		return 0;
	 }
	 return 0;
}
int I()//赋值语句
{
	if(strcmp(new_w.value,"="))
	{error("缺乏'='");}
	getWord();
	str1=new_w.value;//str1=a  a+b*a中的a 
	//strcpy(b[b_num++].bds,new_w.value); 
	Q();//表达式
	return 0;
}
int Q()//表达式
{
	X();//项
	Q1();//子表达式 
	return 0;
} 
int X()//项 
{
	Y();//因子 
	X1();//子项 
	return 0;
}
int X1()//子项 
{
	flag1=0;
	if(strcmp(new_w.value,";")==0 || new_w.type==43||strcmp(new_w.value,")")==0)//当下一个字符为;或者关系运算符时,表达式结束 
	{
		return 0;
	}
	else if(new_w.type!=41&&new_w.type!=42&&new_w.type!=43&&strcmp(new_w.value,",")!=0 )
	{
		flag1=1;
		error("缺少';'");
		return 0;
	}
	if(new_w.type==41||new_w.type==42)//加法.乘法运算符 
	{
		
		f++;//运算符加一 
		if(f>1)
		{
			str1=str2;
			result="temp"+f;
		}
		op=new_w.value;
	}
	getWord();
	//strcpy(b[b_num++].bds,new_w.value);
	Y();
	return 0;
}
int Q1() //子表达式 
{
	if(strcmp(new_w.value,";")==0 || new_w.type==43||strcmp(new_w.value,")")==0)//当下一个字符为;或者关系运算符时,表达式结束
	{
		return 0;
	} 
	else if(new_w.type!=41&&new_w.type!=42&&new_w.type!=43&&strcmp(new_w.value,",")!=0)
	{
		if(flag1==0){
			error("缺少';'");
		}
		return 0;
	}
	if(new_w.type==41||new_w.type==42)//加法.乘法运算符 
	{
		
		f++;//运算符加一 
		if(f>1)
		{
			str1=str2;
			result="temp";
		}
		op=new_w.value;
	}
	getWord();
	//strcpy(b[b_num++].bds,new_w.value);
	X();
	return 0;
}
int Y()//因子 
{
	if(new_w.type!=10 && new_w.type!=20 && strcmp(new_w.value,"("))
	{
		error("表达式错误!!!!");
		return 0;
	}
	if(new_w.type==10||new_w.type== 20)//标识符和数字 
	{	
		if(op.compare("+")==0 || op.compare("-")==0 || op.compare("*")==0 || op.compare("/")==0)
		{
			str2=new_w.value;
			if(result=="temp")
			{
				makeFour(op,str1,str2,result);
				str2="temp";
				result="b";
				str1="a";//***************
				op="+";//*********************
			}
		}
		if(new_w.type==10)
		{
			ise(new_w.value);
		}
		getWord();//a-1 zhong de - 
	//	strcpy(b[b_num++].bds,new_w.value);
		a[a_num++]=new_w.value;

		return 0;
	}
	else if(strcmp(new_w.value,"(")==0)
	{
		getWord();
		Q();
		if(strcmp(new_w.value,")")==0)
		{
			return 0;
		}
	}
	return 0;
}
int J()//条件语句 
{
	if(strcmp(new_w.value,"("))
	{
		error("缺少'('");
	 }
	 getWord();
	 str1=new_w.value; 
	 TJ();//条件
	 makeFour(op,str1,str2,result);
	 if(strcmp(new_w.value,")"))
	 {
	 	error("缺少')'");
	 }
	 //使四元式为空 
	  op="";
	  str1="";
	  str2="";
	  result="";
	  getWord();
	  H1();//语句一 
	  if(strcmp(new_w.value,";")==0)
	  {
	   		getWord();
	  }
	  stringstream if_s;//
      if_s<<f_num+1;//   int转string 
      if_s>>four[tj_x].res;//
      
      tj_x=f_num;
      op="go";
      str1="";
	  str2="";
	  result="";
	  makeFour(op,str1,str2,result);//满足if条件之后 ,跳过else语句 
	  
	  if(strcmp(new_w.value,"else"))
	  {
	  	error("缺少'else'"); 
	  	H1();//语句一
	  }
	  else
	  {
	  	getWord();
	  	H1();//语句一
	  } 
	  stringstream else_s;//
      else_s<<f_num;//   int转string 
      else_s>>four[tj_x].res;//
	return 0; 
}
void K()//循环语句
{
	if(strcmp(new_w.value,"("))
	{
		error("缺少'('");
	}
	getWord();//(a>0)中的a 
	str1=new_w.value;
	TJ();//条件 
	makeFour(op,str1,str2,result);
	if(strcmp(new_w.value,")"))
	{
		error("缺少')'");
	}
	getWord();
	
	if(strcmp(new_w.value,"do"))
	{
		error("缺少'do'");
		H1();//语句1 
	}
	else
	{
		getWord();
		H1();//语句1

	}	
}
int H1()//语句1 
{
	if(strcmp(new_w.value,"{")==0) 
	{
		getWord();
		
		D();//语句部分
		return 0; 
	}
	else
	{
		H();//语句 
		return 0;
	}
}
int TJ()//条件
{
	//进Q之前时(a>0)中的a 
	Q();
	if(strcmp(new_w.value,">")==0)
	op="<=";
	if(strcmp(new_w.value,"<")==0)
	op=">=";
	if(strcmp(new_w.value,">=")==0)
	op="<";
	if(strcmp(new_w.value,"<=")==0)
	op=">";
	if(strcmp(new_w.value,"==")==0)
	op="!=";
	if(strcmp(new_w.value,"!=")==0)
	op="==";
	if(new_w.type!=43)
	{
		error("缺少关系运算符"); 
	}
	getWord();
	str2=new_w.value;
	tj_x=f_num;//记录条件的四元式符号,方便修改他的res 
	Q();
	return 0;
} 
int main()
{
	char Infile[100];
	
	//对文件的读出和写入借用了网上的知识 
	printf("要测试的小程序的名字(.txt):");
    scanf("%s", Infile);
    if ((fin = fopen(Infile, "r")) == NULL)
    {
        printf("\n 读入文件错误 \n");
        return (1);
    } 
   
	P();
	if(e==0)
	{
		printFour();
	}
	else
	{
		cout<<"\n存在语法错误,无法生成四元式"<<endl;
	}
	
	return 0;
}


展开阅读全文

没有更多推荐了,返回首页