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. C# 异步执行操作

    为了方便测试异步,先加个计时 计时相关(可以直接跳过该部分) //开始计时 Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // 停 ...

  2. BeanUtils.copyProperties:曾经是我的女神,现在是我的毒药。

    前言 BeanUtils.copyProperties十有八九是你这些年工作中用的很多的其中一个,不管是Apache的还是Spring的. 网上的解释浩如烟海,我这边用一个超简单的例子直观展示给你看. ...

  3. 【反反爬】使用Jsoup爬取数据保存Excel

      本文主要使用Jsoup爬取XXX房屋信息,抓取一些房屋信息,比如房屋楼盘.户型.价格.地址等信息,然后保存到Excel,便于对比和筛选,选出符合预期的好房. 注意,有些网站有防爬取机制,需要设置动 ...

  4. Nextcloud 维护管理

    Nextcloud 维护管理 目录 Nextcloud 维护管理 1.管理员被禁用怎么办 2.管理员密码忘了怎么办 1.管理员被禁用怎么办 通过命令行解禁管理员用户: 方法一:通过命令行解禁管理员用户 ...

  5. Java开发面试--Redis专区

    1. 什么是Redis?它的主要特点是什么? 答: Redis是一个开源的.基于内存的高性能键值对存储系统.它主要用于缓存.数据存储和消息队列等场景. 高性能:Redis将数据存储在内存中,并采用单线 ...

  6. 将Python程序打包成Linux可执行文件

    将Python程序打包成Linux可执行文件 安装环境 首先我们要安装pip,命令如下: sudo apt install python3-pip 使用的工具是pyinstaller,打开终端输入su ...

  7. fprintf

    fprintf 是一个标准C库函数,用于将格式化的输出写入到指定文件流中.它的函数原型如下: int fprintf(FILE *stream, const char *format, ...); 参 ...

  8. Q-REG论文阅读

    Q-REG Jin, S., Barath, D., Pollefeys, M., & Armeni, I. (2023). Q-REG: End-to-End Trainable Point ...

  9. C静态库的创建与使用--为什么要引入静态库?

    C源程序需要经过预处理.编译.汇编几个阶段,得到各自源文件对应的可重定位目标文件,可重定位目标文件就是各个源文件的二进制机器代码,一般是.o格式.比如:util1.c.util2.c及main.c三个 ...

  10. 【高手训练】【RMQ】奶牛排队

    第一题由于过水,就没写awa 大概就是这样了.题意就是求一个最长的区间使得区间的左边是它的最小值,区间右边是他的最大值第一个想法肯定是暴力枚举啦awa但是这个是O(n^3)的,绝对的不可过awa 思考 ...