编绎原理 - 构造LR(0)分析表与输入串分析过程表

目录

一、 什么是LR(0)文法

1、概念

2、解释

二、实现步骤

1、拓广文法,加入一个用于产生开始符号的产生式,并从0开始编号

2、构造识别活前缀的DFA

(1)第一个项目集(或状态)

①项目集解释

(2)完整活前缀的DFA如下

​编辑

解释

例如

3、构造LR(0)分析表

(1)说明

(2)LR(0)分析表如下

​编辑

4、对于输入串acd#的分析过程

解释

步骤1

步骤2

步骤3

步骤4

步骤5

步骤6

步骤7

三、练习

1、拓广文法并编号

2、构造活前缀的DFA

3、构造LR(0)分析表

4、对于输入串abcde的分析过程


建议

可以使用PixPin截图软件将多个截图固定在屏幕上方,方便后面边看边理解

链接:https://pixpinapp.com/

一、 什么是LR(0)文法

1、概念

若一个文法 G 的拓广文法 G’ 的识别活前缀的自动机中的每个状态(项目集)均不存在下述情况:

  1. 既有移进项目又有规约项目(移进-规约冲突);
  2. 含有多个规约项目(规约-规约冲突),

则称 G 为一个 LR(0) 文法

2、解释

项目分类如下

基本项目:圆点在最左边                  例:E→ •S

移进项目:圆点后边是终结符           例:E→•aS

待约项目:圆点后边是非终结符        例:E→a•S

规约项目:圆点在最右边                   例:E→aS•

二、实现步骤

例:已知文法

G[E]: E→aA

          A→cA

          A→d

1、拓广文法,加入一个用于产生开始符号的产生式,并从0开始编号

      0    S→E                   产生E的符号随意(除E以外)

      1    E→aA

      2    A→cA

      3    A→d

2、构造识别活前缀的DFA

(1)第一个项目集(或状态)

①项目集解释

第0个产生式出发构造基本项,若圆点右侧有非终结符,则写出该非终结符的基本项

(2)完整活前缀的DFA如下

解释

接受一个符号,产生一个新的状态(保留的为可接受该符号的项目),且圆点向前进一位。

同样,若圆点后为非终结符需写出该非终结符的基本项。

直到出现规约状态(圆点在最右侧)

检查DFA是否正确,可通过判断规约项的个数是否等于拓广后产生式的个数

例如

I2中A→•cA接受c进入到I4状态,圆点向前一位:A→c•A

圆点后为非终结符A,写出A的基本项,即A→•cA   A→•d

之后写出I4接受符号后产生的状态,直到出现规约项(即I5、I6)

其中I4接受c还是它本身,不用再写新状态,指向它本身即可

3、构造LR(0)分析表

由上图DFA可得,同一个项目集不存在移进与规约,规约与guiyue

(1)说明

①状态中写DFA的几个状态

ACTION中写终结符,包括#

ACTION中Sn ,代表接受符号后转向哪个状态,n代表第n个状态

ACTION中Rn,代表规约成第n个产生式,且Rn占整个ACTION

⑤ACTION中产生开始符号的规约项,在#处写acc

GOTO中写非终结符,不包括新加进去的那个,即S

GOTO中转向哪个状态直接写状态号即可

(2)LR(0)分析表如下

4、对于输入串acd#的分析过程

说明:转向,则余留输入串分析出一个,余留输入串栈-1,而符号栈+1

           规约,则余留输入串不变,符号栈进行规约

步骤状态栈符号栈余留输入串栈ACTIONGOTO
10#acd#2
202#acd#4
3024#acd#6
40246#acd#35
50245#acA#23
6023#aA#11
701#E#acc

解释

步骤1

状态栈:0

符号栈:#

余留输入串栈:acd#

ACTION:0接受a,转向2状态

分析出c

步骤2

状态栈:0转向2,为02

符号栈:上步分析出a,即符号栈为:#a

余留输入串栈:a被分析,出栈,剩余cd#

ACTION:2接受c,转向4状态

分析出c

步骤3

状态栈:2转向4,为024

符号栈: 上步分析出c,即符号栈为#ac

余留输入串栈:c被分析,出栈,剩余#d

ACTION:4接受d,转向6

分析出d

步骤4

状态栈:4转向6,为0246

符号栈:上步分析出d,即符号栈为#acd

余留输入串栈:d被分析,出栈,剩余#

ACTION:6接受#,规约为产生式3

GOTO:

3产生式如下: A→d

d规约成A

len(3产生式)=|d|=1

出栈1个状态,即状态栈此时为024

GOTO[状态,规约成的非终结符

=GOTO[4,A]=5     4状态接受A为5状态

步骤5

状态栈:上步出栈一个状态,进入状态5,即0245

符号栈:d规约成A,即符号栈为#acA

余留输入串栈:不变,#

ACTION:5接受#规约为2产生式

GOTO:

2产生式如下:A→cA

cA规约成A

len(2产生式)=|cA|=2

出栈2个状态,及状态此时为02

GOTO[状态,规约成的非终结符]

=GOTO[2,A]=3

步骤6

状态栈:上步出栈2个状态,进入状态3,即023

符号栈:cA规约成A,即符号栈为#aA

余留输入串栈:不变,#

ACTION:3接受#规约成为1

GOTO:

1产生式如下:E→aA

aA规约成E

len(1产生式)=|aA|=2

出栈2个状态,及状态此时为0

GOTO[状态,规约成的非终结符]

=GOTO[0,E]=1

步骤7

状态栈:上步出栈2个状态,进入1状态,即01

符号栈:aA规约成E,即#E

余留输入串栈:不变,#

ACTION:1接受#,acc

至此,acc已出现,结束


三、练习

接下来,可以先自己练习一下,之后对答案

已知文法如下:

S→aAcBe

A→b

B→d

1、拓广文法并编号

0  E→S

1  S→aAcBe

2  A→b

3  B→d

2、构造活前缀的DFA

3、构造LR(0)分析表

状态ACTIONGOTO
abcde#SAB
0S21
1acc
2S43
3S6
4r2r2r2r2r2r2
5r3r3r3r3r3r3
6S57
7S8
8r1r1r1r1r1r1

4、对于输入串abcde的分析过程

步骤状态栈符号栈余留输入串栈ACTIONGOTO
00#abcde#2
102#abcde#4
2024#abcde#23
3023#aAcde#6
40236#aAcde#5
502365#aAcde#37
602367#aAcBe#8
7023678#aAcBe#11
801#S#acc

至此,分析成功

另外:内容较多,若有纰漏,请提醒,感谢

  • 26
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LR(0)分析是一种自底向上的语法分析方法,用于分析上下文无关文法。下面是构造LR(0)分析的C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_SYMBOLS 100 #define MAX_STATES 100 int num_symbols, num_states; char symbols[MAX_SYMBOLS]; char states[MAX_STATES][MAX_SYMBOLS]; int num_transitions[MAX_STATES][MAX_SYMBOLS]; char transitions[MAX_STATES][MAX_SYMBOLS][MAX_STATES]; int get_symbol_index(char symbol) { for (int i = 0; i < num_symbols; i++) { if (symbols[i] == symbol) { return i; } } return -1; } void add_transition(int state, char symbol, int next_state) { int symbol_index = get_symbol_index(symbol); if (symbol_index == -1) { symbols[num_symbols++] = symbol; symbol_index = num_symbols - 1; } num_transitions[state][symbol_index]++; transitions[state][symbol_index][next_state] = 1;} void print_table() { printf("State\t"); for (int i = 0; i < num_symbols; i++) { printf("%c\t", symbols[i]); } printf("\n"); for (int i = 0; i < num_states; i++) { printf("%d\t", i); for (int j = 0; j < num_symbols; j++) { if (num_transitions[i][j] == 0) { printf(".\t"); } else if (num_transitions[i][j] == 1) { int next_state = -1; for (int k = 0; k < num_states; k++) { if (transitions[i][j][k]) { next_state = k; break; } } printf("%d\t", next_state); } else { printf("{"); for (int k = 0; k < num_states; k++) { if (transitions[i][j][k]) { printf("%d,", k); } } printf("}\t"); } } printf("\n"); } } int main() { // TODO: 构造LR(0)分析的代码 print_table(); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值