LR(0)是一种自底向上的语法分析方法。两个基本动作是移进和规约。

具体例子如下

已知文法G[E]

(1) E→aА

(2) E→bB

(3) A→cА

(4) A→d

(5) B→cB

(6) B→d

编写LR(0)分析算法,用于识别符号串是否为合法的句子。

设计方法

a.将文法 G[E]拓广为文法 G[E']

(0) S'→E

(1) E→aA

(2) E→bB

(3) A→cA

(4) A→d

(5) B→cB

(6) B→d

b.构造识别可归约前缀的 NFA

c. 将识别可归约前缀的 NFA 确定化成DFA

d. 根据识别可归约前缀的 DFA 构造文法的 LR(0)分析表

表2-1 LR(0)分析表

状态

a

b

c

d

#

E

A

B

0

S1

S2

3

1

S4

S5

6

2

S7

S8

9

3

acc

4

S4

S5

10

5

r4

r4

r4

r4

r4

6

r1

r1

r1

r1

r1

7

S7

S8

11

8

r6

r6

r6

r6

r6

9

r2

r2

r2

r2

r2

10

r3

r3

r3

r3

r3

11

r5

r5

r5

r5

r5

e. 设计 LR(0)分析程序

自底向上的语法分析的两个基本动作就是,移进与规约。分析一下表 2-1 中 文法的 LR(0)分析表,可以发现这两个动作在表中都有。进一步分析可知,这些 移进与规约动作在表的前面终结符列中,因此,这部分称之为 ACTION 表。

表中不但给出了两个基本动作,还给出了规约时,弹出产生式右部,压入左 部之后,应该转换到的状态。例如,当前状态为 9,状态 9 为句柄识别态,查表 得:r2,表示使用第二个产生式E→bB 进行规约。规约动作分为两步:第一步弹 出句柄 bB,从识别文法可归约前缀的 DFA 中可知,弹出句柄 bB后,从当前状态为 9 回到状态 0;第二步就是压入左部 E, 从当前状态 0,转换到状态 3。在表中 的第 0 行第 E 列中就给出状态 3。

分析表 可知,表中的非终结符列填入的是某一规约动作,压入产生式左 部(非终结符)之后,转换到的状态。因此,这部分称之为 GOTO 表。

实验代码:

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

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

  1. 编译原理根据项目集规范族构造LR(0)分析表

    转载于https://blog.csdn.net/Johan_Joe_King/article/details/79058597?utm_medium=distribute.pc_relevant.n ...

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

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

  3. LL(1),LR(0),SLR(1),LALR(1),LR(1)对比与分析

    前言:考虑到这几种文法如果把具体内容讲下来肯定篇幅太长,而且繁多的符号对初学者肯定是极不友好的,而且我相信看这篇博客的人已经对这几个文法已经有所了解了,本篇博客的内容只是对 这几个文法做一下对比,加深 ...

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

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

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

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

  6. LR(0)语法分析

    # include <stdio.h> # include <string.h> //存储LR(0)分析表 struct node { char ch; int num; }; ...

  7. 编译原理LR(0)项目集规范族的构造详解

    转载于https://blog.csdn.net/johan_joe_king/article/details/79051993#comments 学编译原理的时候,感觉什么LL(1).LR(0).S ...

  8. 【转】LR分析法

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

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

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

  10. LL(1),LR(0),SLR(1),LR(1),LALR(1)的 联系与区别

    一:LR(0),SLR(1),规范LR(1),LALR(1)的关系     首先LL(1)分析法是自上而下的分析法.LR(0),LR(1),SLR(1),LALR(1)是自下而上的分析法.       ...

随机推荐

  1. 蚂蚁集团混沌工程 ChaosMeta V0.5 版本发布

    混沌工程 ChaosMeta 的全新版本 V0.5 现已正式发布!该版本包含了许多新特性和增强功能,为用户提供了支撑混沌工程各个阶段的平台能力,以及降低使用门槛的用户界面. ChaosMeta V0. ...

  2. QA||TypeError: ‘module‘ object is not callable报错怎么debugIHRM接口自动化测试

    unittest.py生成测试报告时执行报错:TypeError: 'module' object is not callable 代码如下 原因:结合pycharm自动标注和报错信息,分析出应该是H ...

  3. Java 中的日期时间总结

    前言 大家好,我是 god23bin,在日常开发中,我们经常需要处理日期和时间,日期和时间可以说是一定会用到的,现在总结下 Java 中日期与时间的基本概念与一些常用的用法. 基本概念 日期(年月日, ...

  4. 领域驱动模型DDD(四)——Eventuate Tram Saga源码讲解

    前言 虽然本人一直抱怨<微服务架构设计模式>中DDD模式下采用的Eventuate Tram Saga不算简单易用,但是为了更加深入了解原文作者的设计思路,还是花了点时间去阅读源码,并且为 ...

  5. MySQL中的Statistics等待

    [作者] 吴宙旭,携程数据库专家 [问题描述] 线上我们偶尔会碰到MySQL的状态是statistics. 但如果出现大量的statistics等待,会引起MySQL性能急剧下降.官方的文档对这个状态 ...

  6. 2023 ICPC 网络赛 I

    没留够时间准备导致开考的时候耽搁了 开场我先写缺省源,抄串了一行,后面才发现...然后看了 L 发现是签到,此时 ddw 会了 A 让 zsy 上去写,我等了一会才把 zsy 撵下来写 L 是个失误 ...

  7. FFmpeg H.264编码器指南[译]

    H264 视频编码器指南 本指引着眼于x264编码器,这里假设你的FFmpeg 编译了--enable-libx264支持.如果你需要编译支持的帮助请看这篇文档:https://trac.ffmpeg ...

  8. 黄金眼PAAS化数据服务DIFF测试工具的建设实践

    一.背景介绍 黄金眼PAAS化数据服务是一系列实现相同指标服务协议的数据服务,各个服务间按照所生产指标的主题作划分,比如交易实时服务提供实时交易指标的查询,财务离线服务提供离线财务指标的查询.黄金眼P ...

  9. [ABC207E] Mod i 题解

    Mod i 题目大意 给定一个序列 \(a\),问将其划分成若干段,满足第 \(i\) 段的和是 \(i\) 的倍数的划分方案的个数. 思路分析 考虑 DP,设 \(f_{i,j}\) 表示将序列中前 ...

  10. JAVA类的加载(1) ——类的加载及类加载器介绍

    过程:当程序主动使用某个类时,如果该类还未被加载到内存中,系统会通过加载.连接.初始化三个步骤来对该类进行初始化,有时候称为类加载(类初始化)   类加载 定义:类加载 指的是将类的class文件读入 ...