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的更多相关文章

  1. 【转】LR分析法

    转自:http://guanjy0129.blog.163.com/blog/static/1115494452010614113333509/ LR分析法的归约过程是规范推导的逆过程,所以LR分析过 ...

  2. 编译原理(六)自底向上分析之LR分析法

    自底向上分析之LR分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本概念 1. LR分析:从左到右扫描(L)自底向上进行规约(R),是规范规约,也即最右推导(规范推导) ...

  3. 编译原理 LR分析(主要是LR(0)分析)

    一.LR分析的基本原理 1.LR分析的基本思想 LR方法的基本思想就是,在规范归约的过程中,一方面要记住已移进和归约出的整个字符串,也就是说要记住历史:一方面能够根据所用的产生式的推测未来可能碰到的输 ...

  4. 编译原理 算法3.8 LR分析 c++11实现

    LR分析简介 LR分析是应用最广泛的一类分析方法,它是实用的编译器功能中最强的分析器,其特点是: 1,采用最一般的无回溯移进-规约方法. 2,可分析的文法是LL文法的真超集. 3,能够及时发现错误,及 ...

  5. 《编译原理》LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析

    <编译原理>LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析 笔记 直接做题是有一些特定步骤,有技巧.但也必须先了解一些基本概念,本篇会通过例题形式解释概念,会容易理解和记忆,以 ...

  6. 编译原理--02 自顶向下、自底向上的LR分析复习(清华大学出版社第3版)

    前言 目录 01 文法和语言.词法分析复习 02 自顶向下.自底向上的LR分析复习 03 语法制导翻译和中间代码生成复习 04 符号表.运行时存储组织和代码优化复习 第4章 自顶向下的语法分析方法 确 ...

  7. 编译原理-第四章 语法分析-4.7 规范的LR分析

    规范的LR分析 一.规范LR(l)项 二.规范LR(l)项集族 1.构建项目集 2.例 三.规范LR(1)语法分析表 1.构造 2.例1 3.例2 四.LALR语法分析表 1.重要性 2.特点 3.构 ...

  8. LR分析Analysis火车票

    一.分析结果 1 研究 Vuser 的行为(F:\JMeter\0Tutorial-SCR\机票预订\机票_analysis-session) 筛选该图,仅查看所有 Vuser 同时运行的时间段 右键 ...

  9. LR(0)文法项目集规范族、DFA和分析表的构建实例

    最近在复习编译原理,考试之前以为自己懂了,眼高手低就没去实践.结果一考试出问题了.... 学习就要脚踏实地,容不得半点模糊.凭着侥幸心理很危险的.以后要引以为戒啊. 特别写出这篇文章 :一来总结一下这 ...

随机推荐

  1. arcgis10.2 serverstyle 制作工具位置 小计

    跟9.3时候的套路还是一样的,只是工具已经放到了arcgis desktop的安装目录的bin文件夹下面. engine和developerkit都不附带该工具. 但是engine会附带一组默认的转换 ...

  2. integer storage and decimal storage differences in java

    package storage.java; public class StorageJava { public static void main(String[] args) { byte b = 1 ...

  3. Word 最后一页无法删除-解决办法

    Word 最后一页无法删除-解决办法 制服 word 最后一页无法删除 今天在做一个简历的时候,编辑 word 文档的时候,最后一页空白页怎么也删不掉,百度了很多方法之后,只有一个可行,记录一下. 1 ...

  4. 使用PermissionsDispatcher轻松解决Android权限问题

    之前也处理过6.0后的权限问题,直接处理很是麻烦.这次在github上搜到了关于权限星数最多的PermissionsDispatcher这个库,几个注释完美解决权限问题. 第一步 添加各种注释 1.@ ...

  5. 瞥了一眼js

    JS打开超链接的几种形式1.window.open(''url'') 2.用自定义函数<script>function openWin(tag,obj){obj.target=" ...

  6. HTML5新增的标签和属性归纳

    收集总结的HTML5的新特性,基本除了IE9以下都可以使用. HTML5语法 大部分延续了html的语法 不同之处:开头的 <!DOCTYPE html> <html lang=&q ...

  7. SVN global ignore pattern

    *.o *.lo *.la *.al .libs *.so *.so.[0-9]* *.a *.pyc *.pyo *.rej *~ #*# .#* .*.swp .DS_Store */bin */ ...

  8. NJCTF2017 web getflag(详解)

    题目: url:http://218.2.197.235:23725/ writeup: 首先随便输入后查看源码: <imgsrc="data:image/png;base64,Y2F ...

  9. Programming Assignment 2: Seam Carving

    编程作业二 作业链接:Seam Carving & Checklist 我的代码:SeamCarver.java 问题简介 接缝裁剪(Seam carving),是一个可以针对照片内容做正确缩 ...

  10. pip install lxml mysql-python error

    问题0: 在安装 mysql-python时,会出现: sh: mysql_config: not found Traceback (most recent call last): File &quo ...