LR分析-demo2
0.LR分析
用一个栈来保存文法符号和状态的信息,一个字符串保存输入信息。
使用栈顶的状态符号和当前的输入符号来检索分析表,来决定移进-归约分析的动作。
1.样例文法
"E>E+T",
"E>T",
"T>T*F",
"T>F",
"F>(E)",
"F>id",
2.分析表(未全部列出)

3.code
//LR分析-demo2
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<stack>
#include<map>
using namespace std;
stack<string>stk, tmp, com; //stk是存入s0x1,即状态和符号的栈,tmp是用来输出的栈,
//com是在归约时确定归约式子的栈(防止错误弹出元素)
string input; //输入串
string slr[15][15]; //slr表
string action[] = { //slr表横轴动作+转换
"id","+","*","(",")","$","E","T","F"
};
//i就是id
string handle[] = { //文法
" ",
"E>E+T",
"E>T",
"T>T*F",
"T>F",
"F>(E)",
"F>id",
};
map<string, int> act, status; //转移表
map<string, int>::iterator it_act, it_trans;
string transfer[] = {
"E","T","F"
};
bool flag = false; //accept状态
int now = 0; //当前扫描字符位置
int handle_index = 0; //选中的规约式序号
void init() { //初始化,
int i = 0;
for (i = 0; i < 9;i++) {
act.insert(make_pair(action[i], i)); //建立分析表
}
int j = 0;
while (j<12) {
int i = j;
string t;
if (i < 10)
t = '0' + i;
else {
t = ('0' + (i / 10));
t += ('0' + i % 10);
}
status.insert(make_pair(t, j)); //将状态和数字对应
j++;
}
slr[0][0] = slr[4][0] = slr[6][0] = slr[7][0] = "s5"; //保存slr表
slr[1][1] = slr[8][1] = "s6";
slr[2][1] = slr[2][4] = slr[2][5] = "r2";
slr[2][2] = slr[9][2] ="s7";
slr[0][3] = slr[6][3] = slr[4][3] = slr[7][3] = "s4";
slr[1][5] = "acc";
slr[3][1] = slr[3][2] = slr[3][4] = slr[3][5] = "r4";
slr[5][1] = slr[5][2] = slr[5][4] = slr[5][5] = "r6";
slr[9][1] = slr[9][4] = slr[9][5] = "r1";
slr[8][4] = "s11";
slr[10][1] = slr[10][2] = slr[10][4] = slr[10][5] = "r3";
slr[11][1] = slr[11][2] = slr[11][4] = slr[11][5] = "r5";
slr[0][6] = "1";
slr[0][7] = slr[4][7] = "2";
slr[0][8] = slr[4][8] = slr[6][8] = "3";
slr[4][6] = "8";
slr[6][7] = "9";
slr[7][8] = "10";
}
void show() {
int count_two_char = 0; //数栈中超过两个字符的元素
while (!stk.empty()) { //用两个栈来回倒,输出字符
tmp.push(stk.top());
stk.pop();
}
while (!tmp.empty()) {
cout << tmp.top();
if (tmp.top().size()>1)
count_two_char++;
stk.push(tmp.top());
tmp.pop();
}
cout.setf(ios::right);
cout.width(11 - stk.size()- count_two_char);
cout << "|";
}
//参数1是状态,参数2是符号,符号包括终结符和非终结符,作用是找到slr表中项目
string slrFind(string stat,string ActionAndTransfer) {
string s = stat, a = ActionAndTransfer;
//cout << s + " " + a << endl;
int t1 = status[s]; //取出状态对应下标
int t2 = act[a]; //取出符号对应下标
string tmp;
if (slr[t1][t2] != "") //如果slr表中存在此项
tmp = slr[t1][t2];
else
tmp = "";
//cout << tmp << endl;
return tmp; //返回slr表中的项目
}
//参数1和2同slrFind函数,index是选中的规约式子序号
bool judge(string stat, string Transfer,int &index) {
string judg = slrFind(stat, Transfer); //得到slr表中项目
if (judg[0] != 'r') //如果这个项不是r开头,就不是归约
return false; //非归约直接返回
int i = judg[1] - '0'; //如果是归约,得到归约式子序号
index = i;
return true; //可以发起归约
}
void analysis(string s) {
string w = s;
//cout.setf(ios::right); //设置字符对其方式
//cout.width(10); //设置字符宽度
printf("----------|----------|----------\n");
printf(" 栈 | 输入 | 动作 \n");
printf("----------|----------|----------\n");
while (!flag) { //处于非接受状态
now = 0; //正在处理的输入串中的字符
if (stk.empty()) { //一开始栈为空,直接移进符号
stk.push("0");
cout << "0 |";
cout.setf(ios::right); //设置字符对其方式
cout.width(10); //设置字符宽度
cout << w;
cout << "|移进" << endl;
printf("----------|----------|----------\n");
string t1, t2;
t1 = stk.top();
if (w[now] == 'i') { //移进符号为id
t2 = "id";
now = 2;
}
else { //移进符号不为id
t2 = w[now];
now = 1;
}
stk.push(t2); //将符号压入栈
w = w.substr(now, w.size() - now); //丢弃已扫描的字符
string lr = slrFind(t1, t2); //找到对应的动作
if (lr[0] == 's') //此时是移进
lr = lr.substr(1, lr.size() - 1);
stk.push(lr);
continue;
}
show();
string serach;
if(w[0]!='i') //获取输入串的开头符号
serach =w.substr(0,1);
else
serach = w.substr(0, 2);
//cout << w[0]+""<< endl; //转换字符串不能这么做
if(judge(stk.top(), serach, handle_index)) { //归约,优先级最高
cout.setf(ios::right); //设置字符对其方式
cout.width(10); //设置字符宽度
cout << w;
cout << "|";
cout.setf(ios::left);
cout.width(10);
cout << "按" + handle[handle_index] + "归约" << endl;
printf("----------|----------|----------\n");
string ttt = handle[handle_index].substr(2, handle[handle_index].size() - 2); //得到产生式右部符号
while (ttt != "") {
if (ttt[0] == 'i'){ //将产生式右部所有非终结符暂时压入一个栈中
com.push("id");
ttt=ttt.substr(2, ttt.size() - 2);
}
else
{
string t5;
t5 = ttt[0];
com.push(t5);
ttt=ttt.substr(1, ttt.size() - 1);
}
}
while (!com.empty()) { //用这个有产生式右部所有非终结符的栈和当前栈比对,确定归约式正确
stk.pop();
string cmp1 = stk.top();
if (com.top()==cmp1) {
stk.pop();
com.pop();
}
}
string t3 = handle[handle_index];
t3 = t3[0]; //得到归约式的左部符号
string t4 = slrFind(stk.top(),t3); //用此时左部符号和当前栈顶来确认下一个动作
stk.push(t3);
stk.push(t4);
continue;
}
else { //移进操作--或者acc
cout.setf(ios::right); //设置字符对其方式
cout.width(10); //设置字符宽度
cout << w;
cout << "|";
cout.setf(ios::left);
cout.width(10);
string t1, t2;
t1 = stk.top();
if (w[now] == 'i') { //移进符号为id
t2 = "id";
now = 2;
}
else { //移进符号不为id
t2 = w[now];
now = 1;
}
stk.push(t2); //将符号压入栈
w = w.substr(now, w.size() - now); //丢弃已扫描的字符
string lr = slrFind(t1, t2); //找到对应的动作
if (lr[0] == 's'){ //如果是移进操作
lr = lr.substr(1, lr.size() - 1);
cout << "移进" << endl;
}
else if (lr == "acc") { //或者是接受状态
cout << "接受" << endl;
flag = true;
}
stk.push(lr);
printf("----------|----------|----------\n");
continue;
}
}
}
int main(void) {
init();
input = "id*id+id"; //输入串
input += "$";
analysis(input);
return 0;
}
4.样例输出

5. To be continued.
LR分析-demo2的更多相关文章
- 【转】LR分析法
转自:http://guanjy0129.blog.163.com/blog/static/1115494452010614113333509/ LR分析法的归约过程是规范推导的逆过程,所以LR分析过 ...
- 编译原理(六)自底向上分析之LR分析法
自底向上分析之LR分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本概念 1. LR分析:从左到右扫描(L)自底向上进行规约(R),是规范规约,也即最右推导(规范推导) ...
- 编译原理 LR分析(主要是LR(0)分析)
一.LR分析的基本原理 1.LR分析的基本思想 LR方法的基本思想就是,在规范归约的过程中,一方面要记住已移进和归约出的整个字符串,也就是说要记住历史:一方面能够根据所用的产生式的推测未来可能碰到的输 ...
- 编译原理 算法3.8 LR分析 c++11实现
LR分析简介 LR分析是应用最广泛的一类分析方法,它是实用的编译器功能中最强的分析器,其特点是: 1,采用最一般的无回溯移进-规约方法. 2,可分析的文法是LL文法的真超集. 3,能够及时发现错误,及 ...
- 《编译原理》LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析
<编译原理>LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析 笔记 直接做题是有一些特定步骤,有技巧.但也必须先了解一些基本概念,本篇会通过例题形式解释概念,会容易理解和记忆,以 ...
- 编译原理--02 自顶向下、自底向上的LR分析复习(清华大学出版社第3版)
前言 目录 01 文法和语言.词法分析复习 02 自顶向下.自底向上的LR分析复习 03 语法制导翻译和中间代码生成复习 04 符号表.运行时存储组织和代码优化复习 第4章 自顶向下的语法分析方法 确 ...
- 编译原理-第四章 语法分析-4.7 规范的LR分析
规范的LR分析 一.规范LR(l)项 二.规范LR(l)项集族 1.构建项目集 2.例 三.规范LR(1)语法分析表 1.构造 2.例1 3.例2 四.LALR语法分析表 1.重要性 2.特点 3.构 ...
- LR分析Analysis火车票
一.分析结果 1 研究 Vuser 的行为(F:\JMeter\0Tutorial-SCR\机票预订\机票_analysis-session) 筛选该图,仅查看所有 Vuser 同时运行的时间段 右键 ...
- LR(0)文法项目集规范族、DFA和分析表的构建实例
最近在复习编译原理,考试之前以为自己懂了,眼高手低就没去实践.结果一考试出问题了.... 学习就要脚踏实地,容不得半点模糊.凭着侥幸心理很危险的.以后要引以为戒啊. 特别写出这篇文章 :一来总结一下这 ...
随机推荐
- laravel middleware
当你使用larvel创建一个相对比较复杂的web网站时,往往你的routes文件就会变得很庞大.一般来说在开始网站编码之前,最好做一个整体规划,把这些route逻辑上划分为不同的group,每一个gr ...
- Python问题1:IndentationError:expected an indented block
Python语言是一款对缩进非常敏感的语言,给很多初学者带来了困惑,即便是很有经验的python程序员,也可能陷入陷阱当中.最常见的情况是tab和空格的混用会导致错误,或者缩进不对,而这是用肉眼无法分 ...
- package.json作用
这个文档的内容是你必须要知道的,它必须是JSON文本格式.每个项目的根目录下面,一般都有一个package.json文件,定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称.版本.许可证等元 ...
- select 1 from table 语句中的1代表什么意思
在这里我主要讨论的有以下几个select 语句: doo_archive表是一个数据表,表的行数为4行,如下: 分别用三条select语句select 1 from doo_archive.sele ...
- Mysql学习---索引的学习 180101
索引:约束 + 快速查找 索引是数据库中用于帮助用户快速查询数据的一种数据结构.类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取即可. 问:为什么索引可以这么快?[类似 ...
- Exchange Server 产品路线图 及 补丁下载
Exchange Server RU listExchange Server and Update Rollup Build Numbers -TechNet Articles -United Sta ...
- Apache Spark : Introduction
看了一点<数据算法:Hadoop/Spark大数据处理技巧>,觉得有必要了解一下 Spark . 以上. Spark was introduced by Apache Software F ...
- Entity Framework 指定架构无效 错误:1052
IIS发布网站:如果不发布放到IIS没有问题,发布后IIS部署 打开网站却提示指定架构无效 1052 找到很多解决的问题 1添加wenconfig 2.更改entity名的 其实我认为最简单的就是先找 ...
- DOM节点中获取文本易混淆的属性
DOM 节点中对于获取文本易混淆的属性,innerText, innerHTML, outerHTML, textContent, nodeValue. 一个实例: <!DOCTYPE html ...
- 14. Android框架和工具之 ImageLoader(图片加载)
1. 这个图片加载框架网友很多都已经使用过,而且分析也很到位,这里我就不写了,直接引用别人,尊重别人的劳动成果. 2. 参考如下: (1)Android 开源框架Universal-Image-Loa ...