JMU软件工程编译原理实验四

实验四 利用预测分析表构造语法分析程序

1.实验目的: 熟悉语法分析阶段的要求,掌握LL(1)语法分析的原理,利用预测分析方式构造语法分析器。

2. 实验设备: 硬件:PC 机一台; 软件:Windows系统;高级语言集成开发环境。

3. 实验内容: 利用LL(1)预测分析法构造语法分析器。

4. 实验要求及步骤:

文法G(E):

E→TE’

E’→+TE’ | 空

T→FT’

T’→*FT’|空

F→(E) | i

  1. 证明上述文法是LL(1)文法;
  1. 文法不含左递归
  2. 对于文法中每一个非终结符A的各个产生式的候选首符集两两不相交。
  3. first集和follow集交集为空:

First(E)={(,i}

First(E’)={+,ε}

First(T)={(,i}

First(T’)={*,ε}

First(F)={(,i}

Follow(E)={),#}

Follow(E’)={),#}

Follow(T)={+,),#}

Follow(T’)={+,),#}

Follow(F)={*,+,),#}

  1. 构造预测分析表;

string table[5][6] = {

{"error","error","TM","error","TM","error" },

{"+TM","error","error","","error",""},

{"error","error","FN","error","FN","error"} ,

{"","*FN","error","","error",""} ,

{"error","error","(E)","error","i","error"} };

  1. 利用预测分析表实现以上文法的语法分析器;

                         见代码

  1. 自设10个输入语句(每个语句多加一个#作为结束标记),展示这10个语句经该语法分析器分析后的结果,如果正确输出“Right”,错误输出“ERROR”并输出判错时指针所指符号。

代码如下:

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

using namespace std;


int a;//当前正在读的字符的下标
char VT[7] = { '+','*','(',')','i','#' };//终结符号
int length_vt = 6;//终结符号的个数
char VN[6] = { 'E','M','T','N','F' };//非终结符号用M代替了E' 用N代替了T’
int length_vn = 5;//非终结符号的个数
string equation[8] = { "TM","+TM","","FN","*FN","","(E)","i" };//产生式表
stack<char> sta;//分析栈
bool flag = false;//判断分析是否结束
string str;//存放用户输入的字符串
string used;//所使用的产生式
string table[5][6] = {
{"error","error","TM","error","TM","error" },
{"+TM","error","error","","error",""},
{"error","error","FN","error","FN","error"} ,
{"","*FN","error","","error",""} ,
{"error","error","(E)","error","i","error"} };//预测分析表

bool is_vn()//判断是否为非终结符
{
	if ((sta.top() >= 'A') && (sta.top() <= 'Z'))
		return true;
	else
		return false;
}


void init()//做初始化
{
	sta.push('#');
	sta.push('E');//将'#'和起始符号先入栈
	str = str + '#';//将输入串最后加一个‘#’结束符。
	a = 0;
}

void analyse()//对一个字符的分析情况
{
	string s;//所使用的的产生式
	if (is_vn() == false)//判断是否为非终结符
	{
		if (str[a] == '#' && (sta.top() == '#'))
		{
			cout << "分析成功..." << endl;
			flag = true;
			return;
		}
		else if (sta.top() == str[a])//如果栈顶元素和当前字符一致,则读入下一个字符,且栈顶元素出栈
		{
			s = s + str[a] + "匹配";
			used = s;
			//		cout << "当前栈顶元素" << sta.top() << "当前字符" << str[a] << endl;
			a++;
			sta.pop();
			return;
		}
		else
		{
			flag = true;//已经判断出了该句子不属于此文法,所以分析结束
			cout << "该句子不属于该文法" << endl;
			return;
		}
	}
	else {
		for (int i = 0; i < length_vn; i++)//查表判断
		{
			if (sta.top() == VN[i])
			{
				for (int j = 0; j < length_vt; j++)
				{
					if (VT[j] == str[a])
					{
						if (table[i][j] == "error")
						{
							cout << "预测分析表没有对应的产生式" << endl;
							flag = true;//已经判断出了该句子不属于此文法,所以分析结束
							return;
						}
						else if (table[i][j] == "")
						{
							s = s + VN[i];
							s = s + "->空";
							used = s;//将使用的产生式放入used
							sta.pop();
							return;
						}
						else//将当前栈顶出栈,将预测分析表对应的产生式右部进栈
						{
							sta.pop();
							for (int z = table[i][j].length() - 1; z >= 0; z--)
							{
								sta.push(table[i][j][z]);
							}
							s = s + VN[i] + "->" + table[i][j];
							used = s;
							return;
						}
					}
				}
				cout << "error:这个输入串中的字符不属于该文法" << endl;
				flag = true;
				return;
			}
		}
		cout << "error:该栈顶的符号不属于该文法" << endl;
		flag = true;
		return;
	}
}

string printstack()//顺序输出栈中的符号
{
	string s;//存放栈中的符号
	string sf;//栈中的元素的反序
	int  num = sta.size();
	for (int i = 0; i < num; i++)//把sta栈的内容给s
	{
		sf = sf + sta.top();
		sta.pop();
	}
	for (int i = num - 1; i >= 0; i--)//反序
	{
		s = s + sf[i];
	}
	for (int i = 0; i < num; i++)//恢复sta
	{
		sta.push(s[i]);
	}
	return s;
}

string getstr()//返回输入串
{
	string s;
	for (int i = a; i < str.length(); i++)
	{
		s = s + str[i];
	}
	return s;
}

int main()
{
	cout << "请输入一个字符串:" << endl;
	cin >> str;
	init();
	int step = 0;
	cout << "     " << "步骤" << "     " << "符号栈" << "     " << "输入串" << "     " << "所用产生式" << endl;
	while (flag == false)
	{
		cout <<"     " << step << "     " << printstack() << "     " << getstr() << "     " << used << endl;
		analyse(); 
		step++;
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hiOoo.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值