SLR(1)分析法
由于LR(0)的能力实在是太弱了。例如:
I = { X=>α·bβ,
A=>α·,
B=>α· }
这时候就存在两个冲突。
1、移进和规约的冲突;
2、规约和规约的冲突。
SLR(1)就是为了解决冲突而设计的,解决冲突的方法就是向后多看一个字符,这就是SLR(1)。
简而言之就是为每个非终结符,计算出它们的follow集。从而可以解决移进与规约、规约与规约的冲突了。
SLR(1)所说的多看一个字符在构造分析表的时候就根据follow集已经构造好了,分析程序和LR(0)是一样的,分析表不同。
具体实现如下:
拓广文法 G'[S']:
(0) S'→S
(1) S→ABC
(2) A→Aa
(3) A→a
(4) B→Bb
(5) B→b
(6) C→Cc
(7) C→c
1、计算初始状态的项目集
Q0=CLOSURE({S'→•S })={ S'→•S , S→•ABC, A→•Aa, A→•a };
2、计算每个状态的项目集
Q1=GO(Q0,a)=CLOSURE({A→a •})={ A→a• };
Q2=GO(Q0,S)=CLOSURE({S'→S •})={ S'→S • };
Q3=GO(Q0,A) = CLOSURE({S→A•BC, A→A•a}) = {S→A•BC, A→A•a, B→•Bb, B→•b}; Q4=GO(Q3,a)=CLOSURE({A→Aa• })={ A→Aa• };
Q5=GO(Q3,b)=CLOSURE({B→b• })={ B→b•};
Q6=GO(Q3,B)=CLOSURE({S→AB•C, B→B•b }) ={ S→AB•C, B→B•b , C→•Cc , C→•c }; Q7=GO(Q6,b)=CLOSURE({B→Bb •})={ B→Bb •};
Q8=GO(Q6,c)=CLOSURE({C→c •})={ C→c •};
Q9=GO(Q6,C)=CLOSURE({S→ABC•, C→C•c })={ S→ABC•, C→C•c }; Q10=GO(Q9,c)=CLOSURE({C→Cc• })={ C→Cc•};
3、构造识别可归约前缀的 DFA
4、计算文法的 FIRST 和 FOLLOW 集合
非终结符 |
FIRST |
FOLLOW |
S |
a |
# |
A |
a |
a,b |
B |
b |
b,c |
C |
c |
c,# |
状态节点 Q9= { S→ABC•, C→C•c }中存在存在移进-规约冲突。
{b}∩FOLLOW(S) ={b}∩{#}=Φ,因此文法是 SLR(1)文法。
5、构造 SLR(1)分析表
a |
b |
c |
# |
S |
A |
B |
C |
|
0 |
S1 |
2 |
3 |
|||||
1 |
R3 |
R3 |
||||||
2 |
acc |
|||||||
3 |
S4 |
S5 |
6 |
|||||
4 |
R2 |
R2 |
||||||
5 |
R5 |
R5 |
||||||
6 |
S7 |
S8 |
9 |
|||||
7 |
R4 |
R4 |
||||||
8 |
R7 |
R7 |
||||||
9 |
S10 |
R1 |
||||||
10 |
R6 |
R6 |
实验程序:
1 #include<bits/stdc++.h>
2 #define ROW 12
3 #define COLUMN 9
4 using namespace std;
5 //产生式
6 string products[8][2]={
7 {"S'","S"},
8 {"S","ABC"},
9 {"A","Aa"},
10 {"A","a"},
11 {"B","Bb"},
12 {"B","b"},
13 {"C","Cc"},
14 {"C","c"}
15 };
16 //SLR(1)分析表
17 string actiontable[ROW][COLUMN]={
18 {"","a","b","c","#","S","A","B","C"},
19 {"0","s1","","","","2","3","",""},
20 {"1","r3","r3","","","","","",""},
21 {"2","","","","acc","","","",""},
22 {"3","s4","s5","","","","","6",""},
23 {"4","r2","r2","","","","","",""},
24 {"5","","r5","r5","","","","",""},
25 {"6","","s7","s8","","","","","9"},
26 {"7","","r4","r4","","","","",""},
27 {"8","","","r7","r7","","","",""},
28 {"9","","","s10","r1","","","",""},
29 {"10","","","r6","r6","","","",""}
30 };
31 stack<int> sstatus; //状态栈
32 stack<char> schar; //符号栈
33 struct Node{
34 char type;
35 int num;
36 };
37 //打印步骤
38 void print_step(int times){
39 stack<char> tmp2;
40 cout<<times<<setw(4);
41 while(!schar.empty()){
42 char t=schar.top();
43 schar.pop();
44 tmp2.push(t);
45 cout<<t;
46 }
47 while(!tmp2.empty()){
48 int t=tmp2.top();
49 tmp2.pop();
50 schar.push(t);
51 }
52 }
53 //查表
54 Node Action_Goto_Table(int status,char a){
55 int row=status+1;
56 string tmp;
57 for(int j=1;j<COLUMN;j++){
58 if(a==actiontable[0][j][0]){
59 tmp=actiontable[row][j];
60 }
61 }
62 Node ans;
63 if(tmp[0]>='0'&&tmp[0]<='9'){
64 int val=0;
65 for(int i=0;i<tmp.length();i++){
66 val=val*10+(tmp[i]-'0');
67 }
68 ans.num=val;
69 ans.type=' ';
70 }else if(tmp[0]=='s'){
71 int val=0;
72 for(int i=1;i<tmp.length();i++){
73 val=val*10+(tmp[i]-'0');
74 }
75 ans.type='s';
76 ans.num=val;
77 }else if(tmp[0]=='r'){
78 int val=0;
79 for(int i=1;i<tmp.length();i++){
80 val=val*10+(tmp[i]-'0');
81 }
82 ans.type='r';
83 ans.num=val;
84 }else if(tmp[0]=='a'){
85 ans.type='a';
86 }else{
87 ans.type=' ';
88 }
89 return ans;
90 }
91 //SLR(1)分析算法
92 bool SLR1(string input){
93 while(!sstatus.empty()){
94 sstatus.pop();
95 }
96 while(!schar.empty()){
97 schar.pop();
98 }
99 int times=0;
100 bool flag=true;
101 int st=0;
102 sstatus.push(st);
103 schar.push('#');
104 int i=0;
105 char a=input[i];
106 while(true){
107 Node action=Action_Goto_Table(st,a);
108 if(action.type=='s'){
109 st=action.num;
110 sstatus.push(st);
111 schar.push(a);
112 a=input[++i];
113 print_step(++times);
114 cout<<setw(10)<<'s'<<st<<endl;
115
116 }else if(action.type=='r'){
117 int n=action.num;
118 string ls=products[n][0];
119 string rs=products[n][1];
120 for(int j=0;j<rs.length();j++){
121 sstatus.pop();
122 schar.pop();
123 }
124 schar.push(ls[0]);
125 st=sstatus.top();
126 action =Action_Goto_Table(st,ls[0]);
127 st=action.num;
128 sstatus.push(st);
129 print_step(++times);
130 cout<<setw(10)<<'r'<<" "<<ls<<"->"<<rs<<endl;
131
132 }else if(action.type=='a'){
133 flag=true;
134 break;
135 }else{
136 flag=false;
137 break;
138 }
139 }
140 return flag;
141 }
142 int main(){
143 string input;
144 while(cin>>input){
145 if(SLR1(input)){
146 cout<<"syntax correct"<<endl;
147 }else{
148 cout<<"syntax error"<<endl;
149 }
150 }
151 return 0;
152 }
SLR(1)分析法的更多相关文章
- 【转】LR分析法
转自:http://guanjy0129.blog.163.com/blog/static/1115494452010614113333509/ LR分析法的归约过程是规范推导的逆过程,所以LR分析过 ...
- 编译原理(六)自底向上分析之LR分析法
自底向上分析之LR分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本概念 1. LR分析:从左到右扫描(L)自底向上进行规约(R),是规范规约,也即最右推导(规范推导) ...
- 《编译原理》LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析
<编译原理>LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析 笔记 直接做题是有一些特定步骤,有技巧.但也必须先了解一些基本概念,本篇会通过例题形式解释概念,会容易理解和记忆,以 ...
- 从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 ...
- 5W1H分析法
"5W1H分析法"也叫"六何分析法",它是一种分析方法也可以说是一种创造技法.是对选定的项目.工序和操作,都要从原因(Why).对象(What).地点(Wher ...
随机推荐
- 动态规划二 & 贪心算法 实验三
一.贪心算法和动态规划法解决背包问题. 有一个背包其容积 C = 13.现有表格内的物品可以购买. 商品 价格 P 体积 V 啤酒 24 10 汽水 2 3 饼干 9 4 面包 10 5 牛奶 9 4 ...
- 如何正确实现一个自定义Exception(二)
上一篇<如何正确实现一个自定义 Exception>发布后获得不少 star.有同学表示很担忧,原来自己这么多年一直写错了.其实大家不用过分纠结,如果写的是 .NET CORE 1.0+ ...
- 后端常用的Linux命令大全,建议收藏
引言 作为一名后端工程师,使用终端是一种常见的做法,也是你应该学习的技能.许多命令和实用程序可以帮助你在使用 Linux 时更有效地完成任务. 基本 Linux 命令 如果你想使用 Linux 操作系 ...
- Llama2-Chinese项目:2.1-Atom-7B预训练
虽然Llama2的预训练数据相对于第一代LLaMA扩大了一倍,但是中文预训练数据的比例依然非常少,仅占0.13%,这也导致了原始Llama2的中文能力较弱.为了能够提升模型的中文能力,可以采用微调 ...
- SpringBoot 后端配置 Https 教程
以阿里云为例子 1. 申请 SSL 证书 1. 注册域名 打开阿里云官网,搜索域名 点击域名注册,输入域名,点击搜索 选择心仪的域名,点击购买,打钱 进入域名控制台,进行实名认证 2. 申请 SSL ...
- Python 网页爬虫原理及代理 IP 使用
一.Python 网页爬虫原理 Python 是一种高效的编程语言,在 Web 开发和数据分析领域广受欢迎.Python 的优秀模块使其更加适合大规模数据处理和 Web 服务的编程.网络爬虫是 Pyt ...
- ORACEL12C ORA-01033:ORACLE 正在初始化或关闭
问题:客户端报ORA-01033 原因:oracle12C CDB启动,但是可拔插的PDB实例未启动 解决办法: sqlplus / as sysdba--系统管理员登录 alter session ...
- 在Go中如何实现并发
Go语言的并发机制是其强大和流行的一个关键特性之一.Go使用协程(goroutines)和通道(channels)来实现并发编程,这使得编写高效且可维护的并发代码变得相对容易.下面是Go的并发机制的详 ...
- Django框架项目之课程主页——课程页页面、课程表分析、课程表数据、课程页面、课程接口、前台、后台
文章目录 1-课程页页面 课程组件 2 课程主页之课程表分析 课程表分析 免费课案例 创建models:course/models.py 注册models:course/adminx.py 数据库迁移 ...
- Java 队列Queue的一些基本操作与概念!!!!!!!!
首先Java中的队列(Queue)是一种先进先出的数据结构. 其中常见的一些基本操作与方法,包括: 1.创建队列对象.例如:ArrayDeque.LinkedList等. 2.入队操作.将元素添加到队 ...