1.考虑文法

\(E->E+E\)

\(E->E*E\)

\(E->id\)

2.最右推导

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

3.移进归约

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

#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

输入

id*id+id

5.To be continued.

LR--用栈实现移进--归约分析(demo)的更多相关文章

  1. Java性能分析之线程栈详解与性能分析

    Java性能分析之线程栈详解 Java性能分析迈不过去的一个关键点是线程栈,新的性能班级也讲到了JVM这一块,所以本篇文章对线程栈进行基础知识普及以及如何对线程栈进行性能分析. 基本概念 线程堆栈也称 ...

  2. 表单input中提示文字value随鼠标焦点移进移出而显示或隐藏的

    jQuery代码 <input value="请输入用户名" type="text"> <input value="请输入密码&qu ...

  3. 大数据江湖之即席查询与分析(下篇)--手把手教你搭建即席查询与分析Demo

    上篇小弟分享了几个“即席查询与分析”的典型案例,引起了不少共鸣,好多小伙伴迫不及待地追问我们:说好的“手把手教你搭建即席查询与分析Demo”啥时候能出?说到就得做到,差啥不能差人品,本篇只分享技术干货 ...

  4. C语言函数调用时候内存中栈的动态变化详细分析(彩图)

    版权声明:本文为博主原创文章,未经博主允许不得转载.欢迎联系我qq2488890051 https://blog.csdn.net/kangkanglhb88008/article/details/8 ...

  5. Apache Flink:特性、概念、组件栈、架构及原理分析

     2016-04-30 22:24:39    Yanjun Apache Flink是一个面向分布式数据流处理和批量数据处理的开源计算平台,它能够基于同一个Flink运行时(Flink Runtim ...

  6. CVE-2018-18820 icecast 栈缓冲区越界写漏洞分析

    前言 icecast 是一款开源的流媒体服务器 , 当服务器配置了 url 认证时,服务器在处理 HTTP 头部字段时错误的使用了 snprintf 导致栈缓冲区的越界写漏洞( CVE-2018-18 ...

  7. Android可见APP的不可见任务栈(TaskRecord)销毁分析

    Android依托Java型虚拟机,OOM是经常遇到的问题,那么在快达到OOM的时候,系统难道不能回收部分界面来达到缩减开支的目的码?在系统内存不足的情况下,可以通过AMS及LowMemoryKill ...

  8. linux内核中打印栈回溯信息 - dump_stack()函数分析【转】

    转自:http://blog.csdn.net/jasonchen_gbd/article/details/45585133 版权声明:本文为博主原创文章,转载请附上原博链接.   目录(?)[-] ...

  9. 栈的讲解 和 栈的生长方向 源代码技巧分析,简直没SEI 啦

    函数的局部变量,都是存放在"栈"里面,栈的英文是:STACK.STACK的大小,我们可以在stm32的启动文件里面设置,以战舰stm32开发板为例,在startup_stm32f1 ...

随机推荐

  1. Cloud Computing Causing Digital Business Transformation

    2015-04-13 Cloud Computing Causing Digital Business Transformation We hear all about the cloud, and  ...

  2. change grayscale to pseudo colouring using colormap in Matlab

    change grayscale to pseudo colouring using colormap in Matlab In matlab you can view a grayscale ima ...

  3. 【Angularjs】ng-repeat中使用ng-model遇到的问题

    总结:在ng-repeat中ng-model的问题,原因是ng-model对controller中的$scope是不可见的,所以在使用repeat中的某个对象的属性的时候,最好还是将该对象或者该对象的 ...

  4. 毕向东_Java基础视频教程第20天_IO流(15~17)

    第20天-15-IO流(打印输出流) 打印输出流:PrintWriter与PrintStream 两者的区别:Since JDK 1.4 it's possible to specify the ch ...

  5. 无法安装64位office,因为已有32位版本怎么办

  6. 购买 In-app Billing 商品

    购买 In-app Billing 商品 一旦你的应用连接上了 Google Play,你就可以初始化内购商品的购买请求了.Google Play 提供了结算接口,可以让用户进入使用他们的支付方式,所 ...

  7. C# 托管非托管资源释放

    1.C#几乎所有对象都为托管对象,不同点是有的对象封装了非托管资源. 2.C#大部分对象在进行垃圾回收时都可以回收,包括非托管资源,因为非托管资源都已经通过C#类进行了封装,会将非托管资源的释放放在析 ...

  8. Linux命令--网络管理

    write命令 Linux write命令用于传讯息给其他使用者. 使用权限:所有使用者. 语法 write user [ttyname] 参数说明: user : 预备传讯息的使用者帐号 ttyna ...

  9. error MSB8031: Building an MFC project for a non-Unicode character set is deprecated. You must change the project property to Unicode or download an additional library. See http://go.microsoft.co

    Win10,也重新装了免费版的Visual Studio 2013 y,写MFC程序时候发现这样的提示: error MSB8031: Building an MFC project for a no ...

  10. win7装postgresql10.4

    第一步: 第二步: 第三步: 第四步: 第五步: 下载地址:https://get.enterprisedb.com/postgresql/postgresql-10.4-1-windows-x64. ...