LR(1)分析法
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)分析法的更多相关文章
- 《编译原理》LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析
<编译原理>LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析 笔记 直接做题是有一些特定步骤,有技巧.但也必须先了解一些基本概念,本篇会通过例题形式解释概念,会容易理解和记忆,以 ...
- 【编译原理】自底向上分析方法——LR文法分析方法的总结
LR(0).SLR(1).LR(1).LALR(1) de 若干方面的区别 目录 推导过程 分析能力 本质区别 文法对比 可以适当利用物理意义对二义性文法进行冲突处理 推导过程 LR(0)的基础上才有 ...
- 【转】LR分析法
转自:http://guanjy0129.blog.163.com/blog/static/1115494452010614113333509/ LR分析法的归约过程是规范推导的逆过程,所以LR分析过 ...
- 编译原理(六)自底向上分析之LR分析法
自底向上分析之LR分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本概念 1. LR分析:从左到右扫描(L)自底向上进行规约(R),是规范规约,也即最右推导(规范推导) ...
- 从Elo Rating System谈到层次分析法
1. Elo Rating System Elo Rating System对于很多人来说比较陌生,根据wikipedia上的解释:Elo评分系统是一种用于计算对抗比赛(例如象棋对弈)中对手双方技能水 ...
- Procrustes Analysis普氏分析法
选取N幅同类目标物体的二维图像,并用上一篇博文的方法标注轮廓点,这样就得到训练样本集: 由于图像中目标物体的形状和位置存在较大偏差,因此所得到的数据并不具有仿射不变性,需要对其进行归一化处理.这里采用 ...
- AX中四种库存ABC分析法原理研究
库存ABC分类,简单的说就是抓大放小,是为了让我们抓住重点,用最大精力来管理最重要的物料,而对于不太重要的物料则可以用较少的精力进行管理.它和我们平常说的八二法则有异曲同工之妙. 既然要应用库存ABC ...
- 黑盒测试用例设计方法&理论结合实际 -> 边界值分析法
一. 概念 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法.通常边界值分析法是作为对等价类划分法的补充,这种情况下,其测试用例来自等价类的边界. 二. 边界值分析法的应用 根据大量的测 ...
- 帕累托分析法(Pareto Analysis)(柏拉图分析)
帕累托分析法(Pareto Analysis)(柏拉图分析) ABC分类法是由意大利经济学家帕雷托首创的.1879年,帕累托研究个人收入的分布状态图是地,发现少数人收入占全部人口收入的大部分,而多数人 ...
- SWOT分析法
SWOT(Strengths Weakness Opportunity Threats)分析法,又称为态势分析法或优劣势分析法,用来确定企业自身的竞争优势(strength).竞争劣势(weaknes ...
随机推荐
- python 获取本周 ,上周,本月,上月,本季,上季,今年, 去年的第一天和最后一天
import datetime from datetime import timedelta now = datetime.datetime.now()# 获取当前月的天数 month = 2days ...
- springBoot使用注解Aop实现日志模块
我们在日常业务操作中需要记录很多日志,可以在我们需要的方法中对日志进行保存操作,但是对业务代码入侵性大.使用切面针对控制类进行处理灵活度不高,因此我们可以使用自定义注解来针对方法进行日志记录 1.注解 ...
- JDK21来了!附重要更新说明
JDK21 计划23年9月19日正式发布,虽然一直以来都是"版本随便出,换 8 算我输",但这么多年这么多版本的折腾,如果说之前的 LTS版本JDK17你还觉得不香,那 JDK21 ...
- 一个颜值功能双在线的Zookeeper可视化工具
大家好,我是 Java陈序员,今天给大家介绍一个颜值功能双在线的 Zookeeper 可视化工具. 项目介绍 PrettyZoo 是一个基于 Apache Curator 和 JavaFX 实现的 Z ...
- 「loj - 3022」「cqoi 2017」老 C 的方块
link. good题,考虑像 国家集训队 - happiness 一样在棋盘上搞染色,我毛张 @shadowice1987 的图给你看啊 你像这样奇数层以 red -> blue -> ...
- PLC通过Modbus转Profinet网关与合康变频器Modbus通讯案例
PLC通过Modbus转Profinet网关(XD-MDPN100)与合康变频器Modbus通讯,实现了两个设备之间的数据交互.Profinet是一种基于以太网的实时工控网络协议,而Modbus是一种 ...
- ModbusTCP 转 Profinet 主站网关控制汇川伺服驱动器配置案例
ModbusTCP 转 Profinet 主站网关控制汇川伺服驱动器配置案例 ModbusTCP Client 通过 ModbusTCP 控制 Profinet 接口设备,Profinet 接口设备接 ...
- Flask框架——详解URL、HTTP请求、视图函数和视图类
文章目录 1 什么是url? 2 为什么要有url? 3 如何应用url? 3.1 url和路由的区别. 3.2 url传参的两种 3.2.1动态路由传参 3.2.1.1 动态路由的过滤 3.2.2 ...
- Python - 中文文本进行余弦相似度比较
今天,在看论文的时候,突然想到了一件事情,爱是相对的,是双方的事情.那么"你爱我"和"你爱我"的相似度是多少呢?采用余弦相似度的方式来进行相似度比较.首先&qu ...
- JAVA图搜索算法之DFS-BFS
图算法DFS与BFS BFS和DFS代表对图进行遍历,即搜索的算法,搜索算法中常用的只要有两种算法:深度优先遍历(Depth-First-Search : DFS)和广度优先遍历(Breadth-Fi ...