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

📄 topdown.cpp

📁 编译原理中的自顶向下的语法分析
💻 CPP
📖 第 1 页 / 共 2 页
字号:
						}
						break;
					}
				}
		}
	}

	void Select_Collection()       //求每条产生式的select集,存放在数组selectchars[30][30]中
	{
		for(int i=0;i<sto_tax;i++)
		{
			int select_num=0;
			int key1=0;
			int key2=0;
			for(int j=3;j<strlen(stotax[i]);j++)
			{
				for(int m=0;m<colec0num;m++)
					if(colec0[m]==stotax[i][j]) key1=1;
                if(key1==0)
				{
					key2=1;
					break;
				}
			}
			if(stotax[i][3]=='0')      //产生式右边为0,则把follow集加入select集中
			{
				follownumkey=0;
				follow_num=0;
				Follow_Collection(stotax[i][0]);
				for(int r=0;r<follow_num;r++)
				{
					int key5=0;
					for(int v=0;v<select_num;v++)
						if(followchars[r]==selectchars[i][v]) key5=1;
					if(key5==0) selectchars[i][select_num++]=followchars[r];
				}
                selectchars[i][select_num]='\0';
				break;
			}
			if(key2==0)     //表示产生式右边能推出0,则把first集和follow集加入select集中
			{
				first_num=0;
				First_Collection(&stotax[i][3]);
				for(int q=0;q<first_num;q++)
				{
					int key3=0;
					for(int s=0;s<select_num;s++)
						if(firstchars[q]==selectchars[i][s]) key3=1;
					if(key3==0) selectchars[i][select_num++]=firstchars[q];
				}
				follownumkey=0;
				follow_num=0;
				Follow_Collection(stotax[i][0]);
				for(int p=0;p<follow_num;p++)
				{
					int key4=0;
					for(int t=0;t<select_num;t++)
						if(followchars[p]==selectchars[i][t]) key4=1;
					if(key4==0)
						selectchars[i][select_num++]=followchars[p];
				}
                selectchars[i][select_num]='\0';
			}
			else    //表示产生式右边不能推出0,则把first集加入select集中
			{
				first_num=0;
				First_Collection(&stotax[i][3]);
				for(int q=0;q<first_num;q++)
				{
					int key3=0;
					for(int s=0;s<select_num;s++)
						if(firstchars[q]==selectchars[i][s]) key3=1;
					if(key3==0) selectchars[i][select_num++]=firstchars[q];
				}
				selectchars[i][select_num]='\0';
			}
		}  
	}

	void Estab_preanatab()    //创建预测分析表
	{
		int i,j;
        //如果分析表中有一项有两个产生式,则可确认该文法为非LL(1)文法,也不能改写为LL(1)文法,不能进行确定的自顶向下分析
		for(i=0;i<130;i++)
			for(j=0;j<130;j++)
				for(int m=0;m<20;m++)
					preanatab[i][j][m]='$';   //初始化分析表,以便重复建立
		for(i=0;i<sto_tax;i++)
		{
			for(j=0;j<strlen(selectchars[i]);j++)
			{
				int p=int(stotax[i][0]);
				int q=int(selectchars[i][j]);
				if(preanatab[p][q][0]=='$') strcpy(preanatab[p][q],stotax[i]);
				else
				{
					printf("该文法为非LL(1)文法,也不能改写为LL(1)文法,不能进行确定的自顶向下分析!\n");
                    ll_key=1;
					goto notll1;
				}
			}
		}
notll1:{}
	}

	void dispselect()     //显示选择
	{
		for(int i=0;i<sto_tax;i++)
		{
			cout<<"SELECT("<<stotax[i]<<")={";
			cout<<selectchars[i];
			cout<<"}"<<endl;
		}
	}

	void base_()
	{
		li=0;
		han=0;
		for(int q=0;q<20;q++)
		{
			lie[q]=' ';
			hang[q]=' ';
		}
		for(int i=0;i<130;i++)
		{
			for(int j=0;j<130;j++)
				if(preanatab[i][j][0]!='$')
				{
					int key1=1;
					for(int m=0;m<li;m++)
						if(lie[m]==char(j)) key1=0;
					if(key1) lie[li++]=char(j);
 	        		int key2=1;
	        		for(int n=0;n<han;n++)
	    	    		if(hang[n]==char(i)) key2=0;
		        	if(key2)
		        		hang[han++]=char(i); 
				}
		}
	}

	void disp_table()     //打印预测分析表
	{
	    base_();
		printf("预测分析表为:\n");
		cout<<"       ";
		for(int i=0;i<li;i++)  cout<<lie[i]<<"         ";
		cout<<endl;
		for(i=0;i<han;i++)
		{
			printf("%-5c",hang[i]);
			for(int j=0;j<li;j++)
				if(preanatab[int(hang[i])][int(lie[j])][0]!='$')
	    			printf("%-10s",preanatab[int(hang[i])][int(lie[j])]);
				else 
					printf("          ");
			cout<<endl;
		}
	}

	void Analyse_course()      //分析过程
	{
		char inputchars[100];  //存放要分析的字符
		int  inpoint;          //输入串指针
		char anastack[100];    //分析栈
		int  anapoint;         //分析栈指针
		int  i=1;
again:
		anastack[0]='#';
		anastack[1]=startchar;
		anastack[2]='\0';
		anapoint=1;
		printf("请输入要分析的字符串:\n");
   		char c=getchar();
        inpoint=0;
		int key=0;
		while(c!='#')
		{
			if(isupper(c)) key=1;
			inputchars[inpoint++]=c;
			c=getchar();
		}
		if(key==1)
		{
			printf("输入的字符串不能有大写字母:\n");
			goto again;
		}
		inputchars[inpoint++]='#';
		inputchars[inpoint]='\0';
		inpoint=0;
		printf("步骤 分析栈       (栈顶符号,当前输入符)     剩余输入串    所用产生式\n");
		while(!(anastack[anapoint]=='#' && inputchars[inpoint]=='#'))
		{ 
			if(anastack[anapoint]!=inputchars[inpoint])
			{
				if(preanatab[int(anastack[anapoint])][int(inputchars[inpoint])][0]!='$')
				{
					if(preanatab[int(anastack[anapoint])][int(inputchars[inpoint])][3]=='0')
					{
			    		printf("%-6d",i);
				    	printf("%-15s",anastack);
			    		printf("     (%c,%c)   查表",anastack[anapoint],inputchars[inpoint]);
			    		printf("%20s",&inputchars[inpoint]);
			     		printf("      %s",preanatab[int(anastack[anapoint])][int(inputchars[inpoint])]);
			    		printf("\n");
			    		i++;
						anastack[anapoint]='\0';
						anapoint--;
					}
					else
					{
			    		printf("%-6d",i);
				    	printf("%-15s",anastack);
			    		printf("     (%c,%c)   查表",anastack[anapoint],inputchars[inpoint]);
			    		printf("%20s",&inputchars[inpoint]);
			     		printf("      %s",preanatab[int(anastack[anapoint])][int(inputchars[inpoint])]);
			    		printf("\n");
			    		i++;
			    		char s[30];
			    		strcpy(s,preanatab[int(anastack[anapoint])][int(inputchars[inpoint])]);
                        for(int j=strlen(s)-1;j>=3;j--)
		    				anastack[anapoint++]=s[j];
			    		anastack[anapoint]='\0';
				    	anapoint--;
					}
				}
				else
				{
					printf("该输入串不是文法的句子!\n");
					goto nosent;
				}
			}
			else
			{
				printf("%-6d",i);
				printf("%-15s",anastack);
				printf("     (%c,%c)  %c匹配",anastack[anapoint],inputchars[inpoint],inputchars[inpoint]);
                inpoint++;
				printf("%20s",&inputchars[inpoint]);
				printf("\n");
				anastack[anapoint]='\0';
				anapoint--;
				i++;
			}
		}
		printf("%-6d",i);
		printf("%-15s",anastack);
		printf("     (%c,%c)  成功接收",anastack[anapoint],inputchars[inpoint],inputchars[inpoint]);
		printf("%17s",&inputchars[inpoint]);
		printf("\n");
nosent:{}
	}

	void deduce0_colec()       //将所有能推导出0的非终符放在数组colec0[30]中
	{
		colec0num=0;
		char d0colec[30][20];
		for(int i=0;i<sto_tax;i++) strcpy(d0colec[i],stotax[i]);
		for(i=0;i<sto_tax;i++)
			if(stotax[i][3]=='0') colec0[colec0num++]=stotax[i][0];
		int key1;
next:
		key1=0;
		for(i=0;i<sto_tax;i++)
		{
			d0colec[i][0]=stotax[i][0];
			d0colec[i][1]=stotax[i][1];
			d0colec[i][2]=stotax[i][2];
			for(int j=3;j<strlen(d0colec[i]);j++)
				for(int m=0;m<colec0num;m++)
					if(d0colec[i][j]==colec0[m])
					{
						d0colec[i][j]='0';
						key1=1;
					}
		}
		int key2=0;
		if(key1==1)
		{
			for(i=0;i<sto_tax;i++)
			{
				for(int j=3;j<strlen(d0colec[i]);j++)
					if(d0colec[i][j]!='0')
					{
						key2=1;
						break;
					}
				if(key2==0) colec0[colec0num++]=d0colec[i][0];
			}
			goto next;
		}
	}

	void dispfirst()     //显示First集
	{
fi_again:
		first_num=0;
		cout<<"请输入字符串,以求该串的First集,长度不小于1"<<endl;
        char p[20];
		cin>>p;
        First_Collection(p);
		cout<<"FIRST ( "<<p<<" )={ ";
		for(int i=0;i<first_num;i++)
		{
			int key=1;
			for(int j=0;j<i;j++)
				if(firstchars[j]==firstchars[i]) key=0;
			if(key) cout<<firstchars[i];
		}
		cout<<"}";
		cout<<endl;
		cout<<"would you try another? press y to try again,other to exit"<<endl;
		char c;
		cin>>c;
		if(c=='y') goto fi_again;
	}

	void dispfollow()
	{
fo_again:
		follow_num=0;
		cout<<"请输入一个非终结符"<<endl;
        char p;
		cin>>p;
        Follow_Collection(p);
		cout<<"FOLLOW ( "<<p<<" )={ ";
		for(int i=0;i<follow_num;i++)
		{
			int key=1;
			for(int j=0;j<i;j++)
				if(followchars[j]==followchars[i])
					key=0;
			if(key)
	    		cout<<followchars[i];
		}
		cout<<"}";
		cout<<endl;
		cout<<"would you try another? press y to try again,other to exit"<<endl;
		char c;
		cin>>c;
		if(c=='y') goto fo_again;
	}
};

void main()
{
	Syntax_analysis s;
	printf("=======================自顶向下语法分析器=====================================\n");
	printf("适应的文法类型:\n");
	printf("1.一切LL(1)文法\n");
    printf("2.含有直接左递归但可以转化为LL(1)文法的文法\n");
	printf("3.含有间接左递归但可以转化为LL(1)文法的文法\n\n");
	printf("说明:\n");
	printf("1.文法表达方式:\n");
    printf("  例如:S:=Aa|Bb,其中空串用数字0代替,每输入一个表达式换行写下一表达式\n");
	printf("2.文法输入结束后,换行再按'#'结束\n");
	printf("3.需要输入命令来执行所需要的功能\n\n");
    printf("命令说明:\n");
    printf("open---------从外存储器打开某文法\n");
	printf("input--------从键盘输入文法\n");
	printf("lltab--------查看预测分析表\n");
	printf("select-------查看每条产生式的SELECT集\n");
    printf("first--------求所输串的FIRST集\n");
	printf("follow-------求所输非终结符的FOLLOW集\n");
	printf("ll-----------对某个输入句子进行分析\n");
	printf("exit---------退出程序\n");
    printf("------------------------------------------------------------------------------\n\n");
	int key=0;
	int _key=0;
entercmd:
	char cmd[30];
	printf("cmd>>");
	cin>>cmd;
	if(!strcmp(cmd,"open"))
	{
		if(key==0) _key=1;
		key=1;
		cout<<"请输入文件所在路径和文件名:"<<endl;
		s.openfile();
		s.getin();
		s.disp();
    	s.Delpare();
    	s.deduce0_colec();
    	s.Select_Collection();
        s.Estab_preanatab();
	}
    else if(!strcmp(cmd,"input"))
	{
		if(key==1) s.input_key=0;
		_key=1;
		key=1;
		cout<<"请输入文法,以'#'结束:"<<endl;
    	s.get_in();
    	s.Delpare();
    	s.deduce0_colec();
    	s.Select_Collection();
        s.Estab_preanatab();
	}
    else if(!strcmp(cmd,"ll"))
	{
		char c;
		if(_key==0) c=getchar();
		_key=0;
		if(key==1)
		{ 
    		if(s.ll_key==0) s.Analyse_course();
	    	else printf("该文法为非LL(1)文法,也不能改写为LL(1)文法,不能进行确定的自顶向下分析!\n");
 		}
		else printf("您还没打开或输入文法!\n");
		s.input_key=1;
	}
	else if(!strcmp(cmd,"lltab"))
	{
		if(key==1) s.disp_table();
		else printf("您还没打开或输入文法!\n");
		s.input_key=1;
	}
	else if(!strcmp(cmd,"select"))
	{
		if(key==1) s.dispselect();
		else printf("您还没打开或输入文法!\n");
		s.input_key=1;
	}
	else if(!strcmp(cmd,"first"))
	{
		if(key==1) s.dispfirst();
		else printf("您还没打开或输入文法!\n");
		s.input_key=1;
	}
	else if(!strcmp(cmd,"follow"))
	{
		if(key==1) s.dispfollow();
		else printf("您还没打开或输入文法!\n");
		s.input_key=1;
	}
	else if(!strcmp(cmd,"exit")) goto exitpro;
	else printf("the cmd is not exist!\n");
	goto entercmd;
exitpro:{}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -