递归下降语法分析

烈酒焚心 提交于 2019-12-06 03:23:56

一、实验目的:

利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

 

二、实验原理

每个非终结符都对应一个子程序。

该子程序根据下一个输入符号(SELECT集)来确定按照哪一个产生式进行处理,再根据该产生式的右端:

  • 每遇到一个终结符,则判断当前读入的单词是否与该终结符相匹配,若匹配,再读取下一个单词继续分析;不匹配,则进行出错处理
  • 每遇到一个非终结符,则调用相应的子程序

 

三、实验要求说明

输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。

例如:

输入begin a:=9;x:=2*3;b:=a+x end #

输出success

输入x:=a+b*c  end #

输出‘end' error

 

四、实验步骤

1.待分析的语言的语法(参考P90)

2.将其改为文法表示,至少包含

–语句

–条件

–表达式

3. 消除其左递归

4. 提取公共左因子

5. SELECT集计算

6. LL(1)文法判断

7. 递归下降分析程序

各种单词符号对应的种别码

单词符号 种别码 单词符号 种别码
begin 1 : 17
if 2 := 18
then 3 < 20
while 4 <> 21
do 5 <= 22
end 6 > 23
letter(letter+digit)* 10 >= 24
digit* 11 = 25
+ 13 : 26
- 14 ( 27
* 15 ) 28
/ 16 # 0

#include<stdio.h>

#include<stdlib.h>
#include<string.h>

//程序段  单词 
char prog[800], dc[8];
//单词中的字符 
char ch;
//单词符号种别码
int syn, p, m = 0;
//整数sum 
int n, sum = 0;
//保留字 
char *word[6] = { "begin","if","then","while","do","end" };
//判断是否有错误 
int kk = 0;

void scaner();
void lrparser();
void yucu();
void statement();
void condition();
void expression();
void term();
void factor();

void scaner() {
	m = 0;
	for (n = 0; n < 8; n++) {
		dc[n] = NULL;
	}
	ch = prog[p++];

	while (ch == ' ') {
		ch = prog[p];
		//指针+1往后移一位
		p++;
	}

	//判断输入是否位数字或字母
	if ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z')) {
		m = 0;
		while ((ch >= '0'&&ch <= '9') || (ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z')) {
			dc[m++] = ch;
			ch = prog[p++];
		}
		p--;
		syn = 10;
		//保留字 
		for (n = 0; n < 6; n++) {
			if (strcmp(dc, word[n]) == 0) {
				syn = n + 1;
				break;
			}
		}
	}
	//数字 
	else if ((ch >= '0'&&ch <= '9')) {
		sum = 0;
		while ((ch >= '0'&&ch <= '9')) {
			sum = sum * 10 + ch - '0';
			ch = prog[p++];
		}
		p--;
		syn = 11;
	}
	else {
		switch (ch) {
		case '<':m = 0;
			dc[m++] = ch;
			ch = prog[p++];
			if (ch == '>') {
				syn = 22;
				dc[m++] = ch;
			}
			else if (ch == '=') {
				syn = 21;
				dc[m++] = ch;
			}
			else {
				syn = 20;
				p--;
			}
			break;
		case '>':m = 0;
			dc[m++] = ch;
			ch = prog[p++];
			if (ch == '=') {
				syn = 24;
				dc[m++] = ch;
			}
			else {
				syn = 23;
				p--;
			}
			break;
		case ':':m = 0;
			dc[m++] = ch;
			ch = prog[p++];
			if (ch == '=') {
				syn = 18;
				dc[m++] = ch;
			}
			else {
				syn = 17;
				p--;
			}
			break;
		case '*':
			syn = 15; 
			dc[0] = ch; 
			break;
		case '/':
			syn = 16; 
			dc[0] = ch; 
			break;
		case '+':
			syn = 13; 
			dc[0] = ch; 
			break;
		case '-':
			syn = 14; 
			dc[0] = ch; 
			break;
		case '=':
			syn = 25; 
			dc[0] = ch; 
			break;
		case ';':
			syn = 26; 
			dc[0] = ch; 
			break;
		case '(':
			syn = 27; 
			dc[0] = ch;
			break;
		case ')':
			syn = 28; 
			dc[0] = ch; 
			break;
		case '#':
			syn = 0; 
			dc[0] = ch;
			break;
		case '\n':
			syn = -2; 
			dc[0] = ch; 
			break;
		}
	}
}

//判断是否以begin开始,end #结束 
void lrparser() {
	//begin
	if (syn == 1) {
		scaner();
		yucu();
		//end
		if (syn == 6) {
			scaner();
			if (syn == 0 && kk == 0) {
				printf("success \n");
			}
		}
		else {
			printf("编译出错,缺少 'end' ! \n");
			kk = 1;
			exit(0);
		}
	}
	else {
		printf("编译出错缺少 'begin' ! \n");
		kk = 1;
		exit(0);
	}
	return;
}

//语句串 
void yucu() {
	statement();
	while (syn == 26) {
		scaner();
		statement();
	}
	return;
}
//语句 
void statement() {
	//为标识符
	if (syn == 10) {
		scaner();
		if (syn == 18) { //:=
			scaner();
			expression();
		}
		else {
			printf("error!");
			kk = 1;
			exit(0);
		}
	}
	else if (syn == 2) {  //if 
		condition();
		scaner();
		if (syn == 3) {
			statement();
		}
		else {
			printf("编译出错缺少 'then' ! \n");
			kk = 1;
			exit(0);
		}
	}
	else {
		printf("error!");
		kk = 1;
		exit(0);
	}

	return;
}
//条件
void condition() {
	expression();
	if (syn == 25 || syn == 0 || syn == 20 || syn == 21 || syn == 23 || syn == 24) {
		scaner();
	}
	else {
		printf("error! \n");
		kk = 1;
		exit(0);
	}
	expression();
	return;
}
//表达式 
void expression() {
	term();
	while (syn == 13 || syn == 14) {
		scaner();
		term();
	}
	return;
}
//项 
void term() {
	factor();
	while (syn == 15 || syn == 16) {
		scaner();
		factor();
	}
	return;
}
//因子 
void factor() {
	if (syn == 10 || syn == 11) {
		//为标识符或整常数时,读下一个单词符号
		scaner();
	}
	else if (syn == 27) {
		scaner();
		expression();
		if (syn == 28) {
			scaner();
		}
		else {
			printf(" ')' 错误\n");
			kk = 1;
			exit(0);
		}
	}
	else {
		printf("表达式错误\n");
		kk = 1;
		exit(0);
	}
	return;
}
int main(void) {
	
	//从0开始逐个读取
	p = 0;
	int i;
	printf("请输入源程序:\n");
	do {
		scanf("%c", &ch);
		prog[p++] = ch;
	} while (ch != '#');
	//指针从0开始 
	p = 0;
	do {
		scaner();
		lrparser();
	} while (syn != 0);
	printf("语法分析结束!\n");

}


运行结果

 

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!