LL(1)语法分析

29 篇文章 0 订阅
1 篇文章 0 订阅
实验目的:

        通过程序设计,深入理解利用LL(1)方法进行自顶向下语法分析的过程,提高对数据结构的设计能力和编写程序、调试程序的能力。

实验原理和内容:
  1. 结合算法实现的需要定义存储文法和LL(1)分析表的数据结构;
  2. 采用C语言或JAVA语言编程完成LL(1)语法分析过程,判断一个给定的符号串是否能够被该文法接受;
  3. 有针对性地选择符号串对所编写的语法分析程序进行测试和调试。
话不多说,上代码:
/*
1.S->MH
2.S->a
3.H->LSo
4.H->$
5.K->dML
6.K->$
7.L->eHf
8.M->K
9.M->bLM
*/ 
#include<bits/stdc++.h>
using namespace std;
const int N=100;
/**********************************************************/
/*                    定义变量                            */
/**********************************************************/ 

stack <char> input,sta;//定义输入流栈,语法栈 
char ch[N]; //暂存字符串
int len;//记录字符串的长度 

int LL[5][7]={2,1,1,1,1,-1,1,
			  1,-1,-1,3,4,4,4,
			  -1,-1,5,6,6,-1,6,
			  -1,-1,-1,7,-1,-1,-1,
			  -1,9,8,8,8,-1,8};//数字化的分析表 


/**********************************************************/
/*                     函数声明                           */
/**********************************************************/
void init();//初始化栈 
bool is_terminal(char ch);// 判断是否为终结符
int nTerminal_int(char ch);//获取非终结符对应的数组下标 
int terminal_int(char ch); //获取终结符对应的数组下标 
void LL1(stack <char> input,stack <char> sta);//LL(1)分析
void display(); //打印 


/**********************************************************/
/*                      主函数                            */
/**********************************************************/
int main()
{
	display();//打印文法以及LL(1)预测表 
	cout<<"请输入要识别的字符串(以#结束):";
	while(cin>>ch[len]&&ch[len++]!='#');//读入字符串
	init();//初始化栈 
	LL1(input,sta);//LL(1)语法分析 
	return 0;
 } 


/**********************************************************/
/*                      初始化函数                        */
/**********************************************************/

void init()
{
	//初始化语法栈 
	sta.push('#');
	sta.push('S');
	//初始化输入流栈 
	for(int i=len-1;i>=0;i--)
		input.push(ch[i]);
		
}


/**********************************************************/
/*                   判断是否为终结符                     */
/**********************************************************/
bool is_terminal(char ch)
{
  switch(ch)
  {
   case 'S':
   case 'H':
   case 'K':
   case 'L':
   case 'M': return false;//非终结符 
   case 'a':
   case 'b':
   case 'd':
   case 'e':
   case 'o':
   case 'f':
   case '#':return true;//终结符 
   default: cout<<"Unaccept!"<<endl;exit(0);
  }
}


/**********************************************************/
/*                  获取非终结符对应的数组下标            */
/**********************************************************/
int nTerminal_int(char ch)
{
  int x;
  switch(ch)//获取非终结符对应的数组下标 
  {
   case 'S':x=0;break;
   case 'H':x=1;break;
   case 'K':x=2;break;
   case 'L':x=3;break;
   case 'M':x=4;break;
   default: cout<<"Unaccept!"<<endl;exit(0);
  }
  return x;
}


/**********************************************************/
/*                  获取终结符对应的数组下标            */
/**********************************************************/
int terminal_int(char ch)
{
  int x;
  switch(ch)//获取终结符对应的数组下标 
  {
   case 'a':x=0;break;
   case 'b':x=1;break;
   case 'd':x=2;break;
   case 'e':x=3;break;
   case 'o':x=4;break;
   case 'f':x=5;break;
   case '#':x=6;break;
   default: cout<<"Unaccept!"<<endl;exit(0);
  }
  return x;
}


/**********************************************************/
/*                      LL(1)文法                         */
/**********************************************************/
void LL1(stack <char> input,stack <char> sta)
{
	char in,s;//in用于记录输入流的栈顶字符,s用于记录语法栈的栈顶字符 
	in=input.top();
	s=sta.top();
	int next;//用于标记下一个文法 
	while(s!='#')
	{
//		cout<<"in="<<in<<endl;
//		cout<<"sta="<<s<<endl;
		//语法栈中遇到终结符 
		if(is_terminal(s))
		{
			if(in==s)//语法栈栈顶和输入流栈顶字符相同,同时出栈 
			{
				input.pop();
				sta.pop();
			}
			else//如果都为终结符且不等,则说明不能识别该终结符 
			{
				cout<<"Unaccept!"<<endl;
				exit(0);
			} 
		}
		//语法栈中遇到非终结符 
		else
		{
			sta.pop();//语法栈出栈,接下来进行入栈操作 
			next=LL[nTerminal_int(s)][terminal_int(in)];//获取对应下一个文法的标号 
//			cout<<"next="<<next<<endl; 
			switch(next)//进行入栈操作 
			{
				case 1:sta.push('H');sta.push('M');break;
				case 2:sta.push('a');break;
				case 3:sta.push('o');sta.push('S');sta.push('L');break;
				case 4:break;
				case 5:sta.push('L');sta.push('M');sta.push('d');break;
				case 6:break;
				case 7:sta.push('f');sta.push('H');sta.push('e');break;
				case 8:sta.push('K');break;
				case 9:sta.push('M');sta.push('L');sta.push('b');break;
				case -1:cout<<"unaccept!"<<endl; exit(0);
			}
		} 
		//获取语法栈和输入流栈顶位置的字符 
		in=input.top();
		s=sta.top();
	}
	//结束遍历后,若语法栈和输入流都为结束符#,说明该文法能接收该字符串 
  	if(in=='#'&&s=='#') 
		cout<<"Accept!"<<endl;
    else cout<<"Unaccept!"<<endl;
}


/**********************************************************/
/*                      打印函数                          */
/**********************************************************/
void display()
{
	cout<<"------------文法------------"<<endl;
	cout<<"\t  1.S->MH"<<endl;
	cout<<"\t  2.S->a"<<endl;
	cout<<"\t  3.H->LSo"<<endl;	
	cout<<"\t  4.H->$"<<endl;	
	cout<<"\t  5.K->dML"<<endl;
	cout<<"\t  6.K->$"<<endl;
	cout<<"\t  7.L->eHf"<<endl;
	cout<<"\t  8.M->K"<<endl;
	cout<<"\t  9.M->bLM"<<endl;
	cout<<"----------------------------LL(1)预测表-------------------------"<<endl; 
	cout<<"\t a \t b \t d \t e \t o \t f \t #"<<endl;
	cout<<"----------------------------------------------------------------"<<endl; 
	cout<<"S |\tS->a\tS->MH\tS->MH\tS->MH\tS->MH\t\tS->MH"<<endl;
	cout<<"H |\t\t\t\tH->LSo\tH->$\tH->$\tH->$"<<endl;
	cout<<"K |\t\t\tK->dML\tK->$\tK->$\t\tK->$"<<endl;
	cout<<"L |\t\t\t\tL->eHf" <<endl;
	cout<<"M |\t\tM->bLM\tM->K\tM->K\tM->K\t\tM->K"<<endl;
}

运行结果:

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值