语法分析 —— 上下文无关文法

Post on 20-Jan-2016

216 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

语法分析 —— 上下文无关文法. 授课:胡静. 目录. 复习内容 上下文无关文法( CFGs ) 推导 语法分析树和抽象语法 二义性文法 属性文法 YACC. 语法分析器所处的位置. 语法分析的例子. 语法分析总述. 达到的目标:确定输入的 token 流是否符合程序的语法,如果符合的话,要识别出其结构。 语法分析需要如下条件: 对语法进行描述的方法 一个接受器的机制,来确定输入的 token 流是否符合语法描述。 能够还原语法结构的方法。. 为什么不能用正则表达式. 正则表达式可以对 token 进行表示 - PowerPoint PPT Presentation

TRANSCRIPT

语法分析——上下文无关文法

授课:胡静

23/4/21 编译原理 2

目录

复习内容上下文无关文法( CFGs )推导语法分析树和抽象语法二义性文法

属性文法YACC

23/4/21 编译原理 3

语法分析器所处的位置

23/4/21 编译原理 4

语法分析的例子

23/4/21 编译原理 5

语法分析总述

达到的目标:确定输入的 token 流是否符合程序的语法,如果符合的话,要识别出其结构。语法分析需要如下条件:

对语法进行描述的方法一个接受器的机制,来确定输入的 token 流是否符合语法描述。能够还原语法结构的方法。

23/4/21 编译原理 6

为什么不能用正则表达式

正则表达式可以对 token 进行表示用正则表达式对 token 进行描述,而后可以很方便有效的执行(使用 DFA )

不能够使用正则表达式来描述程序语言的语法:正则表达式没有足够的描述能力来描述程序语言的语法。

例如:嵌套的等价结构比如括号嵌套{ (), ()(), (()), (())(), ()(()), (())(()), ((())(())), etc. }

23/4/21 编译原理 7

上下文无关文法

上下文无关文法是一个四元组表示形式 <V,Σ,S,→>V 是非终结符的有限集合Σ 是终结符的有限集合S V ∈ 是一个特殊的非终结符,叫做开始符号→ ⊆ V × (V Σ)∪ * 是一个有限关系,叫做产生式。

上下文无关文法简写为 CFG

23/4/21 编译原理 8

推导

设 G = <V,Σ,S,→> ,是一个上下文无关文法,“直接的推导”关系 ( ) ⇒ 定义为 { <αAγ, αβγ> | A→β }.

例如:设 G 的文法的产生式是 S → aSbS | ε

那么S aSbS⇒aSbS aaSbSbS⇒aaSbSbS aabSbS⇒aabSbS aabbS⇒aabbS aabbaSbS⇒aabbaSbS aabbabS⇒aabbabS aabbab⇒

23/4/21 编译原理 9

上下文无关语言

设 G = <V,Σ,S,→>是 CFG ,由 G 所产生的语言表示为 L(G), L(G) = { x | S * x }⇒L(G) = 从开始符号开始,将产生式作为规则改写的手段,重复的使用,最后得到的终结符号串的集合,叫做 L(G) 。上下文无关语言 (CFLs) 是由上下文无关文法产生的语言。如果 x L(G)∈ ,那么 x 的推导是一个字符串序列 S=α0 , α1 , ... , αn=x, 其中每一个 αi α⇒ i+1 当 0≤i<n 。我们写作 α0 α⇒ 1 ... α⇒ n 。

23/4/21 编译原理 10

举例

设有文法 G ,其产生式是 S → aSbS | ε

那么S aSbS aaSbSbS aabSbS aabbS ⇒ ⇒ ⇒ ⇒ ⇒aabbaSbS aabbabS aabbab⇒ ⇒

也就是说,属于 L(G)

23/4/21 编译原理 11

文法和接受器

上下文无关文法的接受器如下:

语法分析器 = CFG 接受器,当 token 流被接受时,输出相应的推导

例子: LL(k), LR(k), SLR, LALR

23/4/21 编译原理 12

每个正则语言都是 CFL

为每个 RE 归纳的建立一个 CFGε S → εa S → a

R1R2 S → S1S2

R1 | R2 S → S1 | S2

R1 * S → S1 S | ε

23/4/21 编译原理 13

求和的文法

文法:S → E + S | E

E → number | ( S )

Expanded:

可接受的输入的例子:(1+2+(3+4))+5

23/4/21 编译原理 14

推导的例子

23/4/21 编译原理 15

推导和分析树

语法树:描述推导过程的树形结构树的叶子是终结符中间结点是非终结符不能够描述推导步骤的顺序。

23/4/21 编译原理 16

分析树和抽象语法树( AST )

分析树也叫做具体语法树

23/4/21 编译原理 17

推导顺序

可以选择任意顺序来使用产生式;选择任意一个非终结符 A ,比如: αAγ αβγ⇒两个标准的顺序:最左推导和最右推导——使用在不同类的自动语法分析当中。最左推导:总是替换最左边的非终结符

E + S ⇒ 1 + S

最右推导:总是替换最右边的非终结符E + S E + ⇒ E + S

23/4/21 编译原理 18

例子

S → E + S | EE → number | ( S )最左推导

最右推导

相同的分析树:选择的相同的产生式,只是顺序不同。

23/4/21 编译原理 19

二义性文法

考虑另一个文法S → S + S | S * S | number

二义性文法:不同的推导产生不同的分析树。

考虑表达式 1 + 2 * 3

推导 1: S S + S 1 + S 1 + S * S 1 + 2 * S 1 + 2 * 3⇒ ⇒ ⇒ ⇒ ⇒推导 2: S S * S S * 3 S + S * 3 S + 2 * 3 1 + 2 * 3⇒ ⇒ ⇒ ⇒ ⇒

23/4/21 编译原理 20

二义性的影响

不同的分析树对应不同的赋值。对程序来讲,其含义会产生二义性。

23/4/21 编译原理 21

消除二义性

通常可以通过增加非终结符,或者只允许左递归 / 右递归的方式来消除二义性。

T 非终结符强迫了优先级左递归:左结合

23/4/21 编译原理 22

23/4/21 编译原理 23

目录

复习内容上下文无关文法( CFGs )推导语法分析树和抽象语法二义性文法

属性文法YACC

2023年4月21日 星期五

编译原理 24

属性文法举例

产生式 语义规则L→En print(E.val)

E→E1 + T E.val := E1.val + T.val

E→T E.val := T.val

T→T1 * F T.val := T1.val * F.val

T→F T.val := F.val

F→(E) F.val := E.val

F→digit F.val := digit.lexval

2023年4月21日 星期五

编译原理 25

翻译模式

翻译模式给出了使用语义规则进行计算的次序,这样就可以把某些细节表示出来。在翻译模式中,和文法符号相关的属性和语义规则(这里也称语义动作),用“ {}” 括起来,插入到产生式右部合适的位置上。翻译模式给出了使用语义规则进行计算的顺序。

2023年4月21日 星期五

编译原理 26

翻译模式举例

E→TR

R→addop T {print(addop.lexeme)} R1 | ε

T→num {print(num.val)}E

RT

9 {print(‘9’)} - T {print(‘-’)} R

5 {print(‘5’)} + T {print(‘+’)}

2 {print(‘2’)}

R

ε

9-5+2

按深度优先遍历之后

95-2+

2023年4月21日 星期五

编译原理 27

翻译模式举例

产生式 语义规则S→B B.ps := 10

S.ht := B.ht

B→B1B2 B1.ps := B.ps

B2.ps := B.ps

B.ht := max(B1.ht, B2.ht)

B→ B1 sub B2 B1.ps := B.ps

B2.ps := shrink(B.ps)

B.ht := disp(B1.ht, B2.ht)

B→text B.ht := text.h ×B.ps

S→{B.ps := 10} B {S.ht := B.ht}B→{B1.ps := B.ps} B1

{B2.ps := B.ps} B2

{B.ht := max(B1.ht, B2.ht)}B→ {B1.ps := B.ps} B1 sub {B2.ps := shrink(B.ps)} B2

{B.ht := disp(B1.ht, B2.ht)}B→text {B.ht := text.h ×B.ps}

23/4/21 编译原理 28

目录

复习内容上下文无关文法( CFGs )推导语法分析树和抽象语法二义性文法

属性文法YACC

2023年4月21日 星期五

编译原理 29

YACC 简介

YACC: Yet Another Compiler Compiler

YACC 程序程序语言的 YACC 规范说明

程序语言语法分析器

程序语言语法分析器输入串 语法树

2023年4月21日 星期五

编译原理 30

YACC 规格说明

YACC 规格说明—— YACC源程序说明部分翻译规则辅助过程

说明部分%%

翻译规则%%

辅助过程

2023年4月21日 星期五

编译原理 31

YACC 规格说明

用%{和%} 括起来的部分是C 语言程序的正规说明

说明翻译规则和辅助过程里使用的变量和函数的类型

2023年4月21日 星期五

编译原理 32

YACC 规格说明

形如左部→候选 1|候选 2|…|候选 n|

的产生式,在 YACC 规格说明里写成左部 : 候选 1{ 语义动作 1} | 候选 2{语义动作 2} …… | 候选 n{ 语义动作 n} ;

2023年4月21日 星期五

编译原理 33

YACC 规格说明

E→E+T|TT→T*F|F

F→(E)|digit

2023年4月21日 星期五

编译原理 34

LR 语法分析器的结构

一个 LR 分析器实质上是一个带先进后出存储器(栈)的确定有限状态自动机。

LR分析程序

action goto

输出

输入串 a1

Sm

S1

S0

Xm

X1

#

ai an #…… ……

分析表

2023年4月21日 星期五

编译原理 35

LR 语法分析器分析过程举例

文法 G :(1)E E+T (2)E T(3)T T*F (4)T F (5)F (E)(6)F i

状态 ACTION GOTO

i + * ( ) # E T F

0 S5 S4 1 2 3

1 S6 acc

2 r2 S7 r2 r2

3 r4 r4 r4 r4

4 S5 S4 8 2 3

5 r6 r6 r6 r6

6 S5 S4 9 3

7 S5 S4 10

8 S6 S11

9 r1 r7 r1 r1

10 r3 r3 r3 r3

11 r5 r5 r5 r5

2023年4月21日 星期五

编译原理 36

YACC 中的冲突

YACC 可以指出移进 - 归约冲突和归约 - 归约冲突默认情况下:移移进 - 归约冲突中选择移进归约 - 归约冲突中选择先出现的规则来归约

优先级升

2023年4月21日 星期五

编译原理 37

语法分析过程

语法分析开始于词法分析阶段,其输入为词法分析输出的token 序列,输出为语法树语法树和源程序中各个语句的语法结构一一对应,并且作为后续语义分析的重要数据结构词法分析输入的 token 序列中包括诸如变量、数字、操作符等,对应于产生式中的终结符在 token 序列中,各个 token 按照上下文无关文法的规则连接在一起语法分析的任务是将 token 序列中是否采用正确的语法规则分析出来,并且以树形的数据结构表示出来,最后整个源程序将转化为一棵以程序节点为根,非终结符为中间节点,终结符为叶子节点的语法树。

2023年4月21日 星期五

编译原理 38

抽象语法树的树形结构程序

程序头 子程序

代码头 代码体

子程序函数头

过程声明函数声明

代码段变量常数标签

Case 语句If 语句复合语句过程语句赋值语句

复合语句

子程序过程头

2023年4月21日 星期五

编译原理 39

YACC 的例子

YACC 中文件的说明:生成语法分析器文件为 spl.y 。其中进行 SPL 语法的描述,在语法检查和分析过程中,加入语法树节点生成的代码。Spl.y包含了语法规则的描述和语法树节点生成的程序, YACC程序根据这些自动生成 LALR(1) 分析表,并用一系列矩阵存储分析表中的内容

Yacc 的输出文件 rule.h/rule.c 中的 yytable及相关部分代码YACC 程序初始化接收 token 序列的数组数据结构(包含方法),用于语法分析过程的栈数据结构(包含压入和弹出操作),以及查找 LALR 分析表和进行语法分析动作。按照语法分析过程组织上述数据结构,完成语法分析

2023年4月21日 星期五

编译原理 40

YACC 的例子

存储输入的 token 序列需要的字符串数组数据结构—— rule.c中的函数 yylex 就实现了 token 序列生成和返回 token 的操作( 01850 )分析过程的中间状态需要栈数据结构。 Rule.c 中存储分析过程的中间状态的栈为 (01710)文法规则需要存储在表数据结构中,这个数据结构是 yytable ,其使用见 01870 行。

当状态值为正时,移进 token状态值为负时,采用正数对应的规则进行规约如果是 0 ,则依照 YYDEFACT 中定义的情况动作如果是 YYTABLE_NINF即 -169 为语法错误Yytable 的定义在 0999 行, yyreduce在 01913 行

2023年4月21日 星期五

编译原理 41

语法分析过程中的数据结构

语法树需要树数据结构来存储。 Tree.h 中定义的 _tree 结构体( 046 )

Op记录节点或者树的操作参见 ops.h 中的节点和树操作的枚举结构定义Result_tye记录节点的类型Kids[2]记录该节点或树的两个孩子节点或树U 为当前树节点的值部分

tree

op Resule_type u

2023年4月21日 星期五

编译原理 42

具体实现

A 程序Spl.y 中的 00226 开始。创建树为 00235 ,对应 rule.c为 01940

树节点的操作类型为 TAIL ,表示该树节点实现的是程序结束的操作。见 ops.h中 TAIL 类型的定义 0068

New_tree函数的实现在 tree.c中 0008

子程序 sub_program 的创建: 00285 树节点创建: 00306和00309 ,对应于 rule.c 中也有相应表示。HEADER 表示该树节点定义的为程序的开始; ROUTINE 表示该节点定义了程序主体部分并将程序头节点作为函数节点的左子树

2023年4月21日 星期五

编译原理 43

具体实现

B 子代码(子程序)函数声明 00718 ,树生成 00726

函数头 00744 ,树生成 00778和 00782

23/4/21 编译原理 44

Thanks for your time!Thanks for your time!

Questions & AnswersQuestions & Answers

top related