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

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

  1. 【转】LR分析法

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

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

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

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

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

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

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

  5. Procrustes Analysis普氏分析法

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

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

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

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

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

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

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

  9. SWOT分析法

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

  10. 5W1H分析法

    "5W1H分析法"也叫"六何分析法",它是一种分析方法也可以说是一种创造技法.是对选定的项目.工序和操作,都要从原因(Why).对象(What).地点(Wher ...

随机推荐

  1. QA|Pycharm:allure : 无法将“allure”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。|Allure

    Pycharm中生成allure测试报告时报错如图: 单独执行allure --version也不行,cmd这样执行也报同样的错 网上查了 说是环境变量问题,加一下cmd可以了,重启pycharm也可 ...

  2. Windows 某些软件显示"口口"解决办法

    和乱码不同,文字变成"口口",一般是语言环境出错了. 解决办法 开始->控制面板->区域 (时钟.语言和区域)->区域:更改设置->管理->非 Uni ...

  3. ATtiny88初体验(七):TWI

    ATtiny88初体验(七):TWI TWI模块介绍 ATtiny88的TWI模块兼容Phillips I2C以及SMBus,支持主从模式,支持7bit地址,最大允许128个不同的从机地址.在多主机模 ...

  4. Building-Mobile-Apps-with-Ionic-2中文翻译工作

    最近没啥工作量, 然后学完了这本书, 接着又茫然找不到该干啥, 所以想着何不翻译这个书呢. 这本书首先给我们普及了Ionic 2的基础知识, Ionic 2和Ionic 1有本质上的区别, Ionic ...

  5. Node学习第一步 | 简介及安装

    什么是node Javascript可以在浏览器运行, node可以让javascript在浏览器之外运行 可以用来做本地运行的软件/网络服务器/游戏等等 记得安装vs code里面力扣插件需要先安装 ...

  6. 高效数据管理:Java助力实现Excel数据验证

    摘要:本文由葡萄城技术团队原创并首发.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 在Java中,开发者可以使用一些开源的库(如Apache POI ...

  7. matlab启动时的路径警告

    前段时间在做HDLCoder时为方便修改设置加了一条路径在搜索路径目录,后来把路径名称修改了,文件夹也删掉了,换句话说就是路径不存在了,然后在matlab的setpath对话框里边也把该目录删除了. ...

  8. 基于 Python 和 Vue 的在线评测系统

    基于 Docker,真正一键部署 前后端分离,模块化编程,微服务 ACM/OI 两种比赛模式.实时/非实时评判 任意选择 丰富的可视化图表,一图胜千言 支持 Template Problem,可以添加 ...

  9. 在 Rust 中实现 Repository 仓储模式

    前言 单位上有个 Rust 项目,orm 选型很长时间都没定下来,故先设计了抽象的仓储层方便写业务逻辑. 设计抽象接口 抽象只读接口,仅读取使用,目前需求仅用查询 id.查询全部和按名称搜索,当然理应 ...

  10. Window10安装linux子系统及子系统安装1Panel面板

    原文地址:Window10安装linux子系统及子系统安装1Panel面板 - Stars-One的杂货小窝 最近看到halo博客发布了2.10.0,终于是新增了个备份功能,于是有了念头想要升级下 但 ...