我是靠谱客的博主 灵巧黑夜,最近开发中收集的这篇文章主要介绍语法分析器——自顶向下的递归分析法,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前文:

最近课程实验有点多且难,上一次编译原理做完词法分析器后,这一次终于把语法分析器给撸出来了。通过这一次的实验发现,词法分析器做的有很多不严谨的地方,因为词法分析器不应该是一个独立的,而是需要和语法分析器甚至下面的语义相关联,所以在一开始我们就应该对其有一定的规划,但是刚开始的时候没有这个意识,在网上看了相关代码之后只是觉得符合要求就提交上去了。于是觉得应该对词法分析器加以改进,故重新撸了一篇词法分析器的博文。这一次是语法分析器,先来看看我们老师的要求吧。

题目要求

在这里插入图片描述
可以看到这里要求递归下降分析,这个就不多说了。还有一个拓展要求,要求错误恢复和提示,这个依据恐慌模式来做,不懂?可以看一下这个视频。

代码分析:

一下代码是我昨晚一点多撸完的,感觉太臃肿了,应该分成项目来做,至少也得多个头文件,但是由于时间太赶,先原文贴出。

代码有点偏长,九百多行,其中大部分是词法分析器的,所以最好看一下我的上一篇关于词法分析器的代码。

#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>

int  wordanalysis();
void Irparser();
void yucu();
void statement();
void expression();
void term();
void factor();
void One();
void Two();
void Three();
void is_equal();
void not_equal();
void is_four_cal();
void not_four_cal();
void is_colon();
void not_right();
void not_biaozhifu();


using namespace std;


//BEGIN
//
//
//a = 10;
//b = a + 10;
//e = a + b
//end#


//保留字的种别码。从1开始到25
//出现过的标识符的种别码设为26
//未出现过的标识符种别码为52,将该标识符保存到标识符表中
//数字种别码设为27
// 等号种别码为28
// <= 种别码为29.
// <> 种别码为30。
// < 种别码为31
// >= 种别码为32
// > 种别码为33.
// + 种别码为34
// - 种别码为35
// * 种别码为36
// / 种别码 53
// ;种别码为38
// = 种别码为28
//1到51为正常的。空格为100, 换行符为101, #号为102,错误为404
//case '(': syn = 39; 
//case ')': syn = 40; 

int i, row = 0, line = 0; //line用来保存标识符的个数。row来保存数字个数。i保存读到哪个字符了
char test[1000];  //这是读取文件的内容的。 
int number[100];	//常数表,有个疑问,数字需要常数来保存吗?
char mark[100][5];   //用来存放标识符的。
int count = 1; //记录出错的行号 
int syn;
int wu;
int final_flag = 0;
//关键字:
char pro[100][100] = { "PROGRAM", "BEGIN", "END", "VAR", "INTEGER", "WHILE",
"IF", "THEN", "ELSE", "DO", "PROCEDURE" ,"char",
"int","if","else","var" ,"return","break",
"do","while","for","double","float","short", "main" };
//关键字:从1开始到25.

void Irparser() {
	printf("语法分析n");
	i = 0;
	count = 1;
	wu = wordanalysis();
	while (wu == 100 || wu == 101) {
		i++;
		wu = wordanalysis();
	}
	if (syn == 2) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		yucu();
		//yucu()函数结束之后,把空格和换行过滤掉
		if (syn == 3) {
			i++;
			wu = wordanalysis();
			while (wu == 100 || wu == 101) {
				i++;
				wu = wordanalysis();
			}
			if (syn == 102 && final_flag == 0) {
				printf("成功");
			}
			else {
				printf("这是一串失败的语句");
			}
		}
		else {
			printf("缺少END");
		}
	}
	else {
		printf("开头缺少BEGINn");
		final_flag = 1;
		// 看这个单词,如果是BEGIN的下一个找文件内容下一个单词与他匹配,否则就还是从BEGIN开始,单词从下一个找
		//BEGIN的下一个是END或者标识符
		if (syn == 3 || syn == 26 || syn == 52) {
			if (syn == 3) {
				One();
			}
			else if (syn == 26 || syn == 52) {
				Two();
			}
		}
		else {
			Three();
		}
	}
}

//当当前这一位是BEGIN的FOLLOW集END时
void One() {
	i++;
	wu = wordanalysis();
	while (wu == 100 || wu == 101) {
		i++;
		wu = wordanalysis();
	}
	if (syn == 102 && final_flag == 0) {
		printf("成功");
	}
	else {
		printf("这是一串失败的语句");
	}
}

// 当当前这一位是BEGIN的follow集标识符时。
void Two() {
	i++;
	wu = wordanalysis();
	while (wu == 100 || wu == 101) {
		i++;
		wu = wordanalysis();
	}
	yucu();
	//yucu()函数结束之后,把空格和换行过滤掉
	if (syn == 3) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		if (syn == 102 && final_flag == 0) {
			printf("成功");
		}
		else {
			printf("这是一串失败的语句");
		}
	}
	else {
		printf("缺少END");
	}
}

//这个是当前单词不是BEGIN的FOLLOW集,所以选择下一个单词。
void Three() {
	i++;
	wu = wordanalysis();
	while (wu == 100 || wu == 101) {
		i++;
		wu = wordanalysis();
	}
	if (syn == 2) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		yucu();
		//yucu()函数结束之后,把空格和换行过滤掉
		if (syn == 3) {
			i++;
			wu = wordanalysis();
			while (wu == 100 || wu == 101) {
				i++;
				wu = wordanalysis();
			}
			if (syn == 102 && final_flag == 0) {
				printf("成功");
			}
			else {
				printf("这是一串失败的语句");
			}
		}
		else {
			printf("缺少END");
		}
	}
	else {
		printf("第%d行缺少BEGINn", count);
		final_flag = 1;
		// 看这个单词,如果是BEGIN的下一个找文件内容下一个单词与他匹配,否则就还是从BEGIN开始,单词从下一个找
		//BEGIN的下一个是END或者标识符
		if (syn == 3 || syn == 26 || syn == 52) {
			if (syn == 3) {
				One();
			}
			else if (syn == 26 || syn == 52) {
				Two();
			}
		}
		else {
			Three();
		}
	}
}




void yucu() {
	statement();
	//如果是;,则不断循环下去
	while (syn == 38) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		statement();
	}
}

void statement() {
	//如果是标识符
	if (syn == 26 || syn == 52) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		//如果标识符后面为=
		if (syn == 28) {
			i++;
			wu = wordanalysis();
			while (wu == 100 || wu == 101) {
				i++;
				wu = wordanalysis();
			}
			expression();
		}
		else {
			printf("第%d行等号赋值错误n", count);
			final_flag = 1;
			//当跟=不匹配时,我们知道=的FOLLOW集为标识符(这里的标识符为26
			//出现过的标识符的种别码设为26
			//未出现过的标识符种别码为52,
			if (syn == 26) {
				expression();
			}
			else {
				not_biaozhifu();
			}
		}
	}
	else {
		printf("第%d行标识符有错误n", count);
		final_flag = 1;
		//这里出现不是标识符的情况,那么如果这个单词是标识符的FOLLOW集,即
		//=,所以看这个单词是=吗,要是不是的话,那就直接下一个单词匹配是否是标识符
		if (syn == 28) {
			is_equal();
		}
		else {
			not_equal();
		}
	}
}

void not_biaozhifu() {
	i++;
	wu = wordanalysis();
	while (wu == 100 || wu == 101) {
		i++;
		wu = wordanalysis();
	}
	if (syn == 28) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		expression();
	}
	else {
		printf("第%d行等号赋值错误n", count);
		final_flag = 1;
		//当跟=不匹配时,我们知道=的FOLLOW集为标识符(这里的标识符为26
		//出现过的标识符的种别码设为26
		//未出现过的标识符种别码为52,
		if (syn == 26) {
			expression();
		}
		else {
			not_biaozhifu();
		}
	}
}


void is_equal() {
	i++;
	wu = wordanalysis();
	while (wu == 100 || wu == 101) {
		i++;
		wu = wordanalysis();
	}
	expression();
}

void not_equal() {
	i++;
	wu = wordanalysis();
	while (wu == 100 || wu == 101) {
		i++;
		wu = wordanalysis();
	}
	if (syn == 26 || syn == 52) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		//如果标识符后面为=
		if (syn == 28) {
			i++;
			wu = wordanalysis();
			while (wu == 100 || wu == 101) {
				i++;
				wu = wordanalysis();
			}
			expression();
		}
		else {
			printf("第%d行等号赋值错误n", count);
			final_flag = 1;
			//当跟=不匹配时,我们知道=的FOLLOW集为标识符(这里的标识符为26
			//出现过的标识符的种别码设为26
			//未出现过的标识符种别码为52,
			if (syn == 26) {
				expression();
			}
			else {
				not_biaozhifu();
			}
		}
	}
	else {
		printf("第%d行标识符有错误n", count);
		final_flag = 1;
		//这里出现不是标识符的情况,那么如果这个单词是标识符的FOLLOW集,即
		//=,所以看这个单词是=吗,要是不是的话,那就直接下一个单词匹配是否是标识符
		if (syn == 28) {
			is_equal();
		}
		else {
			not_equal();
		}
	}
}

void expression() {
	term();
	//当时加或者减的时候
	while (syn == 34 || syn == 35) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		term();
	}
}
void term() {
	factor();
	// 当为/或者*的时候
	while (syn == 53 || syn == 36) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		factor();
	}
}
void factor() {
	// 后面是数字或者出现过的标识符
	if (syn == 26 || syn == 27) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
	}
	// 如果是(
	else if (syn == 39) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		expression();
		// 如果是)的话
		if (syn == 40) {
			i++;
			wu = wordanalysis();
			while (wu == 100 || wu == 101) {
				i++;
				wu = wordanalysis();
			}
		}
		else {
			printf("第%d行有错误, 缺少)n", count);
			final_flag = 1;
			//如果不是的话,那么)的FOLLOW集应该是加减乘除或者;或者END
			if (syn == 34 || syn == 35 || syn == 36 || syn == 53 || syn == 38 || syn == 3) {
				if (syn == 34 || syn == 35 || syn == 36 || syn == 53) {
					is_four_cal();
				}
				// 如果是;38
				if (syn == 38) {
					is_colon();
				}
				// 如果是END
				if (syn == 3) {
					One();
				}
			}
			else {
				// 代表没有)的FOLLOW集
				not_right();
			}
		}
	}
	else {
		printf("第%d行输出表达式有错误n", count);
		final_flag = 1;
		//这里我们看到标识符或者数字下一个即FOLLOW集应该是加减乘除或者;或者END
		if (syn == 34 || syn == 35 || syn == 36 || syn == 53 || syn == 38 || syn == 3) {
			if (syn == 34 || syn == 35 || syn == 36 || syn == 53) {
				is_four_cal();
			}
			// 如果是;38
			if (syn == 38) {
				is_colon();
			}
			// 如果是END
			if (syn == 3) {
				One();
			}
		}
		else {
			not_four_cal();
		}
		
	}
}

void not_right() {
	i++;
	wu = wordanalysis();
	while (wu == 100 || wu == 101) {
		i++;
		wu = wordanalysis();
	}
	// 如果是)的话
	if (syn == 40) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
	}
	else {
		printf("第%d行有错误, 缺少)n", count);
		final_flag = 1;
		//如果不是的话,那么)的FOLLOW集应该是加减乘除或者;或者END
		if (syn == 34 || syn == 35 || syn == 36 || syn == 53 || syn == 38 || syn == 3) {
			if (syn == 34 || syn == 35 || syn == 36 || syn == 53) {
				is_four_cal();
			}
			// 如果是;38
			if (syn == 38) {
				is_colon();
			}
			// 如果是END
			if (syn == 3) {
				One();
			}
		}
		else {
			// 代表没有)的FOLLOW集
			not_right();
		}
	}
}


void is_colon() {
	while (syn == 38) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		statement();
	}
}

void not_four_cal() {
	i++;
	wu = wordanalysis();
	while (wu == 100 || wu == 101) {
		i++;
		wu = wordanalysis();
	}
	// 后面是数字或者出现过的标识符
	if (syn == 26 || syn == 27) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
	}
	// 如果是(
	else if (syn == 39) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		expression();
		// 如果是)的话
		if (syn == 40) {
			i++;
			wu = wordanalysis();
			while (wu == 100 || wu == 101) {
				i++;
				wu = wordanalysis();
			}
		}
		else {
			printf("第%d行有错误, 缺少)n", count);
			final_flag = 1;
			//如果不是的话,那么)的FOLLOW集应该是加减乘除或者;或者END
			if (syn == 34 || syn == 35 || syn == 36 || syn == 53 || syn == 38 || syn == 3) {
				if (syn == 34 || syn == 35 || syn == 36 || syn == 53) {
					is_four_cal();
				}
				// 如果是;38
				if (syn == 38) {
					is_colon();
				}
				// 如果是END
				if (syn == 3) {
					One();
				}
			}
			else {
				// 代表没有)的FOLLOW集
				not_right();
			}
		}
	}
	else {
		printf("输出表达式有错误n");
		final_flag = 1;
		//这里我们看到标识符或者数字下一个即FOLLOW集应该是加减乘除或者;或者END
		if (syn == 34 || syn == 35 || syn == 36 || syn == 53 || syn == 38 || syn == 3) {
			if (syn == 34 || syn == 35 || syn == 36 || syn == 53) {
				is_four_cal();
			}
			// 如果是;38
			if (syn == 38) {
				is_colon();
			}
			// 如果是END
			if (syn == 3) {
				One();
			}
		}
		else {
			not_four_cal();
		}

	}
}

void is_four_cal() {
	//当时加或者减的时候
	while (syn == 34 || syn == 35) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		term();
	}

	// 当为/或者*的时候
	while (syn == 53 || syn == 36) {
		i++;
		wu = wordanalysis();
		while (wu == 100 || wu == 101) {
			i++;
			wu = wordanalysis();
		}
		factor();
	}
}




//过滤
void guolv() {
	char temp[1000];
	int flag = 0;
	int j = 0;
	while (test[flag] != '#') {
		//单行注释// 
		if (test[flag] == '/' && test[flag + 1] == '/') {
			while (test[flag] != 'n') {
				flag++;
			}
		}
		else if (test[flag] == '/' && test[flag + 1] == '*') {
			//多行注释/**/ 
			flag = flag + 2;
			while (test[flag] != '*' && test[flag + 1] != '/') {
				flag++;
			}
			flag = flag + 2;
		}
		temp[j] = test[flag];
		flag++;
		j++;
	}
	temp[j] = '#';
	strcpy(test, temp);
}

//词法分析
int wordanalysis()
{
	//标识符和保留字
	//当第一个字符是字母的时候
	if ((test[i] >= 'A'&&test[i] <= 'Z') || (test[i] >= 'a'&&test[i] <= 'z'))
	{
		char word[10];
		//保留字的种别码。从1开始到25

		int n = 0;
		word[n++] = test[i++];
		while ((test[i] >= 'A'&&test[i] <= 'Z') || (test[i] >= '0' && test[i] <= '9') || (test[i] >= 'a'&&test[i] <= 'z'))
		{
			word[n++] = test[i++];
		}
		word[n] = '';
		i--;

		//判断该标识符是否为保留字
		for (n = 0; n < 100; n++)
		{
			if (strcmp(word, pro[n]) == 0)
			{
				syn = n + 1;
				printf(">> %st(%d,-) 保留字n", pro[n], syn);
				return syn;
			}
		}

		//不是关键字的话,判断该标识符是否在标识符表中
		int m = 0;
		if (line != 0)
		{
			int q = 0;
			while (q<line)
			{
				if (strcmp(word, mark[q++]) == 0)
				{
					syn = 26; //出现过的标识符的种别码设为26
					printf(">> %st(%d,%d) 标识符n", word, syn, q);
					return syn;
				}
			}

		}
		//未出现过的标识符种别码为52,将该标识符保存到标识符表中
		strcpy(mark[line], word);
		syn = 52;
		printf(">> %st(%d, %d) 标识符n", word, syn, line + 1);
		line++;
		return syn;

	}
	//数字 
	else if (test[i] >= '0' && test[i] <= '9')
	{
		char x[100];
		int n = 0;
		x[n++] = test[i++];

		while (test[i] >= '0' && test[i] <= '9')
		{
			x[n++] = test[i++];
		}
		x[n] = '';
		i--;
		int num = atoi(x); //将字符串转换成int型

						   //判断该常数是否存在于常数表中
		if (row != 0)
		{

			for (int y = 0; y<row; y++)
			{
				if (number[y] == num)
				{
					syn = 27; //数字种别码设为27
					printf(">> %dt(%d,%d)n", num, syn, y + 1);
					return syn;
				}
			}
		}

		//将该常数保存到标识符表中
		number[row] = num;
		int line = row;
		syn = 27;
		printf(">> %dt(%d,%d)n", num, syn, line + 1);
		row++;
		return syn;
	}

	//各种符号
	else {
		switch (test[i])
		{
		case '=': syn = 28; // 等号种别码为28
			printf(">> =t(%d,-)n", syn); return syn;
		case '<':
			i++;
			if (test[i] == '=')
			{
				syn = 29; // <= 种别码为29.
				printf(">> <= t(%d,-)n", syn);
				return syn;
			}
			else if (test[i] == '>')
			{
				syn = 30; // <> 种别码为30。
				printf(">> <>t(%d,-)n", syn);
				return syn;
			}
			else
			{
				i--;
				syn = 31; // < 种别码为31
				printf(">> <t(%d,-)n", syn);
				return syn;
			}
		case '>':
			i++;
			if (test[i] == '=')
			{
				syn = 32; // >= 种别码为32
				printf(">> >=t(%d,-)n", syn);
				return syn;
			}
			else
			{
				i--;
				syn = 33; // > 种别码为33.
				printf(">> >t(%d,-)n", syn);
				return syn;
			}
		case '+': syn = 34; printf(">> +t(%d,-)n", syn); return syn; // + 种别码为34
		case '-': syn = 35;  printf(">> -t(%d,-)n", syn); return syn; // - 种别码为35
		case '*': syn = 36;  printf(">> *t(%d,-)n", syn); return syn; // * 种别码为36
		case '/': syn = 53; printf(">> *t(%d, -)n", syn); return syn; // /的种别码为53 
																		//case '/':
																		//	i++;
																		//	//if (test[i] == '/') {
																		//	//	//单行注释:
																		//	//	while (1) {
																		//	//		if (test[i++] == 'n')
																		//	//			return -1;
																		//	//	}
																		//	//}
																		//	//else if (test[i] == '*') {
																		//	//	i++;
																		//	//	while (!(test[i] == '*' && test[i + 1] == '/')) {
																		//	//		i++;
																		//	//	}
																		//	//}
																		//	if (test[i] != '/') {
																		//		syn = 37;
																		//		i--;
																		//		printf(">> /t(%d,-)n", syn); return 3;
																		//	}

																		//	else {
																		//		//单行注释:
																		//		while (1) {
																		//			if (test[i++] == 'n')
																		//				return -1;
																		//		}
																		//		printf(">> //t(37,-)n"); return 3;

																		//	}

		case ':': syn = 37; printf(">> :t(%d,-)n", syn); return syn;
		case ';': syn = 38; printf(">> ;t(%d,-)n", syn); return syn;
		case '(': syn = 39; printf(">> (t(%d,-)n", syn); return syn;
		case ')': syn = 40; printf(">> )t(%d,-)n", syn); return syn;
		case '{': syn = 41; printf(">> {t(%d,-)n", syn); return syn;
		case '}': syn = 42; printf(">> }t(%d,-)n", syn); return syn;
		case '[': syn = 43; printf(">> [t(%d,-)n", syn); return syn;
		case ']': syn = 44; printf(">> ]t(%d,-)n", syn); return syn;
		case '|': syn = 45; printf(">> |t(%d,-)n", syn); return syn;
		case '"': syn = 46; printf(">> "t(%d,-)n", syn); return syn;
		case ',': syn = 47; printf(">> ,t(%d,-)n", syn); return syn;
		case ''': syn = 48; printf(">> 't(%d,-)n", syn); return syn;//单引号
		case '&':
			i++;
			if (test[i] != '&') {
				i--;
				// & 种别码为 49;
				syn = 49;
				printf(">> &t(%d,-)n", syn); return syn;
			}
			//&&种别码为50
			syn = 50;
			printf(">> &&t(%d,-)n", syn); return syn;
			//  种别码为51
		case '\': syn = 51; printf(">> \t(%d,-)n", syn); return syn;

		case ' ':
			syn = 100; // 空格种别码为28
			return syn;
		case 'n':count++;
			syn = 101; // 换行符种别码为29
			return syn;
		case '#': syn = 102; //结束符#种别码为30. 
			return syn;
		default:
			syn = 404; //错误的种别码为404
			printf(">> %c error in %d rown", test[i], count);
			return syn;
		}
	}

}

int main()
{

	int c = 0;
	int m;
	i = 0;
	//读取文件
	FILE *fp;
	fp = fopen("D:\yes.txt", "r");
	if (fp == NULL)
	{
		printf("can't open file!n");
		exit(0);
	}
	//把文件内容读取到test数组中
	while (!feof(fp))
	{
		test[c++] = fgetc(fp);
	}
	test[c] = '#';
	while (test[i] != '#') {
		printf("%c", test[i]);
		i++;
	}
	printf("n");
	printf("------------过滤后的-------------n");
	guolv();
	i = 0;
	while (test[i] != '#') {
		printf("%c", test[i]);
		i++;
	}
	printf("n");
	printf("输出文法分析后的:n");
	//1到51为正常的。空格为100, 换行符为101, #号为102,错误为404
	/*do
	{
	m = wordanalysis();

	switch (m)
	{
	case -1:i++; break;
	case 0: i++; break;
	case 3: i++; break;
	}
	} while (m != 0);*/
	Irparser();
	return 0;
}

文件内容:

BEGIN
a = 10;
//fad a = b + c;
b = a + 10;
e = a + b;
d = (a + b) + e;
d = (a + b)
END#

输出:

BEGIN
a = 10;
//fad a = b + c;
b = a + 10;
e = a + b;
d = (a + b) + e;
d = (a + b)
END
------------过滤后的-------------
BEGIN
a = 10;

b = a + 10;
e = a + b;
d = (a + b) + e;
d = (a + b)
END
输出文法分析后的:
语法分析
>> BEGIN        (2,-) 保留字
>> a    (52, 1) 标识符
>> =    (28,-)
>> 10   (27,1)
>> ;    (38,-)
>> b    (52, 2) 标识符
>> =    (28,-)
>> a    (26,1) 标识符
>> +    (34,-)
>> 10   (27,1)
>> ;    (38,-)
>> e    (52, 3) 标识符
>> =    (28,-)
>> a    (26,1) 标识符
>> +    (34,-)
>> b    (26,2) 标识符
>> ;    (38,-)
>> d    (52, 4) 标识符
>> =    (28,-)
>> (    (39,-)
>> a    (26,1) 标识符
>> +    (34,-)
>> b    (26,2) 标识符
>> )    (40,-)
>> +    (34,-)
>> e    (26,3) 标识符
>> ;    (38,-)
>> d    (26,4) 标识符
>> =    (28,-)
>> (    (39,-)
>> a    (26,1) 标识符
>> +    (34,-)
>> b    (26,2) 标识符
>> )    (40,-)
>> END  (3,-) 保留字
成功
--------------------------------
Process exited after 0.3427 seconds with return value 0
请按任意键继续. . .

最后

以上就是灵巧黑夜为你收集整理的语法分析器——自顶向下的递归分析法的全部内容,希望文章能够帮你解决语法分析器——自顶向下的递归分析法所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(77)

评论列表共有 0 条评论

立即
投稿
返回
顶部