SLR(1)方法的出现,解决了大部分的移进和规约冲突、规约和规约的冲突。并且SLR(1)其优点是状态数目少,造表算法简单,大多数程序设计语言基本上都可用SLR(1)文法来描述。

但是仍然有一些文法,不能用SLR(1)解决。

例如:

S->BB;

B->aB;

B->b;

该文法我们可以看到,在S->BB中,第一个B和第二个B的follow集是不同的。为了解决这个问题,于是诞生了LR(1)分析方法。

解决办法是在每个项目集的产生式后加上follow集。比如:

S-> ·BB, #

B-> · aB, a/b

B-> · b ,a/b

这样就是是同一个非终结符,但是仍旧可以根据不同状态集内的产生式的follow集进行不冲突的规约和移进。

目前LR(1)分析法仍旧是应用非常广泛,是当前最一般的分析方法,几乎所有的上下文无关文法描述的程序设计语言都可以通过LR(1)分析法分析。

为了解决LR(1)分析法状态过多的问题,于是提出了LALR(1)分析法,将“心”相同的状态合并,从而减少状态数。

具体例子如下:

文法G[E]

(0)S’->S

(1)S->BB

(2)B->Ab

(3)B->b

1、构造项目集

2、构造LR(分析表)

状态

a

b

#

S

B

0

S3

S4

1

2

1

Acc

2

S6

S7

5

3

S3

S4

8

4

R3

R3

5

R1

6

S6

S7

9

7

R3

8

R2

R2

9

R2

3、编程

  1 #include<bits/stdc++.h>
2 #define ROW 11
3 #define COLUMN 6
4 using namespace std;
5 //产生式
6 string products[4][2]={
7 {"S'","S"},
8 {"S","BB"},
9 {"B","aB"},
10 {"B","b"}
11 };
12 //分析表
13 string actiontable[ROW][COLUMN]={
14 {"","a","b","#","S","B"},
15 {"0","s3","s4","","1","2"},
16 {"1","","","acc","",""},
17 {"2","s6","s7","","","5"},
18 {"3","s3","s4","","","8"},
19 {"4","r3","r3","","",""},
20 {"5","","","r1","",""},
21 {"6","s6","s7","","","9"},
22 {"7","","","r3","",""},
23 {"8","r2","r2","","",""},
24 {"9","","","r2","",""}
25 };
26 stack<int> sstatus; //状态栈
27 stack<char> schar; //符号栈
28 struct Node{
29 char type;
30 int num;
31 };
32 //打印步骤
33 void print_step(int times){
34 stack<char> tmp2;
35 cout<<times<<setw(4);
36 while(!schar.empty()){
37 char t=schar.top();
38 schar.pop();
39 tmp2.push(t);
40 cout<<t;
41 }
42 while(!tmp2.empty()){
43 int t=tmp2.top();
44 tmp2.pop();
45 schar.push(t);
46 }
47 }
48 //查表
49 Node Action_Goto_Table(int status,char a){
50 int row=status+1;
51 string tmp;
52 for(int j=1;j<COLUMN;j++){
53 if(a==actiontable[0][j][0]){
54 tmp=actiontable[row][j];
55 }
56 }
57 Node ans;
58 if(tmp[0]>='0'&&tmp[0]<='9'){
59 int val=0;
60 for(int i=0;i<tmp.length();i++){
61 val=val*10+(tmp[i]-'0');
62 }
63 ans.num=val;
64 ans.type=' ';
65 }else if(tmp[0]=='s'){
66 int val=0;
67 for(int i=1;i<tmp.length();i++){
68 val=val*10+(tmp[i]-'0');
69 }
70 ans.type='s';
71 ans.num=val;
72 }else if(tmp[0]=='r'){
73 int val=0;
74 for(int i=1;i<tmp.length();i++){
75 val=val*10+(tmp[i]-'0');
76 }
77 ans.type='r';
78 ans.num=val;
79 }else if(tmp[0]=='a'){
80 ans.type='a';
81 }else{
82 ans.type=' ';
83 }
84 return ans;
85 }
86 //LR(1)分析法
87 bool LR1(string input){
88 while(!sstatus.empty()){
89 sstatus.pop();
90 }
91 while(!schar.empty()){
92 schar.pop();
93 }
94 int times=0;
95 bool flag=true;
96 int st=0;
97 sstatus.push(st);
98 schar.push('#');
99 int i=0;
100 char a=input[i];
101 while(true){
102 Node action=Action_Goto_Table(st,a);
103 if(action.type=='s'){
104 st=action.num;
105 sstatus.push(st);
106 schar.push(a);
107 a=input[++i];
108 print_step(++times);
109 cout<<setw(10)<<'s'<<st<<endl;
110
111 }else if(action.type=='r'){
112 int n=action.num;
113 string ls=products[n][0];
114 string rs=products[n][1];
115 for(int j=0;j<rs.length();j++){
116 sstatus.pop();
117 schar.pop();
118 }
119 schar.push(ls[0]);
120 st=sstatus.top();
121 action =Action_Goto_Table(st,ls[0]);
122 st=action.num;
123 sstatus.push(st);
124 print_step(++times);
125 cout<<setw(10)<<'r'<<" "<<ls<<"->"<<rs<<endl;
126
127 }else if(action.type=='a'){
128 flag=true;
129 break;
130 }else{
131 flag=false;
132 break;
133 }
134 }
135 return flag;
136 }
137 int main(){
138 string input;
139 while(cin>>input){
140 if(LR1(input)){
141 cout<<"syntax correct"<<endl;
142 }else{
143 cout<<"syntax error"<<endl;
144 }
145 }
146 return 0;
147 }

LR(1)分析法的更多相关文章

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

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

  2. 【编译原理】自底向上分析方法——LR文法分析方法的总结

    LR(0).SLR(1).LR(1).LALR(1) de 若干方面的区别 目录 推导过程 分析能力 本质区别 文法对比 可以适当利用物理意义对二义性文法进行冲突处理 推导过程 LR(0)的基础上才有 ...

  3. 【转】LR分析法

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

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

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

  5. 从Elo Rating System谈到层次分析法

    1. Elo Rating System Elo Rating System对于很多人来说比较陌生,根据wikipedia上的解释:Elo评分系统是一种用于计算对抗比赛(例如象棋对弈)中对手双方技能水 ...

  6. Procrustes Analysis普氏分析法

    选取N幅同类目标物体的二维图像,并用上一篇博文的方法标注轮廓点,这样就得到训练样本集: 由于图像中目标物体的形状和位置存在较大偏差,因此所得到的数据并不具有仿射不变性,需要对其进行归一化处理.这里采用 ...

  7. AX中四种库存ABC分析法原理研究

    库存ABC分类,简单的说就是抓大放小,是为了让我们抓住重点,用最大精力来管理最重要的物料,而对于不太重要的物料则可以用较少的精力进行管理.它和我们平常说的八二法则有异曲同工之妙. 既然要应用库存ABC ...

  8. 黑盒测试用例设计方法&理论结合实际 -> 边界值分析法

    一. 概念 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法.通常边界值分析法是作为对等价类划分法的补充,这种情况下,其测试用例来自等价类的边界. 二. 边界值分析法的应用 根据大量的测 ...

  9. 帕累托分析法(Pareto Analysis)(柏拉图分析)

    帕累托分析法(Pareto Analysis)(柏拉图分析) ABC分类法是由意大利经济学家帕雷托首创的.1879年,帕累托研究个人收入的分布状态图是地,发现少数人收入占全部人口收入的大部分,而多数人 ...

  10. SWOT分析法

    SWOT(Strengths Weakness Opportunity Threats)分析法,又称为态势分析法或优劣势分析法,用来确定企业自身的竞争优势(strength).竞争劣势(weaknes ...

随机推荐

  1. LeetCode买卖股票之一:基本套路(122)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 关于<LeetCode买卖股票>系列 在L ...

  2. 全局安装oh-my-zsh保姆教程

    我的系统是CentOS 7.6,按流程走完后可以实现系统内所有用户都默认使用zsh且插件配置共享省去重复编写配置或软连接的烦恼 1 安装git yum -y install git 2 安装zsh y ...

  3. CVE-2018-8120 漏洞复现

    CVE-2018-8120 漏洞复现 漏洞描述 win32k.sys中函数 SetImeInfoEx未对指针进行合法性检查,从而导致一个任意地址写. 漏洞分析 漏洞成因 int __stdcall S ...

  4. js原生 toggle函数编写

    工作中遇到了需要动态切换slide下拉框展示与隐藏,同时需要切换元素上附加的样式,以下脚本为实现此功能的实践. //元素点击时切换隐藏与展示逻辑 var slidsDownShow = documen ...

  5. Vue-基本语法及事件绑定

    一.基本语法 v-bind绑定: 双大括号不能在 HTML attributes 中使用.想要响应式地绑定一个 attribute,应该使用 v-bind 指令 代码展示: <div id=&q ...

  6. Python基于Flask的高校舆情分析,舆情监控可视化系统

    一.前言在当今社会,舆情监控越来越被重视.随着互联网技术的发展,我们从传统媒体渠道.官方报告.调查问卷等方式搜集到的舆情信息,逐渐被网络上的内容所替代.因为网络上的内容传播速度快.及时性强.覆盖范围广 ...

  7. 多租户基于Springboot+MybatisPlus实现使用一个数据库一个表 使用字段进行数据隔离

    多租户实现方式 多租户在数据存储上主要存在三种方案,分别是: 1. 独立数据库 即一个租户一个数据库,这种方案的用户数据隔离级别最高,安全性最好,但成本较高. 优点:为不同的租户提供独立的数据库,有助 ...

  8. c语言代码练习4(改进)

    #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <string.h> #include <wi ...

  9. 【RocketMQ】Dledger模式下的日志复制

    RocketMQ在开启Dledger时,使用DLedgerCommitLog,其他情况使用的是CommitLog来管理消息的存储.在Dledger模式下,消息写入时Leader节点还需要将消息转发给F ...

  10. Python面向对象——封装

    文章目录 内容回顾 封装 为何要隐藏? 作业 内容回顾 上节课复习: 1.编程范式/思想 面向过程 介绍: 核心是"过程"二字 过程就是"流水线" 过程终极奥义 ...