编译原理——SLR(1)分析

名称:用SLR(1)分析技术对输入串进行句型分析

输入:SLR(1)分析表(保存为text.txt文件)、分析的句型

文件示例:

实现代码如下:

(每个函数的功能在代码中均有注释)

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

typedef struct any_W                      //保存文法
{
	char unset;
	char wenFA[8];
}W;                        
typedef struct any_table                //保存分析表
{
	char body[8];
}table;                 
int step_NUM=0;
int calculate(char a[])              //计算带字母的状态

{
	int i;
	int num=0;
	for(i=1;i<=strlen(a)&&a[i]!='\0';i++)
	{
		num=num*10+(a[i]-'0'); //注意字符与整形的转换
	}
	return num;
}      
int calculate_INT(char a[])           //计算不带字母的状态
{
	int i;
	int num=0;
	for(i=0;a[i]!='\0';i++)
	{
		num=num*10+(a[i]-'0');
	}
	return num;
}  
int print_K(char a[])                    //规范格式输出空格
{
	int k;
	for(k=15;k>strlen(a);k--)                    
		printf(" ");
	return 0;
}
int print_K_INT(int num)
{
	int k;
	for(k=16;k>num;k--)                     //输出格式控制
			{
				printf(" ");
			}
	return 0;
}
void clear_W(W a[])                    //初始化文法保存数组wen
{
	for(int i=0;i<20;i++)
	{
		a[i].unset='\0';
		for(int k=0;k<8;k++)
			a[i].wenFA[k]='\0';
	}
}
void ana_C(table a[][50])                    //初始化二维表
{
	for(int i=0;i<50;i++)
	{
		for(int j=0;j<50;j++)
		{
			for(int k=0;k<sizeof(a[i][j].body);k++)

			   a[i][j].body[k]='\0';
		}
	}
}
void clear(char a[])           //清空字符串数组
{
	int i=strlen(a);
	for(int k=0;k<i;k++)
		a[k]='\0';
}
void clear_INT(int a[])           //清空int型数组
{
	for(int k=0;k<sizeof(a);k++)
		a[k]=-1;
}
int table_NUM(char n,char t[])                        //查找元素n在一维数组中的位置
{
	int num=0;
	for(;num<strlen(t);num++)
	{
		if(n==t[num])
			return num;
	}
	return -1;

}
int sourch(char a[],char x)                 //查找相同元素,找到返回1,未找到返回0
{
	int i=0;
	for(;i<strlen(a);i++)
	{
		if(a[i]==x)
			return 1;
	}
	return 0;
}
void input_SET(char fiset[],table ana[][50],W wen[])             //输入分析表(文件读入)
{
	int hr;
	int w_NUM=1;
	int fiset_NUM=0;
	char fiset_S;
	int i=0;
	int q=0;
	int p;
	FILE  *fp=NULL;
	fp=fopen("text.txt","r");
	char x[20];
	clear(x);
	while(!feof(fp))
	{
		fscanf(fp,"%s",x);
		if(x[0]=='$')break;
		q++;
		if(q%2==1)
		{
			wen[w_NUM].unset=x[0];
			clear(x);
		}
		if(q%2==0)
		{
			strcpy(wen[w_NUM].wenFA,x);
			clear(x);
			w_NUM++;
		}
	}
	clear(x);
	while(!feof(fp))
	{
		
		i++;
		if(i%3==1)
		{
			fscanf(fp,"%d",&p);
			hr=p+1;
			clear(x);
		}
		if(i%3==2)
		{
			fscanf(fp,"%s",x);
			fiset_S=x[0];
			if(sourch(fiset,fiset_S)==0)           //为找到终结符
			{
				fiset[fiset_NUM++]=x[0];
				fiset[fiset_NUM]='\0';
			}
			clear(x);
		}
		if(i%3==0)
		{  
			fscanf(fp,"%s",x);
			int lr=table_NUM(fiset_S,fiset);
			strcpy(ana[hr][lr].body,x);
			ana[hr][lr].body[strlen(x)]='\0';
			fiset_S='\0';
			clear(x);

		}
	}
	fclose(fp);
}
void input_HAND(char fiset[],table ana[][50])              //添加表头
{
	int i,j;
	for(i=0;i<strlen(fiset);i++)
	{
		ana[0][i].body[0]=fiset[i];
		ana[0][i].body[1]='\0';
	}
}
void output_ANA(table analysis[][50],char fiset_T[])     //分析表的输出

{
	int i,j,k;
	for(i=0;i<=12;i++) 
	{
		if(i!=0)
			printf("%2d   ",i-1);
		else
			printf("     ");
		for(j=0;j<=strlen(fiset_T);j++)
		{
			if(fiset_T[j]<'A'||fiset_T[j]>'Z')
			{
				if(analysis[i][j].body[0]!='\0')
					printf("%6s",analysis[i][j].body);
				else 
					printf("     -");
			}
		}
		for(j=0;j<=strlen(fiset_T);j++)
		{
			if(fiset_T[j]>='A'&&fiset_T[j]<='Z')
			{
				if(analysis[i][j].body[0]!='\0')
					printf("%6s",analysis[i][j].body);
				else 
					printf("     -");
			}
		}
		printf("\n");
	}
}
void output_PRO(int ana_ZT[],char ana_FH[],char ana_V,char value[],int zt_NUM,int fh_NUM,int v_NUM,int behaver,int lr,char fiset[],table analysis[][50],int flag,char q_S,int back_NUM)
//过程的输出

{
	int qq=1;
	int w=0;
	int k;
	printf("%2d        ",step_NUM);
	for(int k=0;k<=zt_NUM;k++)
		printf("%d",ana_ZT[k]);
	for(int q=0;q<=zt_NUM;q++)
	{
		if(ana_ZT[q]>10)
		{
			w=zt_NUM+qq;
			qq++;
		}
		else w=zt_NUM;
	}
	print_K_INT(w);
	for(int k=0;k<=fh_NUM;k++)
		printf("%c",ana_FH[k]);
	print_K(ana_FH);
	printf("%c          ",ana_V);
	for(int k=v_NUM;k<strlen(value);k++)
		printf("%c",value[k]);
	for(k=0;k<6+v_NUM;k++)                    
	{
		printf(" ");
	}
	printf("ACTION[%2d,%c]=%3s     ",ana_ZT[zt_NUM],ana_V,analysis[behaver+1][lr].body);
	step_NUM++;
}
//查找 goto语句的B
char sourch_FH_back(int A,char C,char fiset[],table analysis[][50])//goto(A,B)=C
{
	int i;
	for(i=0;i<strlen(fiset);i++)
	{
		if(analysis[A+1][i].body[0]==C)        
			break;
	}
	return fiset[i];
}
void error()
{
	printf("输入句子不符合文法规则\n");
}
int ana_FUNCTION_ANA(table analysis[][50],char fiset[],W wen[],char value[])
{
	int back_NUM;
	char q_S;
	int c;
	int p;
	char v;
	int flag_P=0;                    //0为无goto, 1为有goto
	int lr;
	int ana_ZT[50];                     //状态栈
	char ana_FH[50];           //符号栈
	clear_INT(ana_ZT);
	clear(ana_FH);
	int behaver;                 //当前状态
	char x;
	int zt_NUM=0;
	int fh_NUM=0;
	int v_NUM=0;
	ana_ZT[zt_NUM]=0;           //栈初始化
	ana_FH[fh_NUM]='#';
	char ana_V;
	ana_V=value[v_NUM];
	behaver=ana_ZT[zt_NUM];
	lr=table_NUM(ana_V,fiset);
	output_PRO(ana_ZT,ana_FH,ana_V,value,zt_NUM,fh_NUM,v_NUM+1,behaver,lr,fiset,analysis,flag_P,q_S,back_NUM);
	printf("                          <移入>");
	printf("\n");
	p=calculate(analysis[behaver+1][lr].body);
	ana_ZT[++zt_NUM]=p; 
	ana_FH[++fh_NUM]=value[v_NUM];
	ana_FH[fh_NUM+1]='\0';
	v_NUM++;
	while(1)
	{
		ana_V=value[v_NUM];     //当前输入符
		behaver=ana_ZT[zt_NUM];  //当前状态
		lr=table_NUM(ana_V,fiset);            //当前输入符号的列
		if(analysis[behaver+1][lr].body[0]=='s')
		{
			flag_P=0;
			output_PRO(ana_ZT,ana_FH,ana_V,value,zt_NUM,fh_NUM,v_NUM+1,behaver,lr,fiset,analysis,flag_P,q_S,back_NUM);
			p=calculate(analysis[behaver+1][lr].body);
			ana_ZT[++zt_NUM]=p; //加入状态
			ana_FH[++fh_NUM]=ana_V;
			ana_FH[fh_NUM+1]='\0';
			v_NUM++;
			printf("                          <移入>");
			printf("\n");
			
		}
		else
		{
			if(analysis[behaver+1][lr].body[0]=='r')
			{
				
				output_PRO(ana_ZT,ana_FH,ana_V,value,zt_NUM,fh_NUM,v_NUM+1,behaver,lr,fiset,analysis,flag_P,q_S,back_NUM);
				int p=calculate(analysis[behaver+1][lr].body);     //r后面的状态
				back_NUM=strlen(wen[p].wenFA);             //r后的状态所对应的文法的右边长度
				zt_NUM-=back_NUM;
				fh_NUM-=back_NUM;
				c=ana_ZT[zt_NUM];                             //回退后的状态
				q_S=wen[p].unset;					 //文法的左边
				int lr_S=table_NUM(q_S,fiset);                //文法左边对应的下标
				int back_T=calculate_INT(analysis[c+1][lr_S].body);           //新的状态
				ana_ZT[++zt_NUM]=back_T; 
				ana_FH[++fh_NUM]=wen[p].unset;
				ana_FH[fh_NUM+1]='\0';
				printf("     GOTO[%2d,%c]=%2d",c,q_S,back_T);
				printf("        <归约>\n");
			}
			else
			{
				if(behaver==1)
				{
					output_PRO(ana_ZT,ana_FH,ana_V,value,zt_NUM,fh_NUM,v_NUM+1,behaver,lr,fiset,analysis,flag_P,q_S,back_NUM);
printf("                          <接受>");

					printf("\nCONGRATRULATION!\n");
					break;
				}
				else
				{
					error();
					break;
				}
			}
		}
	}

	return 0;
}

int main()
{
	printf("状态                 ACTION                  GOTO\n");
	W wen[20];
	clear_W(wen);         //初始化文法表
	table analysis[50][50];      //定义分析表
	ana_C(analysis);
	char fiset_T[20];          //符号数组
	clear(fiset_T);
	input_SET(fiset_T,analysis,wen);
	input_HAND(fiset_T,analysis);
	output_ANA(analysis,fiset_T);
	printf("请输入需要分析的字符串,以#结尾\n");
	char value_A[50];
	clear(value_A);
	scanf("%s",value_A);
	value_A[strlen(value_A)]='\0';
	printf("步骤    状态栈          符号栈        当前输入符      剩余输入串        ACTION                      GOTO          当前操作\n");
	ana_FUNCTION_ANA(analysis,fiset_T,wen,value_A);
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SLR分析是一种用来分析文法的自动工具,可以用来判断一个输入串是否符合给定的文法规则。下面是一个简单的SLR分析的实现: 1. 构建LR(0)自动机 首先需要构建LR(0)自动机,即从文法的起始符号开始,用状态示当前所在的分析位置,用项目示当前所在的分析位置和剩余待分析的输入符号。根据文法规则构建自动机的转移边和项目集。 2. 计算FIRST和FOLLOW集 根据文法规则计算FIRST集和FOLLOW集,用于构建SLR分析。FIRST集示每个非终结符号能够推导出的终结符号集合,FOLLOW集示每个非终结符号后面可能出现的终结符号集合。 3. 构建SLR分析 根据LR(0)自动机和计算得到的FIRST和FOLLOW集构建SLR分析格的行示状态,列示终结符号和非终结符号,格中的每个元素示对应状态上遇到该终结符号或非终结符号时应该执行的动作,包括SHIFT(将当前符号移入栈中)、REDUCE(根据某个文法规则进行规约)、ACCEPT(接受输入串,分析成功)和ERROR(分析失败)。 下面是一个SLR分析的Python实现示例,其中输入的文法规则为: ``` E -> E + T E -> T T -> T * F T -> F F -> ( E ) F -> id ``` ```python class SLRTable: def __init__(self, grammar): self.grammar = grammar self.action = {} # action self.goto = {} # goto self.states = self.build_states() # LR(0)自动机状态集 self.first = self.compute_first() # FIRST集 self.follow = self.compute_follow() # FOLLOW集 self.build_table() # 构建SLR分析 def build_states(self): pass # 构建LR(0)自动机状态集 def compute_first(self): pass # 计算FIRST集 def compute_follow(self): pass # 计算FOLLOW集 def build_table(self): for i, state in enumerate(self.states): for item in state.items: if item.dot_at_end(): if item.production.left == self.grammar.start_symbol: self.action[(i, '$')] = 'accept' # 接受 else: for symbol in self.follow[item.production.left]: self.action[(i, symbol)] = f"reduce {item.production}" # 规约 elif item.next_symbol().is_terminal(): next_state = state.next_state(item.next_symbol()) self.action[(i, item.next_symbol())] = f"shift {next_state}" # 移入 elif item.next_symbol().is_nonterminal(): next_state = state.next_state(item.next_symbol()) self.goto[(i, item.next_symbol())] = next_state # 转移 for i, state in enumerate(self.states): for item in state.items: if item.dot_at_end() and item.production.left == self.grammar.start_symbol: continue if item.next_symbol().is_terminal(): continue for symbol in self.first[item.next_symbol()]: if (i, symbol) in self.action or (i, symbol) in self.goto: raise ValueError("Conflict in SLR table") self.action[(i, symbol)] = f"reduce {item.production}" # 规约 ``` 在实现中,我们先通过`build_states()`方法构建LR(0)自动机状态集,然后分别计算`compute_first()`和`compute_follow()`方法得到FIRST集和FOLLOW集。接下来,我们根据自动机状态集和FIRST/FOLLOW集构建SLR分析,用字典`action`和`goto`分别示action和goto,最终得到的SLR分析就是这两个的组合。其中,字典的键由状态和符号组成,值示对应的动作或转移状态。 注意,SLR分析可能存在冲突,例如同一个状态上遇到同一个符号既可以移入也可以规约。这种情况需要进行处理,通常有两种解决方法:1)修改文法使其满足某些性质(例如LR(1)文法就不会存在冲突);2)手动调整SLR分析,比较麻烦但是可行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值