【编译原理】-- 递归下降语法分析设计原理与实现(C语言实现)

本实验基于词法分析程序实现,可参考本人前面的文章。


目录

一、目标任务

二、程序功能描述

三、主要数据结构描述

四、程序结构描述

设计方法

First集和Follow集

递归子程序框图

函数定义及函数之间的调用关系

五、程序测试

测试用例1

测试结果1

测试用例2

测试结果2

测试用例3

测试结果3

测试用例4

测试结果4


一、目标任务

完成以下描述赋值语句的 LL(1)文法的递归下降分析程序
G[S]: S→V=E
E→TE′
E′→ATE′|ε
T→FT′

T′→MFT′|ε
F→ (E)|i
A→+|-
M→*|/
V→i终结符号 i 为用户定义的简单变量,即标识符的定义。

二、程序功能描述

输入词法分析输出的二元式序列,能够输出该算术表达式是否为该文发定义的判断结果;

输出二元式序列对应的算术表达式;

输出算术表达式对应的单词符号类别编码;

输出递归下降语法分析的过程;

能够通过递归下降分析发现简单的语法错误。

三、主要数据结构描述

常量MAX_LENG定义数组的最大长度;

sign用于标记语句是否正确;

key[MAX_LENG]存放单词符号的编码类别;

   buf[MAX_LENG]保存词法分析程序的二元式序列;

   shuru[MAX_LENG]保存待检测的算术表达式;

   len为buf的长度。

四、程序结构描述

设计方法

First集和Follow集

递归子程序框图

函数定义及函数之间的调用关系

S():调用V、E

E():调用E’

E’():调用A、T、E’

T():调用F、T’、

T’():调用M、F、T’

F():调用E

A()

M()

V()

五、代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LENG 1024
int i;
int sign=0;//标记语句是否正确 
int key[MAX_LENG];//存放单词符号的编码类别 

void S();
void E(); 
void E_(); 
void T(); 
void T_(); 
void F(); 
void A(); 
void M(); 
void V(); 

void S(){
	if(sign==0){
		printf("S ");
		if(key[i]==1){
			V();
			if(sign==0&&key[i]==31){
				i++;
				E();
			}
			else{
				sign=1;
				printf("\nS处出现错误\n");
			}
		}
		else{
			sign=1;
			printf("\nS处出现错误\n");
		}
	}
}
void E(){
	if(sign==0){
		printf("->E ");
		if(key[i]==23||key[i]==1){
			T();
			if(sign==0){
				if(key[i]==16||key[i]==17){
					E_();
				}else if(key[i]==24||key[i]==-1){
					return;
				}else{
					sign=1;
					printf("\nE处出现错误\n");
				}
			}
		}else{
			sign=1;
			printf("\nE处出现错误\n");
		} 
	}
}
void E_(){
	if(sign==0){
		printf("->E' ");
		if(key[i]==16||key[i]==17){
			A();
			if(sign==0){
				if(key[i]==23||key[i]==1){
					T();
					if(sign==0){
						if(key[i]==16||key[i]==17){
							E_();
						}else if(key[i]==24||key[i]==-1){
							return;
						}else{
							sign=1;
							printf("\nE'处出现错误\n");
						}
					}
				}else{
					sign=1;
					printf("\nE'处出现错误\n");
				}
			}
		}else if(key[i]==24||key[i]==-1){
			return;
		}else{
			sign=1;
			printf("\nE'处出现错误\n");
		}
	}
}
void T(){
	if(sign==0){
		printf("->T ");
		if(key[i]==23||key[i]==1){
			F();
			if(sign==0){
				if(key[i]==18||key[i]==19){
					T_();
				}else if(key[i]==16||key[i]==17||key[i]==24||key[i]==-1){
					return;
				}else{
					sign=1;
					printf("\nT处出现错误\n");
				}
			}
		}else{
			sign=1;
			printf("\nT处出现错误\n");
		}
	}
}
void T_(){
	if(sign==0){
		printf("->T' ");
		if(key[i]==18||key[i]==19){
			M();
			if(sign==0){
				F();
				if(sign==0){
					T_();
				}
			}
		}else if(key[i]==16||key[i]==17||key[i]==24||key[i]==-1){
			return;
		}else{
			sign=1;
			printf("\nT'处出现错误\n");
		}
	}
}
void F(){
	if(sign==0){
		printf("->F ");
		if(key[i]==23){
			i++;
			if(key[i]==23||key[i]==1){
				E();
				if(sign==0){
					if(key[i]==24){
						i++;
					}
					else{
						sign=1;
						printf("\nF处出现错误\n");
					}
				}
			}
			else{
				sign=1;
				printf("\nF处出现错误\n"); 
			}
		}
		else if(key[i]==1){
			i++;
		}
		else{
			sign=1;
			printf("\nF处出现错误\n");
		}
	}
}
void A()
{
	if(sign==0){
		printf("->A ");
		if(key[i]==16||key[i]==17){
			i++;
		}
		else{
			sign=1;
			printf("\nA处出现错误\n");
		}
	}
}
void M()
{
	if(sign==0){
		printf("->M");
		if(key[i]==18||key[i]==19){
			i++;
		}
		else{
			sign=1;
			printf("\nM处出现错误\n");
		}
	}
}
void V()
{
	if(sign==0){
		printf("->V ");
		if(key[i]==1){
			i++;
		}
		else{
			sign=1;
			printf("\nV处出现错误\n");
		}
	}
}
int main(){
	FILE *fp;
	char buf[MAX_LENG]={0};//用于保存文件词法分析的结果 
	char shuru[MAX_LENG]={0};//shuru为待检测的语句
	int len;//buf的长度 
	int k=0,x=0,j=0;
	printf("词法分析二元式序列:\n");
	if((fp=fopen("demo_out.txt","r"))!=NULL){
		while(fgets(buf,MAX_LENG,fp)!=NULL){//每次读取一行 
			len=strlen(buf);
			buf[len]='\0';//去除换行符 
			printf("%s \n",buf); 
			for(i=0;i<len;i++){
				if(buf[i]=='('){//将单词符号类别编码转换成数字 
					if(buf[i+2]!=',')//如果是十位数数字
						key[j++]=int((buf[i+1]-'0')*10+buf[i+2]-'0');
					else//如果是个位数数字 
						key[j++]=int(buf[i+1]-'0');
					continue;
				}
				if(buf[i]==','){
					i++;
					if(buf[i]==')')//解决(24,))的情况 
					{
						shuru[x++]=')';
						i++;
						continue;
					}
					while(buf[i]!=')'){//分析的词法可能多个字符,如果没有while则只能保存一个字符 
						shuru[x++]=buf[i];
						i++;	
					}
				}
			}
		}
	}
	shuru[x++]='#';
	key[j++]=-1;
	fclose(fp);
	printf("算术表达式为:\n%s\n",shuru);
	printf("算术表达式的单词符号类别编码依次为:\n");
	for(i=0;i<j;i++)
	printf("%d ",key[i]);
	printf("\n");
	if(key[0]==-1)//当输入的第一个字符为#,直接结束 
	return 0;
	printf("递归下降语法分析过程:\n"); 
	i=0;
	S();
	printf("\n");
	if(key[i]==-1&&sign==0){
		printf("此语句合法!\n");
	}else{
		printf("此语句不合法!\n");
	}
	return 0;
}

六、程序测试

输入为词法分析程序的二元式序列

测试用例1

(1,a)(31,=)(1,b)(18,*)(1,c)(16,+)(1,d)(16,+)(1,e)

测试结果1

测试用例2

(1,a)(31,=)(1,b)(18,*)(1,c)(16,+)(23,()(1,d)(16,+)(1,e)(24,))

测试结果2

测试用例3

(1,a)(31,=)(1,b)(18,*)(1,c)(16,+)(1,d)(16,+)(1,e)(24,))

测试结果3

测试用例4

(1,p)(31,=)(1,a)(16,+)(23,()(1,b)(18,*)(23,()(1,c)(16,+)(1,d)(24,))(19,/)(1,e)(16,+)(23,()(1,x)(16,+)(1,y)(24,))

测试结果4


如果对你有帮助,不妨点个赞~~~

  • 28
    点赞
  • 173
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
编译原理中,语法分析是编译过程中的一个重要阶段,它用于验证源代码是否符合语法规则,并构建抽象语法树(AST)表示源代码的结构。在C语言中,可以使用各种方法来实现语法分析。 一种常见的方法是使用上下文无关文法(CFG)和自顶向下的递归下降分析法。下面是一个简单的示例: ```c #include <stdio.h> // 定义全局变量 int lookahead; // 函数声明 void expr(); void term(); void factor(); void match(int t); // 获取下一个输入符号 void getNextToken() { lookahead = getchar(); } // 匹配输入符号与预期符号 void match(int t) { if (lookahead == t) { getNextToken(); } else { printf("Syntax error\n"); } } // 表达式解析 void expr() { term(); while (1) { if (lookahead == '+') { match('+'); term(); printf("+ "); } else if (lookahead == '-') { match('-'); term(); printf("- "); } else { break; } } } // 项解析 void term() { factor(); while (1) { if (lookahead == '*') { match('*'); factor(); printf("* "); } else if (lookahead == '/') { match('/'); factor(); printf("/ "); } else { break; } } } // 因子解析 void factor() { if (lookahead == '(') { match('('); expr(); match(')'); } else if (isdigit(lookahead)) { printf("%c ", lookahead); match(lookahead); } else { printf("Syntax error\n"); } } int main() { printf("Enter an arithmetic expression: "); getNextToken(); expr(); printf("\n"); return 0; } ``` 上述代码实现了一个简单的四则运算语法分析器,它可以解析输入的算术表达式并输出其后缀表达式形式。在这个例子中,我们使用递归下降的方法根据语法规则逐步解析输入符号。具体来说,我们定义了expr、term和factor等函数来表示不同的语法规则,并使用match函数来匹配输入符号和预期符号。 请注意,这只是一个简单的示例,实际上,C语言的语法非常复杂,需要定义更多的语法规则和处理逻辑才能完整地实现C语言语法分析。实际的C语言编译器会使用更复杂的算法和数据结构来进行语法分析,如LR分析、LL分析、语法制导翻译等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四月天行健

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值