编译原理之自下而上语法分析

本关任务:编写一个程序实现自下而上语法分析,利用SLR(1)分析算法实现。

 

 

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

#define size 20
//状态个数    
#define size_s 10    
//终结符个数   
#define size_a 5   
//非终结符个数   
#define size_g 2     
//文法规则条数    
#define size_ge 5    
#define MAXSIZE 3

typedef struct Ge
{
	char head;      
	char gen[4];       
}Generate;

typedef struct A
{
	int st[size_a];       
	int re[size_a];       
}Action;
typedef struct G
{
	char head[size_g];     
	int gt[size_g];       
}GOTO;
int status[size];   //状态栈                                                        
int  sta_Index;     //状态栈栈顶    
char symbol[size];  //符号栈                     
int  sym_Index;     //符号栈栈顶   
char expression[size];    //输入串            
int  exp_Index;          //输入串最后下标                  
int  exp_top;            //输入串开始下标
int  step;               //步骤
int  IsAccept = 0;       //0 不接受,1表示接受
Generate gene[size_ge +1]; //文法
Action act[size_s];  //action表
GOTO go[size_s];     //goto表

void GOTOTable(int sta, char symb);
void Syntax(void)//输出文法
{
	printf("-------SLR(1) Analysis Program -------- \n");

	printf(" (1)S -> Sb\n (2)S -> bAa\n (3)A -> aSc\n (4)A -> aSb\n (5)A -> a\n ");
	printf("-----------------------------------------\n");
}

void InputExpression(void)//输入表达式,以#结束
{
	char ch;
	printf("请输入分析串,以'#'结束:");
	exp_Index = 0;
	do                                
	{
		scanf("%c",&ch);
		if ((ch!='a') &&(ch!='b') &&(ch!='c')&&(ch!='#'))
		{
			printf("fail");
			getchar();
			exit(0);
		}
		expression[exp_Index++]=ch;
	}while(ch!='#');                       
	getchar();
}


void Initlize(void)//将文法、action表、goto表初始化
{
	gene[1].head = 'S';
	strcpy(gene[1].gen,"Sb");
	gene[2].head = 'S';
	strcpy(gene[2].gen,"bAa");
	
	gene[3].head = 'A';
	strcpy(gene[3].gen,"aSc");
	
	gene[4].head = 'A';
	strcpy(gene[4].gen,"aSb");
	
	gene[5].head = 'A';
	strcpy(gene[5].gen,"a");

	act[0].st[1] = 2;

	act[1].st[1] = 3;        //E -> E + T\n (1)E -> T\n (2)T -> T*F\n (3)T -> F\n (4)F -> (E)\n (5)F ->i\n");
	// act[1].st[5] = 10;
	act[2].st[0] = 5;

	act[3].re[1] = 1;
	act[3].re[2] = 1;
	act[3].re[3] = 1;
	
	act[4].st[0] = 6;
		
	act[5].re[0] = 5;
	act[5].st[1] = 2;

	
	act[6].re[1] = 2;
	act[6].re[2] = 2;
	act[6].re[3] = 2;
	
	act[7].st[1] = 9;
	act[7].st[2] = 8;
	
	act[8].re[0] = 3;
	
	act[9].re[0] = 4;
	act[9].re[1] = 1;
	act[9].re[2] = 1;
	act[9].re[3] = 1;
	

	go[0].head[0] = 'S';
	go[0].gt[0] = 1;
	
	go[2].head[1] = 'A';
	go[2].gt[1] = 4;

	
	go[5].head[0] = 'S';
	go[5].gt[0] = 7;
	
	sta_Index = 0;                //状态栈栈顶
	status[sta_Index] = 0;        //状态栈 
	step = 1;                     //步骤
	sym_Index = 0;                //符号栈栈顶
	symbol[sym_Index] = '#';      //符号栈
	IsAccept = 0;                 //是否被接受
	exp_top = 0;                  //表达式下标
}

void Reduce(int sta, char symb,int col)
//归约,若句柄有n个字符,则状态栈和符号栈都需要出栈n个
{
	int i = 0;
	for(i = 0; i < strlen(gene[act[sta].re[col]].gen); i++)
	{
		symbol[sym_Index--] = '\0';
	}
	symbol[++sym_Index] = gene[act[sta].re[col]].head;
	for(i = 0; i < strlen(gene[act[sta].re[col]].gen) ; i++)
	{
		status[sta_Index - i] = '\0';
	}
	sta_Index -= i; 
	GOTOTable(status[sta_Index], symbol[sym_Index]);
}

void ActionTable(int sta, char symb,int col)
//对应LR分析表,
{
	if(sta == 1 && col == 3)
	{
		printf("accept\n");
		IsAccept = 1;
		return;
	}
	if(act[sta].st[col] != 0)
	{
		status[++sta_Index] = act[sta].st[col];
		symbol[++sym_Index] = symb;
		exp_top ++;
	}
	else if(act[sta].re[col] != 0)
	{
		Reduce(sta, symb, col);
	}
	else
	{
		getchar();
		exit(1);
	}
	
}
void GOTOTable(int sta, char symb)
{
	int i = 0;
	for(i = 0; i < size_s; i++)
	{
		if(go[sta].head[i] == symb)
		{
			status[++sta_Index] = go[sta].gt[i];
			return;
		}
	}
}

void Launch(void)//语法分析
{
	int s = status[sta_Index];
	char exp = expression[exp_top];
	char sym = symbol[sym_Index];
	while(IsAccept != 1)
	{
		s = status[sta_Index];
		exp = expression[exp_top];
		sym = symbol[sym_Index];
		switch(exp)
		{
		case 'a':
			ActionTable(s, exp, 0); 
			break;
		case 'b':
			ActionTable(s, exp, 1);
			break;
		case 'c':
			ActionTable(s, exp, 2);
			break;
		case '#':
			ActionTable(s, exp, 3);
			break;
		}
	}
}

int main()
{
	Syntax();//输出文法
	InputExpression();//输入表达式
	//初始化文法数组gene[]、action表中:act[].st[]为状态, act[].re[]为规则
	//goto表go[].head[]为表头, go[].gt[]为转移状态
	Initlize();
	Launch();//语法分析
	return 1;
}

 因为编译器的不同,某些输入和输出代码会出bug,需要读者自行修改一下,(我用的是DEVC++)另外代码是直接从DEV上复制过来的,进行了一点修改,也可能导致代码报错无法通过,这也需要读者自行修改一下,总体来说代码没有太大的毛病,只需要稍微修改一下就可以啦!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值