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. firefox对webview性能数据监控的模拟

    现在为了降低手机端的开发成本,越来越多的手机应用采用html5在进行开发,这样可以保证一处开发,到处嵌入. 但是这样的手机性能经常会是个瓶颈,因为当体验要求变高时,大多依赖html渲染引擎来对dom数 ...

  2. 云上的甜蜜早安:腾讯云云函数助力PHP打造女友专属每日推送

    用腾讯云的云函数做一个微信公众号早安,每天定时发送早安给你的女朋友! 1.首先我们登录腾讯云,在搜索栏搜索云函数,或直接用这个链接进入curl.qcloud.com/Td0IkpmD 2.进入云函数, ...

  3. 「atcoder - 214G」Three Permutations

    la traduction. link. 如果我们对于每一个 \(k\in[0,n]\) 找到所有满足存在 \(k\) 个 \(i\) 使得 \(r_i=p_i\) 或 \(r_i=q_i\) 条件的 ...

  4. 树莓派3B/3B+的串口使用

    树莓派包含两个串口,一个称之为硬件串口(/dev/ttyAMA0),一个称之为mini串口(/dev/ttyS0).硬件串口由硬件实现,有单独的波特率时钟源,性能高.可靠.mini串口时钟源是由CPU ...

  5. 记录 Ucharts 的使用

    1.开启 2d 渲染 线上运行开启 canvas2d 可以解决图表显示问题 <qiun-data-charts canvas2d .../> canvasId 可以不传,官方内置生成随机字 ...

  6. TopCoder 15903 EllysNim

    TopCoder 15903 EllysNim(https://vjudge.net/problem/TopCoder-15903) \(n\)看似有点东西,实际上就只是一个贪心... 设\(i\)表 ...

  7. Go函数介绍与一等公民

    Go函数介绍与一等公民 函数对应的英文单词是 Function,Function 这个单词原本是功能.职责的意思.编程语言使用 Function 这个单词,表示将一个大问题分解后而形成的.若干具有特定 ...

  8. 文心一言 VS 讯飞星火 VS chatgpt (113)-- 算法导论10.2 5题

    五.用go语言,使用单向循环链表实现字典操作 INSERT.DELETE 和 SEARCH,并给出所写过程的运行时间. 文心一言: 在Go语言中,我们首先需要定义一个Node结构体来表示单向循环链表的 ...

  9. ciscn_2019_c_1 题解

    main函数如下: int __cdecl main(int argc, const char **argv, const char **envp) { int v4; // [rsp+Ch] [rb ...

  10. Interesting Array 题解

    Interesting Array 题目大意 构造一个序列 \(a\),使其满足若干限制条件,每个限制条件是形如 l r q 的式子,其意义是:\(\&_{i=l}^ra_i=q\). 题意分 ...