111
湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理 Compiler Principles 第三章 词法分析

编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

  • Upload
    others

  • View
    33

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

湖南大学信息科学与工程学院

软件工程系 杨金民

2018

编译原理Compiler Principles

第三章 词法分析

Page 2: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

第三章 词法分析

• 1. 词法分析的含义;

• 2. 词法分析的基本概念;

• 3. 正则表达式——词法单元模式的表达;

• 4. 状态转换图;

• 5. 词法分析器构造工具;

• 6. 有穷状态自动机;

• 7. 从正则表达式到NFA,DFA的映射方法;

Page 3: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

词法分析

• 词法分析/扫描(lexical analysis, scanning)

• 高级语言程序的源文件(文本文件),可将其看作字符流。

• 如何把源程序文件中的字符流它识别为词素流;

• 例如:return (initial<=10)?100:(position+initial**2);

return ( initial <= 10 ) ? 100 : ( position + initial ** 2 ) ;

Page 4: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

词法分析

• 词素有类概念:预定义符和自定义符;

• 预定义符有:保留字,运算符,标点符,特义符;

• 词素流:可以表达在符号表:row_id name type class v_class row_num

1 return 预留 保留字 120

2 ( 预留 特义符 120

3 initial 自定义 局部变量 int 120

4 <= 预留 运算符 float 120

5 10 自定义 常量 数值 1206 ? 预留 标点符号 120

Page 5: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

语法分析中的三个概念

词法单元(token):词素的类概念,例如,自定义符;

词素(lexme):字符序列;

– 词法单元的实例;例如,上例中的position,initial。

词法单元的模式(pattern)

– 词法单元的构成规约;

Page 6: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

词法分析要解决的问题

• 要解决的问题:如何从字符流切分识别为词素流。

return ( initial <= 10 ) ? 100 : ( position + initial ** 2 ) ;

forward

lexemeBegin

如何描述词法单元的模式? 正则表达式

词法单元的模式:从左到右的字符序列,在其组成上的约束条件。如果一个字符串匹配某个词法单元的模式,就说它是该词法单元的一个实例,称之为词素

Page 7: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

模式表达中的概念

• 字符(character):字符集,例如,ASCII字符集:字母集,

数字集,标点符号集;

• 串(string): 某个字符集下的字符串。注意:串不是集合。

串s的长度记为|s|。空串用ε表示。

• 语言(language):串的集合。

例如:C语言, Java语言,英语,汉语。,{a}是语言。

在语言中,串有语义。 字,词,句,段,文都是串。

串s的前缀(prefix), 后缀(suffix), 子串(substring),子序列(subsequence): 去掉了一些其中的字符。

Page 8: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

串的运算

串的连接运算:也叫“乘积”运算,串x连接串y记为xy。结

果还是为串。

例如, x=my, y =house, 那么xy =myhouse;

自然有:sε = εs = s

串的“指数”运算: si = si-1s; s0 = ε

例如, x=my, 那么x3 =mymymy;

表达串接特性

表达重复串接性

Page 9: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

语言的运算

并运算,联接,闭包三种运算: 结果还是为语言。语言L和M

并运算:LM = L | M = {s| sL 或者 sM};

联接运算: LM = {st | sL , tM};

闭包运算:L的Kneene闭包:

L的正闭包:

L= {A, B,...,Z, a,b, ...., z}, D = {0,1,2,3,4,5,6,7,8,9}

LD ,LD中包含的串元素的个数各为多少?

L0={ε}。L4, L*, D+, L(LD)*分别是什么?

ii LL 0

*

ii LL

1

可选性

串接的可搭配性

重复次数的可随意性

Page 10: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

语言运算的例子

• L= {A, B,...,Z, a,b, ...., z}, D = {0,1,2,3,4,5,6,7,8,9}

• LD = {A, B,...,Z, a,b, ...., z, 0,1,2,3,4,5,6,7,8,9};

• (LD)2 = (LD)(LD) = {AA, AB, Az, A0, A9,...., 9A,9B, 99},

其中的串元素各个数为:

• (LD)* = {ε} (LD) (LD)2 ... (LD)

• 因此,L(LD)*是以字母开头,由字母和数字组成的串的集合。

2162

162 62CC

注意:(LD)n和(LD)*,(LD)+是完全不同的概念

Page 11: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式—描述串接约束—词法单元的模式

语言运算表达式就称作正则表达式(Regular expression):

表达式中通常是变量(斜体字)运算表达式. 并运算符:或|。

语言运算的结合律和交换律,不言而喻;但(a|b)* ≠ a*| b*

三种运算的优先级:*(+) > 联接 > 或|

正则表达式也可给它取一个名字,随后用于其它正则表达式:

例如,C语言的自定义标示符的一个正则定义可以是: letter_ → A | B | ... | Z | a | b | ... | z | _ digit → 0 | 1 | 2 | ... | 9 id → letter_ (letter_ | digit)*

Page 12: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式表达词法单元的模式

digit → 0 | 1 | 2 | ... | 9 digits → digit digit* = digit+

optionalFraction → . digits | ε

optionalExponent → (E(+ | - | ε ) digits) | ε

number → digits optionalFraction optionalExponent

问题:01匹配number吗? 1.0匹配number吗?

1.匹配number吗?

Page 13: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式的标记符扩展

基本运算符:并、连接、Kleene闭包(*)

扩展的标记符:

0个或多个实例: (r)* = r*r , r* = r+ | ε

1个或多个实例:(r)+ = rr* = r*r , r* = r+ | ε

0个或1个实例:ε | r = r?

字符类:连续的字符中的任选其一,例如

a1 | a2 | …| an = [a1a2…an] = [a1- an]

a | b | c | d | e = [a - e]

仅仅只是使正则表达式更简洁。

Page 14: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

简洁的正则表达式例子

letter_ → [A- Z a - z _ ] digit → [0 - 9] id → letter_ (letter_ | digit)*

digits → digit+

number → digits (.digits )?( E [+ - ]? digits)?

Page 15: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式的特性

字符串在构成上的无缝串接约束;这些串接约束必须相互独立,

不能重贴交叉:

例如:asdfgghjkweyr38839ssdf

只能

约束1 约束2 约束3

约束1约束2

约束3

id → letter_ (letter_ | digit)* digits → digit+

number → digits (. digits )?( E [+ - ]? digits)?

Page 16: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

程序语言的词法单元及其正则表达式

letter_ → [A- Z a - z _ ] digit → [0 - 9] digits → digit+

customed identifier: id → letter_ (letter_ | digit)* number → digits (. digits )?( E [+ - ]? digits)?reserved keywords:

if→ digitselse → digits;operator→ = | < | > | == | <= | >= | != punctuation →; |,|“ |” |‘ |’ space →( blank | tab | newline )+

Page 17: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

随堂测试1

character → [A- Z a - z 0-9]

SQL语言中可模糊查询,比如: LIKE “zhang%”, 为模糊

查询,其中%可以在任意位置,请用正则表达式表达该类

模糊查询的模式。

IP地址例子为1.192.21.0,即0~255的四个数用点隔开。请

写出IP地址得正则表达式。

Page 18: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式例子

letter_ → [A- Z a - z _ ] digit → [0 - 9] id → letter_ (letter_ | digit)*

digits → digit+

number → digits (.digits )?( E [+ - ]? digits)?

Page 19: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

词法分析算法

return ( initial <= 10 ) ? 100 : ( position + initial ** 2 ) ;

forward

lexemeBegin

string s= ε; i, RE[i].math = true; //所有词法单元的正则表达式while ( i, RE[i].math == true) { s = s + 下一个字符; i, if (RE[i].math == true) if s does not math RE[i] RE[i].math = false;}

得出了词素,也得出了它所属的词法单元

Page 20: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

词法单元的正则表达式的状态转换图

将字符流切分成词素流,表达了一个词素的获取过程。

start0 =

<

>

1 =

other

2 =

other

3 =

other

8

9

6

7

4

*

*

5 *

return operator. >

return operator. >=

return operator. <

return operator. <=

return operator. =

return operator. ==

Page 21: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

词法单元的正则表达式的状态转换图

将字符流切分成词素流,表达了一个词素的获取过程。

start0 =

<

>

1 =

other

2 =

other

3 =

other

8

9

6

7

4

*

*

5 *

return operator. >

return operator. >=

return operator. <

return operator. <=

return operator. =

return operator. ==

状态转换图

Page 22: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式的状态转换图

start 0letter_

10.other 11

letter_ | digit

*

正则表达式: id → letter_ (letter_ | digit)*

start 0i

23.not letter_ | digit

25*f

24

正则表达式: if → if

Page 23: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式的状态转换图

Eother20 *

start 0digit

13.

14digit

15E

16+|-

17digit

18other

19

digit digit digit

digitother

21 *

正则表达式: number → digits (. digits )?( E [+ - ]? digits)?

Page 24: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式的兼容性vs最长匹配原则

start 0letter_

10.other 11

letter_ | digit

*

正则表达式: id → letter_ (letter_ | digit)*

start 0i

23.not letter_ | digit

25*f

24

正则表达式: if → if

Page 25: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

基于状态转换图的词法分析体系结构state = 0; while (1) {

c = Char(forward);swith(state) {

case 0: if (c is letter_ ) // id state =10;else if (c = '<') //operator state = 2;else if (c is digit) // number state =12;

forward++;break;

case 10:if (!(c is not letter_ or digit)) forward; find_id(lexemeBegin, forward -1); lexemeBegin = forward; state = 0; }else forward++;break;

if(area>=len*h/2-2)

forward

lexemeBegin

0letter_

10.other11

letter_ | digit

*

状态,以及输入字符驱动下的状态变迁

Page 26: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

随堂测试2

Eother20 *

start 12digit

13.

14digit

15E

16+|-

17digit

18other

19

digit digit digit

digitother

21 *

2.对正则表达式: number → digits (. digits )?( E [+ - ]? digits)?

写出该状态转换图的词法分析程序。

1. 写出(a|b)*a(a|b)(a|b)的状态转换图。

Page 27: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.5 词法分析器生成工具Lex

词法单元的正则表达式 → 状态转换图 → 词法分析代码

工具Lex

表达 生成 生成

lex.l lex工具 C编译器 lex.yy.c a.out

a.out 源程序的字符流 词素流

Page 28: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.5 词法分析器生成工具Lex

词法单元的正则表达式 → 状态转换图 → 词法分析代码

工具Lex

表达 生成 生成

lex.l lex工具 C编译器 lex.yy.c a.out

a.out 源程序的字符流 词素流

Page 29: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

词法分析器构造接下来要解决的问题

从正则表达式 状态转换图,在前面是手工构造的,

能否有一种方法(算法),以正则表达式表达式为输入,状态

转换图为输出呢?

状态转换图有哪些类型?各种类型之间的关系如何?

Page 30: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式的状态转换图的分类

Eother20 *

start 12digit

13.

14digit

15E

16+|-

17digit

18other

19

digit digit digit

digitother

21 *

正则表达式: number → digits (. digits )?( E [+ - ]? digits)?

b

start 0 1 2b

3a b(a|b)*abb

a

Page 31: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

另一个例子

语言L((aa*|bb*)的状态转换图:

bstart 0

1 2a

εa 开始状态:一个

接受状态:可多个

转换函数

边上的标号3 4

b

ε

Page 32: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.6 有穷自动机

将状态转换图形式化,上升为一种理论知识,被称作有穷自动

机(finite automata)。为两类:

– 非确定有穷自动机NFA(Nondeterministic Finite

Automata)。图中的某一状态结点,一个驱动符号(即边上

的标号),可引出多条边, ε 可以是边上的标号。

– 确定性有穷自动机DFA( Deterministic Finite

Automata):图中的状态结点,一个驱动符号,有且仅有

一条出边。驱动符号不包含ε 。

Page 33: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

NFA 正则表达式(a|b)*abb的NFA表示。NFA的图表示

a

b

start 0 1 2b

3a b

开始状态:一个

接受状态:可多个

转换函数;

边上的标号。

NFA的表表示法:转换表

Page 34: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

NFA的另一个例子

语言L((aa*|bb*)的NFA:

bstart 0

1 2a

εa 开始状态:一个

接受状态:可多个

转换函数

边上的标号3 4

b

ε

Page 35: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.6.2. DFA匹配(DFA模拟)

state = 0; ;c = nextChar();while (c != eof ) { state = move(state, c); c = nextChar();}if (state 在 接受状态集合F) return true;else return false;

Page 36: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

NFA中ε-closure()函数

开始状态0:

ε-closure()函数:S = ε-closure(0) = {0,1,2,4, 7} ; 其中0是

自己; 1,7是直接的ε后继状态; 2和4是通过1的ε间接后继;

ε-closure(S) = sS ε-closure(s) = {0,1,2,4, 7}= S;

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

εε

ε

Page 37: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

S0在字符a驱动下的后继状态集

开始状态的集合:S0 = ε-closure(0) = {0,1,2,4, 7};

状态集合S0在字符a的驱动下的后继状态集合T:

S'0,a = move(S0,a) = {3, 8};

S1,1 = ε-closure(S'0,a) = {3,6,1,2,4,7,8};

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 38: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

S0在字符b驱动下的后继状态集

开始状态的集合:S0 = {0,1,2,4, 7};

状态集合S0在字符b的驱动下的后继状态集合:

S'0,b = move(S0,b) = {5};

S1,2 = ε-closure(S'0,b) = {5,6,1,2,4,7};

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 39: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

DFA和NFA的匹配对比

state = 0; c = nextChar();while (c != eof ) { state = move(state, c); c = nextChar();}if (state接受状态集F!=) return true;else return false;

states = ε-closure(0) ;c = nextChar();while (c != eof ) { states=ε-closure(move(states,c); c = nextChar();}if (states接受状态集F!=) return true;else return false;

DFA匹配 NFA匹配

Page 40: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.7 从正则表达式到NFA

• 正则表达式r= (a|b)*abb, 先构建其语法分析树:

a br1 r2

r3

|

( )r4 *

r5 r6

r7

a

r8

r9

b

r10

r11

b仅只有三种运算:

r= s|t

r= st

r= s* (s+)

Page 41: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式的NFA实例

对于正则表达式r= (a|b)*abb

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

εε

ε

Page 42: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.7 简单正则表达式的NFA

对于表达式 ε,构建其NFA:

对于表达式(例如 (a|b)*abb) 中的单个字符a,构建其NFA:

fstart

fstart

ia

Page 43: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

并运算与NFA组合的对应

对于表达式r =s| t ,构建其NFA:

ftstart

it

t

startir

startis fs

s

ε fr

ε

ε

ε

ftit

t

startir

is fs

s

ε fr

ε

ε

ε

Page 44: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

联接运算与NFA组合的对应

对于表达式r =s t ,构建其NFA:

ftstart

it

tstartis fs

s

εstart

startis ftfsit

ts

Page 45: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

*运算与NFA组合的对应

对于表达式r =s*,构建其NFA:ε

startir

startis fs

sfr

ε

ε

ε

startir is fs

sfr

ε

ε

ε

ε

Page 46: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式的NFA构建例子

对于正则表达式r= (a|b)*abb

1ε 3

b

2a

4 5ε6

start

ε

ε

b4 5

2a 3

Page 47: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式的NFA构建例子

对于正则表达式r= (a|b)*abb

b

start1

ε 2 3a

4 5ε60 ε

ε

εε

ε

1ε 3

b

2a

4 5ε6

start

ε

ε

Page 48: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式的NFA构建例子

对于正则表达式r= (a|b)*abb

7 8ε a

b

start1

ε 2 3a

4 5ε60 ε

ε

εε

ε

b

start1

ε 2 3a

4 5ε60 ε

ε

εε

ε

7a 8

Page 49: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式的NFA构建例子

对于正则表达式r= (a|b)*abb

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0 ε

ε

εε

ε

Page 50: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

随堂测试3

• 对正则表达式:((ε|a)b*)*, 画出其NFA

Page 51: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

NFA中的开始状态和后继状态

开始状态的集合:S = ε-closure(0) = {0,1,2,4, 7}; 其中0是自

己; 1,7是直接的ε后继状态; 2和4是通过1的ε间接后继;

ε-closure(S) = sS ε-closure(s) = {0,1,2,4, 7};

状态集合S在字符a的驱动下的后继状态集合T:

T = ε-closure(move(S,a) )= ε-closure(sS move(s,a)) ={3, 8};

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

εε

ε

Page 52: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

NFA中开始状态的ε闭包

开始状态的集合:S = ε-closure(0) = {0,1,2,4, 7}; 其中0是

自己; 1,7是直接的ε后继状态; 2和4是通过1的ε间接后继;

ε-closure(S) = sS ε-closure(s) = {0,1,2,4, 7};

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 53: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

NFA中状态集的后继状态集(a)

开始状态的集合:S0 = ε-closure(0) = {0,1,2,4, 7};

状态集合S0在字符a的驱动下的后继状态集合T:

T = ε-closure(move(S,a) )= ε-closure(sS move(s,a)) ={3, 8};

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 54: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

状态集{3,8}的ε闭包

开始状态的集合:S0 = {0,1,2,4, 7}的后继状态集合:

S1,1= S0→a = ε-closure( {3, 8} ) = {1,2,3,4,6,7,8};

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 55: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

S0的后继状态(b)

开始状态的集合:S0 = {0,1,2,4, 7};

S1,2= S0→b = ε-closure(move(S,b) )=ε-closure( {5} )

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 56: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

NFA中状态集{5}的ε闭包

S1,2= S0→b = ε-closure( {5} ) ={1,2,4,5,6,7};

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 57: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

NFA中的状态集S1,1的后继状态(a)

已知状态的集合:S1,1 = {1,2,3,4,6,7,8};S2,1= S1,1→a = = ε-closure(move(S1,1, a) )= ε-closure( {3, 8} )

= S1,1;

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 58: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

NFA中状态集S1,1的后继状态(b)

已知状态的集合:S1,1 = {1,2,3,4,6,7,8};S2,2= S1,1→b = = ε-closure(move(S1,1, a) )= ε-closure( {5, 9} )

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 59: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

NFA中状态集{5,9}的ε闭包

已知状态的集合:S1,1 = {1,2,3,4,6,7,8};S2,2= S1,1→b = = ε-closure(move(S1,1, a) )= ε-closure( {5, 9} )

= {1,2,4,5,6,7,9}

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

新状态!!!

Page 60: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

求S1,2的后继状态集(a)

已知状态的集合:S1,2 = {1,2,4,5,6,7};S2,3= S1,2→a = = ε-closure(move(S1,2, a) )= ε-closure( {3, 8} )

= S1,1

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 61: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

求S1,2的后继状态(b)

已知状态的集合:S1,2 = {1,2,4,5,6,7};S2,4= S1,2→b = = ε-closure(move(S1,2, b) )= ε-closure( {5} )

= S1,2

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 62: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

求S2,2 的后继状态(a)

已知状态的集合:S2,2 = {1,2,4,5,6,7,9};S3,1= S2,2→a = ε-closure(move(S1,1, a) )= ε-closure( {3, 8} )

= S1,1

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 63: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

求S2,2 的后继状态(b)

已知状态的集合:S2,2 = {1,2,4,5,6,7,9};S3,2= S2,2→b = ε-closure(move(S1,1, a) )= ε-closure( {5, 10} )

= {1,2,4,5,6,7,10}

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

新状态!!!

Page 64: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

求S3,2 的后继状态(a)

已知状态的集合:S3,2= {1,2,4,5,6,7,10};S4,1= S3,2→a = ε-closure(move(S1,1, a) )= ε-closure( {3, 8} )

= S1,1

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 65: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

求S3,2 的后继状态(b)

已知状态的集合:S3,2= {1,2,4,5,6,7,10};S4,2= S3,2→b = ε-closure(move(S1,1, a) )= ε-closure( {5} )

= S1,2

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

Page 66: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.7.1 由NFA转化成DFA(子集构造法)

正则表达式r= (a|b)*abb,构建其NFA,然后转化为DFA:

startS0 S1,1

a

S1,2

b a

a

b

S2,2b S3,2

ba

a

b

Page 67: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

随堂测试4

• 对正则表达式:((ε|a)b*)*, 在上一随堂测试的基础上

(画出了其NFA),将其NFA转化为DFA。

Page 68: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9.6 最小化DFA的状态数量

对于DFA中的状态,分为两个集合S和F:

startS T

a

Ub a

a

b

Zb

Qb

aa

b

Page 69: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9.6 最小化DFA的状态数量

对S集合中的任一元素s,如果move(s,a)或者move(s,b)不在S

中,则将其从S脱离出来;

startS T

a

Ub a

a

b

Zb

Qb

aa

b

Page 70: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9.6 最小化DFA的状态数量

对于表达式r =s t ,构建其NFA:

startS T

a

Ub a

a

b

Zb

Qb

aa

b

Page 71: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9.6 最小化DFA的状态数量

对于表达式r =s t ,构建其NFA:

startS T

a

Ub a

a

b

Zb

Qb

aa

b

Page 72: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3. 9.6 最小化DFA的状态数量

对于表达式r =s t ,构建其NFA:

startS T

a

Ub a

a

b

Zb

Qb

aa

b

Page 73: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3. 9.6 最小化DFA的状态数量

对于表达式r =s t ,构建其NFA:

startS T

a

Ub a

a

b

Zb

Qb

aa

b

Page 74: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9.6 最小化DFA的状态数量

Ub

b

b

startS T

aa

a

Zb

Qb

aa

startS T

a

b

a

Zb

Qb

aa

b

Page 75: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

复习:空串ε在表达和衔接上很有用

对于表达式r =s| t ,构建其NFA:

ftstart

it

t

startir

startis fs

s

ε fr

ε

ε

ε

ftit

t

startir

is fs

s

ε fr

ε

ε

ε

Page 76: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

复习:空串ε在表达和衔接上很有用

对于表达式r =s*,构建其NFA:ε

startir

startis fs

sfr

ε

ε

ε

startir is fs

sfr

ε

ε

ε

ε

Page 77: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

复习:最小化DFA的状态数量

S1,2

b

b

b

startS0 T

aa

a

Zb

Qb

aa

startS T

a

b

a

Zb

Qb

aa

b

Page 78: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

为什么S0和S1,2可以合并:它们等价

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

S0

S1,2

Page 79: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

复习:软件构造方法学:用软件编软件——词法分析器生成工具Lex

词法单元的正则表达式 → 状态转换图 → 词法分析代码

工具Lex

表达 生成 生成

lex.l lex工具 C编译器 lex.yy.c a.out

a.out 源程序的字符流 词素流

Page 80: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9 从正则表达式到DFA

• 正则表达式r= (a|b)*abb

• 构建其语法分析树:

a b

|

*a

b

b

Page 81: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9 从正则表达式到DFA

• 正则表达式r= (a|b)*abb

• 构建其语法分析树。标识每一个叶结点。

实例:abbaabbbabbbaabb

a b

|

*a

#

b

b

1 2

3

4

5

6

Page 82: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

只有一个实例:a,它的:

第一个字符来自位置1: firstPos = 1;

最后一个字符来自位置1: lastPos = 1;

3.9 正则表达式的第一个字符,和最后一个字符函数

a b

|

*a

#

b

b

1 2

3

4

5

6

看其实例的第一个字符,和最后一个字符。

ε不是其实例

Page 83: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9 正则表达式的firstPos, lastPos

a b

|

*a

#

b

b

1 2

3

4

5

6

1#叶的实例的第一个字符,和最后一个字符。

只有一个实例:a,它的:

firstPos = 1; lastPos = 1;

ε不是其实例,于是

{1} {1}nullable = false

nullable = false

Page 84: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9 正则表达式的firstPos, lastPos

a b

|

*a

#

b

b

1 2

3

4

5

6

2#叶的的第一个字符,和最后一个字符。

{1} {1}nullable = false

nullable = false{2} {2}

只有一个实例:b,它的:

firstPos = 2;

lastPos = 2;

Page 85: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9 正则表达式的firstPos, lastPos

a b

|

*a

#

b

b

a:firstPos = 1,lastPos = 1;b:firstPos = 2,lastPos = 2;

1 2

3

4

5

6

结点a|b的只有2个实例:

ε不是其实例

{1,2} {1,2}nullable = false

{1} {1} {2} {2}

Page 86: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9 正则表达式的firstPos, lastPos

a b

|

*a

#

b

b

a:firstPos = 1,lastPos = 1;b:firstPos = 2,lastPos = 2;ab:firstPos = 1,lastPos = 2;ba:firstPos = 2,lastPos = 1;

1 2

3

4

5

6

结点(a|b)*的实例:

ε是其实例

{1,2} {1,2}nullable = true

{1,2} {1,2}

{1} {1} {2} {2}

Page 87: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9 正则表达式的firstPos, lastPos

a b

|

*a

#

b

b

a:firstPos = 3,lastPos = 3;ba:firstPos = 2,lastPos = 3;aa:firstPos = 1,lastPos = 3;aba:firstPos = 1,lastPos = 3;

1 2

3

4

5

6

结点(a|b*a的实例:

ε不是其实例 {1,2,3} {3}nullable = false

{1,2} {1,2}

{1,2} {1,2}

{1} {1} {2} {2}

{3} {3}

Page 88: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9 正则表达式的firstPos, lastPos

a b

|

*a

#

b

b

abb#:firstPos = 3,lastPos = 6;aabb#:firstPos = 1,lastPos = 6;babb#:firstPos = 2,lastPos = 6;

1 2

3

4

5

6

结点(a|b*abb#实例:nullable =false

{1,2,3} {6}

Page 89: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9 正则表达式的firstPos, lastPos

• 对语法分析树中的每一结点n:

• nullable(n);

• firstPos(n);

• lastPos(n);

a b

|

*a

#

{1} {1} {2} {2}

{3} {3}

b{4} {4}

b{5} {5}

{6} {6}

{1,2} {1,2}

{1,2} {1,2}

{1,2,3} {3}

{1,2,3} {4}

{1,2,3} {5}

{1,2,3} {6}

Page 90: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

3.9 正则表达式的firstPos, lastPos

语法分析树中,自底向上的三个函数求解方法:

结点n nullable(n) firstPos(n) lastPos(n)为ε的叶结点 true 序号为i的叶结点 false {i} {i}

| 运算结点:n = c1 | c2

nullable(c1)OR nullable(c2)

firstPos(c1) firstPos(c2) lastPos(c1) lastPos(c2)

cat运算结点:n = c1c2 nullable(c1)AND

nullable(c2)

if nullable(c1)firstPos(c1) firstPos(c2)elsefirstPos(c1)

if nullable(c2)lastPos(c1) lastPos(c2)elselastPos(c2)

*运算结点:n = c1*

true firstPos(c1) lastPos(c1)

Page 91: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

对于叶结点i——定义函数followPos(i)

实例:aabb:第一个a的位置序号为1,紧接其后的标号a的位置序号为3;

ababb:第一个a的位置序号为1,紧接其后的标号b的位置序号为2;

aaabb:第一个a的位置序号为1;紧接其后的标号a的位置序号为1;

b

|

*

a1 2

a3

b4

b5

#6

followPos(1)={1,2,3}

所有可能接在其后

Page 92: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

对于叶结点i——定义函数followPos(i)

实例:babb:第一个b的位置序号为2,紧接其后的标号a的位置序号为3;

baabb:第一个b的位置序号为2,紧接其后的标号a的位置序号为1;

abbabb:第一个b的位置序号为2;紧接其后的标号b的位置序号为2;

b

|

*

a1 2

a3

b4

b5

#6

followPos(2)={1,2,3}

所有可能接在其后

Page 93: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

函数followPos(i)的求法

对于cat运算的结点n:其左子结点为c1, 右子结点为c2,ilastPos(c1): followPos(i) = { j | jfirstPos(c2)};

b

|

*

a1 2

a3

b4

b5

#

6

{1,2} {1,2} {3} {3}

{4} {4}

{5} {5}{1,2,3} {3}

{1,2,3} {4}

{1,2,3} {5}

{1,2,3} {6}

{6} #{6}

结点n followPos(n)

1 {3}

2 {3}

3 {4}

4 {5}

5 {6}

6

Page 94: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

函数followPos(i)的求法

对于*运算的结点n:jlastPos(n): followPos(j) = { i | ifirstPos(n)};

b

|

*

a1 2

a3

b4

b5

#6

{1,2} {1,2} {3} {3}

{4} {4}

{5} {5}{1,2,3} {3}

{1,2,3} {4}

{1,2,3} {5}

{1,2,3} {6}

{6}

结点n followPos(n)

1 {1,2, 3}

2 {1,2, 3}

3 {4}

4 {5}

5 {6}

6

Page 95: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

函数followPos(i)的求法

实例:a:没有followPosb:没有followPos

b

|

*

a1 2

a3

b4

b5

#6

{1,2} {1,2} {3} {3}

{4} {4}

{5} {5}{1,2,3} {3}

{1,2,3} {4}

{1,2,3} {5}

{1,2,3} {6}

{6}

对于|运算的结点n:不存在followPos判断的基础

Page 96: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

S1,2 ={ j | iS0,char(i) =b, j followPos(i)}

从正则表达式直接构建DFA

S1,1 = { j | iS0,char(i) =a, j followPos(i)} = {1,2,3,4};

b

|*

a1 2

a3

b4

b5

#6

{1,2} {1,2} {3} {3}

{4} {4}

{5} {5}{1,2,3} {3}

{1,2,3} {4}

{1,2,3} {5}

{1,2,3} {6}

{6}

结点n followPos(n)

1 {1,2, 3}

2 {1,2, 3}

3 {4}

4 {5}

5 {6}

S0=firstPos(树根)={1,2,3};

= {1,2,3} = S0;

Page 97: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

从正则表达式直接构建DFA

S2,1 = { j | iS1,1,char(i) =a, j followPos(i)}={1,2,3,4} =S1,1;

b

|

*

a1 2

a3

b4

b5

#6

{1,2} {1,2} {3} {3}

{4} {4}

{5} {5}{1,2,3} {3}

{1,2,3} {4}

{1,2,3} {5}

{1,2,3} {6}

{6}

结点n followPos(n)

1 {1,2, 3}

2 {1,2, 3}

3 {4}

4 {5}

5 {6}

S2,2 = { j | iS1,1,char(i) =b, j followPos(i)}

= {1,2,3,5}

Page 98: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

从正则表达式直接构建DFA

S3,1 = { j | iS2,2,char(i) =a, j followPos(i)}={1,2,3,4} =S1,1;

b

|

*

a1 2

a3

b4

b5

#6

{1,2} {1,2} {3} {3}

{4} {4}

{5} {5}{1,2,3} {3}

{1,2,3} {4}

{1,2,3} {5}

{1,2,3} {6}

{6}

结点n followPos(n)

1 {1,2, 3}

2 {1,2, 3}

3 {4}

4 {5}

5 {6}

S3,2 = { j | iS2,2,char(i) =b, j followPos(i)}

= {1,2,3,6}

Page 99: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

从正则表达式直接构建DFA

S4,1 = { j | iS3,2,char(i) =a, j followPos(i)}={1,2,3,4} =S1,1;

b

|

*

a1 2

a3

b4

b5

#6

{1,2} {1,2} {3} {3}

{4} {4}

{5} {5}{1,2,3} {3}

{1,2,3} {4}

{1,2,3} {5}

{1,2,3} {6}

{6}

结点n followPos(n)

1 {1,2, 3}

2 {1,2, 3}

3 {4}

4 {5}

5 {6}

S4,2 = { j | iS3,2,char(i) =b, j followPos(i)}

= {1,2,3}= S0

Page 100: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

从正则表达式直接构建DFA的含义

startS0 S1,1a

b

a

S2,2b S3,2

ba

a

b

123

1234 1235 1236

1(a)2(b)3(a)

可以,可能,所有可能(意思是还没有发生,还在等待发生)

一旦发生,来了个a,那就变迁到下一个(可以,可能,所有可能)

穷举策略

Page 101: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

从正则表达式直接构建DFA

startS0 S1,1a

b

a

S2,2b S3,2

ba

a

b

123

1234 1235 1236

正因为结点是表示“可以,可能,所有可能,还没有发生,还在等待”,所以S2,2(1235)并不表示是接受状态。而S3,2(1236)则表示5(b)已经发生了,自然是接受状态。

这就是为什么要在树中加一个“6(#)”的原因。

Page 102: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

有穷状态机中状态的含义

① 表明它有个历史;即以前已经接受了哪些字符。但历

史可能不唯一。

② 表明它当前“可以,可能,所有可能,还没有发生,

还在等待”的字符。

③ 一旦接受了某个字符,就会转到下一个“可以,可能,

所有可能,还没有发生,还在等待”的状态。

Page 103: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

小结1:词法分析

语言:既有类概念,也有实例概念

词法单元(类概念) 模式 词素(实例概念)

字符 字符串

语言的类概念:词法单元的集合;

语言的实例概念:词素的集合;

匹配

字符串的三种运算 正则表达式

Page 104: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

小结2

正则表达式 DFA 语言的词法分析程序

NFA DFA 状态数的最小化

Page 105: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

随堂测试5

• 对正则表达式:((ε|a)b*)*, 画出其DFA.

• 证明它与(a|b)*等价。

Page 106: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

第二章作业

3.1.1,3.1.2

3.3.2, 3.3.5(1-3,9), 3.3.11, 3.3.12

3.4.1,3.4.2,成绩好的学生选做3.4.3

3.6.2, 3.6.3, 3.6.4

3.7.1, 3.7.3

3.9.1

3.9.2

3.9.4

Page 107: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

第一次讨论课

第一次讨论课的主题: 词法分析。小主题:

1) 正则表达式转换NFA;

2) NFA确定化为DFA;

3) DFA最小化和词法分析器的状态图最小化;

4) DFA代码化;

5) TINY编译器与TM虚拟机;

6) 词法分析器自动工具(如:FLEX)

自己定题,也可以选择如下内容:

1) Unix/Linux中的grep指令嵌套使用的典型应用案例;

2) 练习3.3.5(4,5,6,8)中的任何一个;

3) 其它习题也可以;

Page 108: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

NFA的化简——基于迁移来减少NFA的状态数

7 8b

10ε a

b

start1

ε 2 3a

4 5ε6 9

b0

ε

ε

ε

ε

ε

0 8b

10a

bstart a

9b

0

ε

ε

7start

b

a

Page 109: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式(0?0?1) *0?0?的NFA

S0={0,1,2,3,4,5} S0,1={3} ; ε-closure({3}) =S0

S0,0={1,2,4,5} ; ε-closure({1,2,4,5}) ={1,2,4,5} =S1

S1,1={3} = S0

S1,0={2,5} ; ε-closure({2,5}) ={2,5} =S2

S2,1={3} = S0

S2,0={} ;

start0 1

02

0 31 4

0 50

Page 110: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

正则表达式(0?0?1) *0?0?的DFA

S0={0,1,2,3,4,5} S0,1={3} ; ε-closure({3}) =S0

S0,0={1,2,4,5} ; ε-closure({1,2,4,5}) ={1,2,4,5} =S1

S1,1={3} = S0

S1,0={2,5} ; ε-closure({2,5}) ={2,5} =S2

S2,1={3} = S0

S2,0={} ;

startS0 S1

0S2

0

1

11

Page 111: 编译原理 Compiler Principles 第三章 词法分析csee.hnu.edu.cn/Content/UploadFiles/2004213/Files/...湖南大学信息科学与工程学院 软件工程系 杨金民 2018 编译原理

谢 谢!谢 谢