前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LR--用栈实现移进--归约分析(demo)

LR--用栈实现移进--归约分析(demo)

作者头像
Enterprise_
发布2019-02-20 11:37:35
4870
发布2019-02-20 11:37:35
举报
文章被收录于专栏:小L的魔法馆小L的魔法馆
1.考虑文法

E−>E+EE->E+EE−>E+E E−>E∗EE->E*EE−>E∗E E−>idE->idE−>id

2.最右推导

不难看出,这个文法是而二义的,所以有多个最右推导

3.移进归约

用一个栈存文法符号,用输入缓存区保存要分析的输入串,用$标记栈底

代码语言:javascript
复制
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<stack>
using namespace std;
stack<string> stk, tmp;
string w;
bool flag = false;
int main(void) {
	cin >> w;	//输入串
	w += "$";	//加上标识符
	printf("----------|----------|----------\n");
	printf("    栈    |   输入   |    动作  \n");
	printf("----------|----------|----------\n");
	int now = 0;	//当前扫描字符位置
	while (!flag) {
		now = 0;
		if (stk.empty()) {	//如果一开始栈为空,直接移进符号
			stk.push("$");
			cout << "$         |";
			cout.setf(ios::right);	//设置字符对其方式
			cout.width(10);			//设置字符宽度
			cout << w;
			cout<< "|移进" << endl;
			printf("----------|----------|----------\n");
			string tt;
			if (w[now] == 'i') {	//移进符号为id
				tt = "id";
				now = 2;
			}
			else {					//移进符号不为id
				tt = w[now];
				now = 1;
			}
			stk.push(tt);			//将符号压入栈
			w = w.substr(now, w.size() - now);	//丢弃已扫描的字符
			continue;
		}
		while (!stk.empty()) {		//用两个栈来回倒,输出字符
			tmp.push(stk.top());
			stk.pop();
		}
		while (!tmp.empty()) {
			cout << tmp.top();
			stk.push(tmp.top());
			tmp.pop();
		}
		if (stk.top() == "id") {	//E-->id归约,优先级最高
			cout.width(10-stk.size());
			cout << "|";
			cout.setf(ios::right);	//设置字符对其方式
			cout.width(10);			//设置字符宽度
			cout << w;
			cout<< "|按E-->id进行归约" << endl;
			printf("----------|----------|----------\n");
			stk.pop();
			stk.push("E");
			continue;
		}
		if (w[now]=='$'&&stk.size() == 2 && stk.top() == "E") {		//接受状态
			flag = true;
			cout<< "        |         $|接受"<< endl;
			printf("----------|----------|----------\n");
			continue;
		}
		if (w[now]!='$') {		//移进字符
			string tp;
			if (w[now] == 'i') {
				tp = "id";
				now = 2;
			}
			else {
				tp = w[now];
				now = 1;
			}
			cout.width(11 - stk.size());
			cout << "|";
			cout.setf(ios::right);	//设置字符对其方式
			cout.width(10);			//设置字符宽度
			cout << w;
			cout<< "|移进" << endl;
			printf("----------|----------|----------\n");
			stk.push(tp);
			w = w.substr(now, w.size() - now);	//丢弃已扫描的字符
			continue;
		}
		if (w[now] == '$'  &&!flag) {	//E-->E+E或者E-->E*E归约
			string  tc;
			tc = stk.top();
			if (tc == "E")
				stk.pop();
			tc += stk.top();
			if (stk.top() != "E") {
				stk.pop();
				tc += stk.top();
				cout.setf(ios::right);	//设置字符对其方式
				cout.width(9- stk.size());//设置字符宽度
				cout << "|";
				cout << "         $|";
				cout << "按E-->"<<tc<<"归约" << endl;
				printf("----------|----------|----------\n");
				stk.pop();
				stk.push("E");
			}
		}
	}
	return 0;
}
4.Sample

输入

代码语言:javascript
复制
id*id+id
在这里插入图片描述
在这里插入图片描述
5. To be continued.
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年11月10日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.考虑文法
  • 2.最右推导
  • 3.移进归约
  • 4.Sample
  • 5. To be continued.
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档