《编译原理-龙书》练习第4章

4.2 上下文无关文法

**4.2.7节中L={a^nb^n|n>=1}怎么用文法表示?
S -> aAb
A -> ab| ε

4.2.1

1) E -> EE* 

-> EE+E*

-> aa+a*

左到右依次a

2) 与1)一样,只是最后一步右到左依次a

3)       E

      E       E  *

 E E +

id id        id

4)无二义性,但是怎么证明呢?

5)+*组成的后缀表达式

4.2.3 如果是正则表达式,可以采用4.2.7的方法转成文法

1) (0*1+)* 根据DNF推出:

S -> 0A

S -> 1S

S -> ε

A -> 1S

2)

S -> ABA

A -> BB

B -> 0|1|ε

4.2.4

对于A->X[Y]Z,可以表示为

A->XBZ

B->Y|ε

对于A->X{YZ},可以表示为

A->XB

B->CC

C->YZ|ε

4.2.5 stmt -> if expr then stmt [ else stmt ] | begin stmt{; stmt} end

4.2.6 基本的正则表达式还剩*,表示为A->Z*,可以改写为:

A->BB

B->Z|ε

4.2.7 1)

建立一个集合表示所有非“无用符号”集合T,开始置为所有终结符号

集合A表示所有推导式,默认不打标记

for(所有没有打标记的A中推导式)

{

 if( 如果右边只有T中符号集合)

  {

    将这个表达式打标记

    表达式左边符号加入集合T

  }

 if(一个循环结束没有新的表达式被打标记)

   循环退出

}

将开始符号加入T

2)非“无用符号”集合T会依次加入{0, B, S},所以A是无用符号

4.2.8 读懂这道题费了好大劲,不知到是因为最后一道题了还是比较晚了(2012-12-20 22:49,离世界末日不远了)

1)前2行不变,后面改为:

option -> A1|A2|...|An

A1 -> a1|b1

...

An -> an|bn

2)又花了一段时间读懂了这个题目,生成的串固定长度n,不考虑<n的串

n!*n的产生式是这样的,1)中的第一行改为:

option->Aa1|Aa2...|Aan

其中a1有n种选择(A1-An),a2有剩下的n-1种.....an为剩下的一种。

这些产生式一共包括n!个长度为n的产生式,即O(n!*n)


如果有一个O(n*2^n)的产生式序列,那么可能是n个长度为2^n的产生式,具体构造方法没想出来


4.3 设计文法

4.3.1 1)没有左公因子

2)有左递归,不能自顶向下语法分析

3)

rexpr -> rterm | E1

E1 -> +rterm | ε

rterm -> rfactor | F1

F1 -> rfactor | ε

rfactor -> rprimary | P1

P1 -> * | ε

rprimary -> a|b

4)目前没有左递归、左公因子,可以自顶向下语法分析

4.3.3 考虑 if E1 then if E2 else if E3 then MATCHED1 else MATCHED2

if E3 then MATCHED1 else MATCHED2不能确定跟前面两个if中的哪个匹配

4.4 自顶向下的语法分析

4.4.1 1)S -> 0S1 | 01
S -> 0T
T -> S1|1
FIRST(S) = {0}
FIRST(T) = {0,1}
FOLLOW(S) = {1,$}
FOLLOW(T) = {1,$}
 01$
SS->0T  
TT->S1T->1 


4.4.2 S -> SS+ | SS* | a
提取左公因子
S -> SST|a
T -> +|*
消除左递归

S -> aX

X -> STX |ε 

T -> +|*

FIRST(S) = {a}
FIRST(X) = {a}
FOLLOW(S) = {+,*,$}
FOLLOW(X) = {+,*,$}
提取左公因子
 a+*$
SaX   
XSTXεεε
T +* 

4.4.5 感觉可以识别aaaaaa,为啥不行呢?

aaaaaa aSa

  aaaaa  Sa

  aaaaa  aSaa 如果可以向前看4个输入符号,则可以识别aaaaa,否则,会继续采用S -> aSa

    aaaa  Saa    aSaaa

      aaa  aSaaaa

        aa  Saaaa    aSaaaaa

          a  Saaaaa  需要回溯,回溯到一定程度就可以识别

4.4.6 1)如果产生式左边只能生成ε,则将其在文法中所有出现的地方删除即可

否则,就是类似T -> X | ε,这种情况下,将T在其他推导中出现的地方用这两个替换

这样有可能粗先左递归或左公因子。

2)

S -> aSbS  => S -> aaSbSbaSbS | abSaSbbSaS | aSbS

S -> bSaS  => S -> baSbSaaSbS | bbSaSabSaS | bSaS

S -> ε

综合得到S -> aaSbSbaSbS | abSaSbbSaS | aSbS | baSbSaaSbS | bbSaSabSaS | bSaS

4.4.7 1)如果有A=》B,则将B进行替换,替换为B可推导得到的表达式

2)E -> E+T | T   T -> T*F | F   F->(E) | id 进行替换如下:

T -> T*F | (E) | id

E -> E+T | T*F | (E) | id

3)一步推导得到的环可以直接删除,如果是多步,不失一般性,假设为2步,由于文法中不存在ε,所以必然存在这样的推导:

A->B B->A,我们可以爱用上面方法将B去掉,并去掉一步环。

4.4.8 根据4.4.7不难得到,但是得到的结果有左递归

4.4.9 如果n*n的表能够构造成功直到j-i=n-1,说明串在这个语言中

4.5 自底向上的语法分析

4.5.1  S -> 0S1 | 01

1)000111 最右推导:S -> 0S1 -> 00S11 -> 000111

最中间的01

2)00S11   最右推导: S -> 0S1 ->00S11

中间的0S1

4.5.2  S -> SS+ |SS* | a

1)SS+A*+      SS+

2)SS+a*a+   SS+

3)aaa*a++    a

4.5.3

1)

$            000111$

$0001            11$

$00S              11$

$00S1              1$

$0S                   1$

$0S1                   $

$S                       $

2)

aaa*a++

Saa*a++

SSa*a++

SSS*a++

SSa++

SSS++

SS+

S

4.6 LR语法分析技术介绍:简单LR技术

4.6.1

1) 0,0S,00S....

2)

4.6.2 S -> SS+| SS* | a

采用图4-33中算法处理 

(1) S`->S

(2) S -> SS+

(3) S -> SS*

(4) S -> a

01 0S2 0a3 1S4 3+5 3*

S`->.S

S->.SS+

S->.SS*

S->.a

S`->S.

S->S.S+

S->S.S*

S->.a

1$ = accept

S->a.

S->SS.+

S->SS.*

S->SS+.S->SS*.

采用算法4.46

FOLLOW(S) = {+, *,a $}    FOLLOW(+)={+, *, a}    FOLLOW(*)={+, *, a}   FOLLOW(a)={+, *, a}

 a+*$S
0s2   1
1s2  acc3
2r4r4r4  
3 s4s5  
4r2r2r2  
5r3r3r3  

没有发现哪个ACTION既有归约又有移入操作,应该是SLR文法

4.6.3

符号输入动作
0 aa*a+$移入
02aa*a+$归约S->a
01Sa*a+$移入
012Sa*a+$归约S->a
013SS*a+$移入
0135SS*a+$归约S->SS*
01Sa+$移入
012Sa+$归约S->a
013SS+$移入
0134SS+$归约S->SS+
01S$接收
    


对于下面两题

LL(1)文法特点:需要满足4.4.3中的三个条件

SLR(1)文法特点:在输入某个表示串以后,有移入/规约冲突或规约/规约冲突

LL文法是LR文法的一个真子集,而不是SLR的

4.6.5

S`->S

S -> AaAb | BbBa

A ->ε

B ->ε

构造LR(0)自动机

0

S`->.S

S->.AaAb

S->.BbBa

A->.ε

B->.ε

1 0S

S`->S

没法继续构造下去

4.6.6

FIRST(SA)与FIRST(A)都包含{a}。所以不是LL(1)的

4.6.7 1)

S -> Aibi          n个

Ai -> ajAi          n^2-n个

Ai -> aj             n^2-n个 

2)考虑其中某个i和j

index项集

贡献数量

 
0

S`->.S 

S->.Aibi 

Ai->.ajAi 

Ai->.aj

1S`->.S
S->.A1b1 ...
S->.Anbn
A1->.a2A1...
A1->.anA1...
...
An->.a1An...
An->.an-1An
1
0->S
S`->S.1S`->S.
2
0->Ai
S->Ai.binn个S->Ai.bi
3
0->aj

Ai->aj.Ai

Ai->aj.

Ai->.ajAi

Ai->.aj

n对于a1
A2->a1.A2...
An->a1.An
A2->.ajA2
A2->.aj
...an
4
2->bi
S->Aibi.nn个S->Aibi.
5
3->Ai, 6Ai
Ai->ajAi.n*(n-1)对于a1
输入A2...An
6
3->aj,6->aj
Ai->aj.Ai
Ai->.ajAi
Ai->.aj
n*n对于a1
输入a1,a3...an
A2->aj.A2
A2->aj.
    

这样算下来是2n*n+2n+2

结果应该是2^n+n^2+n,看来我算错了,求高手指点

如果势2^n那说明状态数量太多了,手工构造太困难了,做4.6练习过程感觉中间太容易出错了(手动计算的情况)

4.6.8

4.6.9

index项集 
0S'->.S
S->.AS
S->.b
A->.SA
A->.a
 
1
0->S
S'->S.
A->S.A
A->.SA
A->.a
->$
accept
2
0->A
S->A.S
S->.AS
S->.b
A->.SA
A->.a
 
3
0->a
1->a
2->a
5->a
7->a
A->a. 
4
0->b
S->b. 
5
1->S
5->S
7->S
A->S.A
A->.SA
A->.a
 
6
1->A
5->A
7->A
A->SA. 
7
2->S
S->AS.
A->S.A
A->.SA
A->.a
 
8
2->A
8->A
S->A.S
S->.AS
S->.b
 
9
8->S
A->AS. 

FIRST(A)、FIRST(S)、FOLLOW(A)、FOLLOW(S)都是{a,b},7可能有冲突,因为当前状态输入a的情况下,不能确定按S->AS.规约还是移入a。

4.7 更强大的LR语法分析器

学习编译原理真是个痛并快乐的过程,网上说龙书翻译的还行,个人感觉也是如此,只是学习的时候如果希望从头读一遍就理解是不可能的,通常要看3-4次才能理解,而且每次阅读的时候都会有新的收获。

学习4.7.5的时候怎么都想不明白例4.64怎么得出的自发向前看符号,再回头看一遍4.7,并且手动构造下LR项集族,马上明白了。

学习这一节最重要的是理解4.7.2开头对于算法4.53的解释,明白了以后这一节基本也就没问题了

为理解4.7.5中算法执行过程,构造例4.6的规范LR项集族

index项集GOTO
0S`->.S    ,$
S->.L=R ,$
S->.R     ,$
L->.*R    ,=
L->.id     ,=
R->L      ,$
 
1  
2  
3  
4  
5  
6  
7  
8  
8  

4.7.1 FIRST(S) = {a}

S'->S

S->SS+

S->SS*

S->a

构造LR项集族如下


index项集GOTO
0S`->.S     , $
S->.SS+  ,a
S->.SS*   ,a
S->.a        ,a
 
1
0->S
S'->S.       ,$
S->S.S+   ,a/+
S->S.S*   ,a/*
S->.a        ,a/+/*
 
2
0->a
S->a.        ,a 
3
1->S
S->SS.+    ,a/+
S->SS.*     ,a/*
S->.A          ,a/+/*
 
4
1->a
S->a.          ,a/+/* 
5
3->+
S->SS+.     ,a/+ 
6
3->*
S->SS*.      ,a/* 
   

LALR项集族只需要将上面2/4合并即可

4.7.3 算法4.6.3前后看了至少5遍,稍微有了些理解

  INIT12
0S'->.S$$$
1S'->S.
S->S.S+
S->S.S*
aaa
2S->a.aaa
3S->SS.+
S->SS.*
 a/+/*a/+/*
4S->SS+.  a/+
5S->SS*.  a/*

4.7.4/4.7.5 类似例4.58



index项集GOTO
0S`->.S    ,$
S->.L=R ,$
S->.R     ,$
L->.*R    ,=
L->.id     ,=
R->L      ,$
 
1  
2  
3  
4  
5  
6  
7  
8  
8  
  • 12
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
目 录 译者序 前言 第1 概论 1 1.1 为什么要用编译器 2 1.2 与编译器相关的程序 3 1.3 翻译步骤 5 1.4 编译器中的主要数据结构 8 1.5 编译器结构中的其他问题 10 1.6 自举与移植 12 1.7 TINY样本语言与编译器 14 1.7.1 TINY语言 15 1.7.2 TINY编译器 15 1.7.3 TM机 17 1.8 C-Minus:编译器项目的一种语言 18 练习 19 注意与参考 20 第2 词法分析 21 2.1 扫描处理 21 2.2 正则表达式 23 2.2.1 正则表达式的定义 23 2.2.2 正则表达式的扩展 27 2.2.3 程序设计语言记号的正则表达式 29 2.3 有穷自动机 32 2.3.1 确定性有穷自动机的定义 32 2.3.2 先行、回溯和非确定性自动机 36 2.3.3 用代码实现有穷自动机 41 2.4 从正则表达式到DFA 45 2.4.1 从正则表达式到NFA 45 2.4.2 从NFA到DFA 48 2.4.3 利用子集构造模拟NFA 50 2.4.4 将DFA中的状态数最小化 51 2.5 TINY扫描程序的实现 52 2.5.1 为样本语言TINY实现一个扫描 程序 53 2.5.2 保留字与标识符 56 2.5.3 为标识符分配空间 57 2.6 利用Lex 自动生成扫描程序 57 2.6.1 正则表达式的Lex 约定 58 2.6.2 Lex输入文件的格式 59 2.6.3 使用Lex的TINY扫描程序 64 练习 65 编程练习 67 注意与参考 67 第3 上下文无关文法及分析 69 3.1 分析过程 69 3.2 上下文无关文法 70 3.2.1 与正则表达式比较 70 3.2.2 上下文无关文法规则的说明 71 3.2.3 推导及由文法定义的语言 72 3.3 分析树与抽象语法树 77 3.3.1 分析树 77 3.3.2 抽象语法树 79 3.4 二义性 83 3.4.1 二义性文法 83 3.4.2 优先权和结合性 85 3.4.3 悬挂else问题 87 3.4.4 无关紧要的二义性 89 3.5 扩展的表示法:EBNF和语法图 89 3.5.1 EBNF表示法 89 3.5.2 语法图 91 3.6 上下文无关语言的形式特性 93 3.6.1 上下文无关语言的形式定义 93 3.6.2 文法规则和等式 94 3.6.3 乔姆斯基层次和作为上下文无关 规则的语法局限 95 3.7 TINY语言的语法 97 3.7.1 TINY的上下文无关文法 97 3.7.2 TINY编译器的语法树结构 98 练习 101 注意与参考 104 第4 自顶向下的分析 105 4.1 使用递归下降分析算法进行自顶向下 的分析 105 4.1.1 递归下降分析的基本方法 105 4.1.2 重复和选择:使用EBNF 107 4.1.3 其他决定问题 112 4.2 LL(1)分析 113 4.2.1 LL(1)分析的基本方法 113 4.2.2 LL(1)分析与算法 114 4.2.3 消除左递归和提取左因子 117 4.2.4 在LL(1)分析中构造语法树 124 4.3 First集合和Follow集合 125 4.3.1 First 集合 125 4.3.2 Follow 集合 130 4.3.3 构造LL(1)分析表 134 4.3.4 再向前:LL(k)分析程序 135 4.4 TINY语言的递归下降分析程序 136 4.5 自顶向下分析程序中的错误校正 137 4.5.1 在递归下降分析程序中的错误 校正 138 4.5.2 在LL(1)分析程序中的错误校正 140 4.5.3 在TINY分析程序中的错误校正 141 练习 143 编程练习 146 注意与参考 148 第5 自底向上的分析 150 5.1 自底向上分析概览 151 5.2 LR(0)项的有穷自动机与LR(0)分析 153 5.2.1 LR(0)项 153 5.2.2 项目的有穷自动机 154 5.2.3 LR(0)分析算法 157 5.3 SLR(1)分析 160 5.3.1 SLR(1)分析算法 160 5.3.2 用于分析冲突的消除二义性 规则 163 5.3.3 SLR(1)分析能力的局限性 164 5.3.4 SLR(k)文法 165 5.4 一般的LR(1)和LALR(1)分析 166 5.4.1 LR(1)项的有穷自动机 166
### 回答1: 编译原理龙书第四主要讲述了词法分析器的设计与实现。词法分析器的主要作用是将源代码转化为一个词法单元序列。 在词法分析器的设计中,需要确定输入的文法,构造有限自动机(DFA)并最小化它,生成词法单元并将其输出。在实现中,可以采用手工编写DFA、使用生成器(如Lex和Flex)、使用正则表达式引擎(如PCRE)等不同方法。 本中重点介绍了正则表达式的语法和特性,以及基于DFA的词法分析器生成器Flex的使用。在实现词法分析器时需要考虑错误处理和效率,同时保证正确性和完整性。 总体来说,词法分析器的设计与实现是编译器构建中的重要一环。掌握词法分析器的设计与实现可以提高编译器的开发效率和质量,也能够提高对编译原理的理解。 ### 回答2: 编译原理龙书第四主要讲述了词法分析器的设计和实现。 词法分析器的任务是将源程序中的字符序列转换为单词序列,单词是指语言中的最小单元,包括关键字、标识符、常量、运算符等。词法分析器使用有限状态自动机(DFA)来识别单词,并将单词传递给语法分析器进一步分析。 第四详细介绍了DFA的构造方法,包括正则表达式到NFA的转换以及NFA到DFA的子集构造法。同时也介绍了如何最小化DFA,以减少DFA中状态的数量,提高词法分析器的效率。 此外,第四还讨论了错误处理和词法单元的表示方法。错误的检测和处理是词法分析器的重要任务之一,常用的处理方法包括返回错误信息、跳过错误单词或者将错误单词视为一个token进行处理。词法单元的表示方法也有多种选择,常见的是将token表示为一个结构体,包括单词的种类、属性、行号等信息。 总之,第四编译原理中非常重要的一,词法分析器是编译器中的第一个组件,其正确性和效率对整个编译过程都具有决定性的影响。因此,认真学习和理解本内容对编译原理学习有着重要的意义。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值