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. VB.NET Syntax Tips

    Difference Between C# and VB.NET Namespace VB.NET [Class Namespace in IL]=[Root Namespace].[Namespac ...

  2. Android Tab与TabHost

    这就是Tab,而盛放Tab的容器就是TabHost 如何实现?? 每一个Tab还对应了一个布局,这个就有点好玩了.一个Activity,对应了多个功能布局. ①新建一个Tab项目,注意,不要生成mai ...

  3. Python爬虫教程-00-写在前面

    鉴于好多人想学Python爬虫,缺没有简单易学的教程,我将在CSDN和大家分享Python爬虫的学习笔记,不定期更新 基础要求 Python 基础知识 Python 的基础知识,大家可以去菜鸟教程进行 ...

  4. Pig集群安装

    1.安装hadoop 这个之前已经写过 2.下载Pig,解压 3.保证Java和Hadoop已经在/etc/profile中配置 4.配置Pig安装目录 export PIG_INSTALL=/hom ...

  5. Vertical-Align: 关于inline,inline-block文本排版

    inline, inline-block元素在同行元素的排版布局中非常有用,但是时常会出现一些莫名奇妙的问题.要解决这些问题,深刻理解inline,inline-block元素的特征有非常重要的意义. ...

  6. 创建基于 AFS 的 Docker 容器卷

    标准的 Docker 容器卷一般是位于 Docker 主机上的一个本地目录.在这样的配置下,容器必须依赖于一台特定的主机,因此使得容器的迁移和扩展变得困难.通过使用容器卷插件,能让容器访问独立于主机的 ...

  7. VISO画UML用例图添加Include关系的方法

    VISO画UML用例图添加Include关系的方法 今天用Microsoft Visio 2007画用例图时,发现visio UML用例里面找不到include关系,查到一个可行的解决办法:  1)创 ...

  8. Django 的视图层

    什么是视图: 之前我们也了解了urls路由 那么路由的主要作用是决定你下一步走哪个视图函数 ,视图就是用来存放一个个的函数的python文件,主要存储的函数就是你Django主要的流程的控制 都存放在 ...

  9. Python学习---迭代器学习1210

    可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器和带yield的generator fun ...

  10. JavaScript --- Map集合结构详解

    Map 对象保存键值对.任何值(对象或者原始值) 都可以作为一个键或一个值. 语法 new Map([iterable]) 参数 iterable Iterable 可以是一个数组或者其他 itera ...