编译原理课件chapter_第1页
编译原理课件chapter_第2页
编译原理课件chapter_第3页
编译原理课件chapter_第4页
编译原理课件chapter_第5页
已阅读5页,还剩139页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第四章 语法分析南京大学计算机系2012年春季概要n 语法分析器n 上下文无关n 语法分析技术 自顶向下 自底向上n 语法分析器生成工具2程序设计语言构造的描述n 程序设计语言构造的语法可使用上下文无关或BNF表示法来描述可给出精确易懂的语则的语法分析器 可以自动构造出某些类型的指出了语言的结构,有助于进一步的语义处理/代码生成 支持语言的演化和迭代3语法分析器的作用基本作用从词法分析器获得词法单元的序列,确认该序列是否可以由语言的生成对于语法错误的程序,报告错误信息对于语法正确的程序,生成语法分析树通常并不真的生产这棵语法分析树4语法分析器的分类通用语法分析器可以对任意进行语法分析效率很低,

2、不适合用于编译器自顶向下语法分析器 (通常用于处理LL)从语法分析树的根部开始构造语法分析树自底向上语法分析器 (通常用于处理LR)从语法分析树的叶子开始构造语法分析树后两种方法总是从左到右、逐个扫描词法单元只能处理特定类型的述程序设计语言,但是这些足以用来描5上下文无关定义:一个上下文无关(CFG) 包含四个部分终结符号:组成串的基本符号 (词法单元名字)非终结符号:表示串的集合的语法变量给出了语言的层次结构在程序设计语言中通常对应于某个程序构造,比如stmt (语句)开始符号:某个被指定的非终结符号它对应的串的集合就是的语言产生式集合:描述将终结符号和非终结符号组成串的方法产生式的形式:头

3、 (左) 部 体 (右) 部头部是一个非终结符号,右部是一个符号串例子:expression expression + term6上下文无关的例子简单算术表的终结符号:id, +, , *, /, (, )非终结符号:expression, term, factor开始符号:expression 产生式集合expression expression + term expression expression term expression termterm term * factor term term / factor term factorfactor ( expression )facto

4、r id7书写的约定n 终结符号:a b + 3 id n 非终结符号: A B C S stmt 符号: X Y n符号串: nn 终结符号串: u v w n 开始符号: S8简单形式的例子E E + T | E T | TT T * F | T / F | F F ( E ) | idn 注意 | 是元符号 (即符号)描述中的符号,而不是 这里的 ( 和 ) 不是元符号9推导 (1)n 推导 将待处理的串中的某个非终结符号替换为这个非终结符号的某个产生式的体 从开始符号出发,不断进行上面的替换,就可以得到的不同句型n 例子:E E | E + E | E * E | ( E ) | id

5、 推导序列:E = E = ( E ) = ( id )10推导 (2)推导的正式定义如果A 是一个产生式,那么A = 最左 (右) 推导:() 中不包含非终结符号符号:经过零步或者多步推导出:对于任何串如果且 = ,那么经过一步或者多步推导出:等价于且不等于11句型/句子/语言句型 (Sentential form)如果S,那么就是S的句型可能既包含非终结符号,又包含终结符号,也可以是空串句子 (Sentence)的句子就是不包含非终结符号的句型语言G的语言就是G的句子的集合,记为L(G)w在L(G)中当且仅当w是G的句子,即Sw12语法分析树推导的图形表示形式根结点的标号时的开始符号每个叶

6、子结点的标号是非终结符号、终结符号或每个内部节点的标号是非终结符号每个内部结点表示某个产生式的一次应用内部结点的标号为产生式头,结点的子结点从左到右是产生式的体树的叶子组成的序列是根的符号的一个句型一棵语法分析树可对个推导序列,但每颗分析唯一的最左推导及唯一的最右推导相关联13语法分析树的例子:E E | E + E | E * E | ( E ) | idnn 句子: ( id + id )14从推导序列构造分析树n 假设有推导序列 A = a1 = a2 = = ann 算法 初始化:a1的分析树是标号为A的单个结点 假设已经构造出ai-1 = X1X2Xk的分析树,且ai-1到ai的推导

7、是将Xj替换为,那么在当前分析树中找出第j个非结点,向这个结点增加则增加一个标号为的子结点的子结点;如果 = ,15构造分析树的例子n 推导序列 E = E = ( E ) = ( E + E ) = ( id + E )= ( id + id )16二义性 (1)二义性 (Ambiguous):一个生成多棵语法分析树,这个例子可以为某个句子就是二义性的E = E + E = id + E = id + E * E = id + id * E= id + id * idE = E * E = E + E * E = id + E * E = id + id * E= id + id * id都

8、是最左推导17二义性 (2)程序设计语言的通常都应该是无二义性的否则就会导致一个程序有多种“正确”的解释E E | E + E | E * E | ( E ) | id 的句子a + b * c如但有些二义性的情况可以方便的设计或语法分析器但是需要消二义性规则来剔除不要的语法分析树比如:先乘除后加减18词法分析和语法分析的比较19阶段输入输出描述体系词法分析源程序符号串词法单元序列正则表语法分析词法单元序列语法树上下文无关(1)上下文无关和正则表上下文无关比正则表的能力更强描述所有的正则语言都可以使用但是一些用描述的语言不能用正则表描述证明首先S aSb | ab描述了语言anbn | n 0

9、,但是这个语言无法用DFA识别假设有DFA识别此语言L,且这个DFA有k个状态。那么在识别ak+1的输入串时,必然两次到达同一个状态。设自在第i个和第j个a时进入同一个状态,那么:因为DFA识别L,ajbj必然到达接受状态,因此aibj必然也到达接受状态。直观地讲:有穷自不能计数20(2)上下文无关和正则表证明 (续)其次证明:任何正则语言都可以表示为上下文无关文法的语言任何正则语言都必然有一个NFA;对于任意的NFA构造如下的上下文无关对NFA的每个状态i,创建非终结符号Ai如果有i在输入a上到达j的转换,增加产生式Ai aAj如果i在输入上到达j,那么增加产生式Ai Aj如果i是一个接受状

10、态,增加产生式Ai 如果i是开始状态,令Ai为所得的开始符号21NFA构造的例子b(a|b)*abbA0 aA0 | bA0 | aA1A1 bA2 A2 bA3 A3 考虑baabb的推导和接受过程可知:NFA接受一个句子的运行过程实际是推导出该句子的过程22及其生成的语言n 语言是由的开始符号出发,能够推导得到的所有句子的集合G:S a S | a | b,L(G) = ai(a|b), i = 0G:S a S b | ab,L(G) = anbn, n = 1G:S ( S ) S | ,L(G) = 所有具有对称括号对的串G所确定的语言Ln 如何验证 证明G生成的每个串都在L中 证明

11、L中的每个串都能被G生成23(1)设计能够描述程序设计语言的大部分语法n 但不是全部,比如:标识符的先后使用无法用上下文无关描述 因此语法分析器接受的语言是程序设计语言的超集;必须通过语义分析来剔除一些符合程序、但不合法的24(2)设计n 在进行高效的语法分析之前,需要对处理 消除二义性做以下的二义性:可以为一个句子生成多颗不同的分析树n 消除左递归中一个非终结符号A使得对某个串,左递归:推导 A一个nA,则称这个是左递归的 提取因子25二义性的消除 (1)一些二义性例子可以被改成等价的无二义性的stmtif expr then stmt| if expr then stmt else stm

12、t| otherif E1 then if E2then S1else S2的两棵语法树26二义性的消除 (2)为了保证“else和最近未匹配的then匹配”,我们要求在then分支的语句必须是匹配好的引入matched_stmt表示匹配好的语句,有如下 matched_stmt | open_stmt if expr then matched_stmt elsematched_stmt| otherstmtmatched_stmtopen_stmt if expr then stmt| if expr then matched_stmt else open_stmt二义性的消除方法没有规律可

13、循27左递归的消除n 左递归的定义 如果一个中有非终结符号A使得AA,那么这个就是左递归的n 立即左递归 (规则左递归)中一个形如A A的产生式n 自顶向下的语法分析技术不能处理左递归的情况,因此需要消除左递归;但是自底向上的技术可以 处理左递归28立即左递归的消除假设非终结符号A立即左递归的情形,假设以A为左部的规则有:A A1 | A2 | | Am | 1| 2 | | n可以替换为A 1A | 2A | | nAA 1A | 2A | | mA | 由A生成的串总是以某个i开头,然后跟上零个或者多个j的重复 A A 29A A | A AA A | AA立即左递归消除示例30消除多步左

14、递归n 消除立即左递归的方法并不能消除因为两步或多步推导而产生的左递归:S Aa | b,A Ac | Sd | S = Aa = Sdan 如何消除?31通用的左递归消除方法输入:没有环和产生式的输出:等价的无左递归的步骤G的非终结符号任意排序为A1, A2, , An将for i = 1 to n do for j = 1 to i1 do 将形如Ai Aj的产生式替换为Ai 1 | 2 | | k,其中Aj 1 | 2 | | k是以Aj为左部的所有产生式消除Ai的立即左递归32通用左递归消除的例子S Aa | bA Ac | Sd | 步骤1:排列为S, Ai = 1时:内层循环不运行

15、,S没有立即左递归i = 2时:j = 1,处理规则A Sd;替换得到A Ac | Aad | bd | 消除A的立即左递归本例子中的产生式恰好没有影响算法的正确性S Aa | bA bdA | AA cA | adA | 通用左递归消除的问题在于很难找到新和旧的推导之间的对应关系,因此很难依据新进行语义处理33分析法简介试图从开始符号推导出输入符号串以开始符号作为初始的当前句型每次为最左边的非终结符号选择适当的产生式通过查看下一个输入符号来选择这个产生式有多个可能的产生式时分析法为力:E + E E | E E | id;输入为+ id id id比如当两个产生式具有相同的前缀时无法:stm

16、t if expr then stmt else stmt | if expr then stmt输入:if a then 新:stmt if expr then stmt elsePartelsePart else stmt | 需要提取公因子34提取公因子的变换n 算法 输入:G 输出:等价的提取了因子的 方法:对于每个非终结符号A,找出它的两个或者多个可选产生式体之间的最长公共前缀n A 1 | 2 | | n | n A A | ,A 1 | 2 | | nn 其中是不以开头的产生式体35提取公因子的例子n S i E t S | i E t S e S | a E bn 对于S而言,

17、最长的前缀是i E t S,因此 S i E t S S | a S e S | E b36自顶向下的语法分析为输入串构造语法分析树从分析树的根结点开始,按照先根次序,深度优先地创建各个结点对应推导基本步骤确定对句型中最左边的非终结符号应用哪个产生式然后对句型中的非终结符号和输入符号进行匹配关键问题确定对最左边的非终结符号应用哪个产生式37自顶向下分析的例子E T EE + T E | T F TT * F T | F ( E ) | id输入id + id * id分析树序列见右38递归下降的语法分析递归下降语法分析一组过程组成每个非终结符号对应于一个过程,该过程负责扫描此非终结符号对应的结

18、构程序执行从开始符号对应的过程开始当扫描整个输入串时宣布分析完成39递归下降分析技术的回溯如果没有足够的信息来唯一地确定可能的产生式,那么分析过程就产生回溯前面的算法报告错误 (第7行) 并不意味着输入串不是句子,而可能是表示前面了产生式第1行上保存当前的扫描指针;在第7行上应该改成回退到保存的指针;GOTO 1) 并选择下一个产生式如果没有下一个产生式可选,报告错误回溯需要来回扫描,因而低效需要撤销已经完成的语义处理动作 (如果有)解决方法设法通过一些信息确定唯一可能的产生式40递归下降分析中回溯的例子:S cAd输入串:cad步骤A ab | a调用函数SS选择唯一产生式S cAd输入中的

19、c和句型中的c匹配,继续调用AA首先选择产生式A ab,a和输入的a匹配,b和输入的d不匹配回溯并选择下一个产生式A a;a和输入的a相匹配;对A的调用返回;到S的调用S cAd中的d和下一个输入d匹配对S的调用返回,已经读入所有输入符号因此扫描结束,cad是S的句子41FIRST和FOLLOW在自顶向下的分析技术中,通常使用向前看几个 符号来唯一地确定产生式 (通常只看一个符号)当前句型是xA,而输入是xa;那么选择产生 式A 的必要条件是下列之一a,且以a开头,即在某个句型中a跟在A之后如果按照这两个条件选择时能够保证唯一性,那么我们就可以避免回溯因此,我们定义FIRST和FOLLOW42

20、FIRSTn FIRST() 可以从推导得到的串的首符号的集合 如果,那么也在FIRST()中n FIRST函数的意义 如果两个A产生式 A | ,且FIRST()和FIRST() 不相交;下一个输入符号是a,若a FIRST(),则选择A ,若a FIRST(),则选择A 43FIRST的计算方法计算FIRST(X)的方法如果X是终结符号,那么FIRST(X) = X如果X是非终结符号,且X Y1Y2Yk是产生式如果a在FIRST(Yi)中,且在FIRST(Y1), FIRST(Y2), ,FIRST(Yi-1)中,那么a也在FIRST(X)中如果在FIRST(Y1), FIRST(Y2),

21、 , FIRST(Yk)中,那么在FIRST(X)中如果X是非终结符号且有X ,那么在FIRST(X)中计算FIRST(X1X2Xn)的方法向集合中加入FIRST(X1)中所有非的符号如果在FIRST(X1)中,再加入FIRST(X2)中的所有非 的符号;如果在所有FIRST(Xi)中,将加入FIRST(X1X2Xn)中44FOLLOWn FOLLOW(A) 可能在某些句型中紧跟在A右边的终结符号的集合 例如:S Aa,终结符号a FOLLOW(A)n FOLLOW函数的意义 如果A ,当 e或 = e时,FOLLOW(A)可以帮助我们选择恰当的产生式 例如:A ,而b属于FOLLOW(A),

22、如果 = e, 则若当前输入符号是b,可以选择A ,因为A最终到达了e,而且后面跟着b45FOLLOW的计算方法算法将右端结束标记$放到FOLLOW(S)中按照下面的两个规则不断迭代,直到所有的FOLLOW集合都不再增长为止产生式A B,那么FIRST()中所有非的符号都在如果FOLLOW(B)中一个产生式A B,或者A B且FIRST()包含,如果那么FOLLOW(A)中的所有符号都加入到FOLLOW(B)中请注意各个步骤中将符号加入到FOLLOW集合中的理由46FIRST/FOLLOW的例子 (1)n E TE T FTn FIRST集合E +TE | T *FT | F (E) | id

23、 FIRST(F) = (, id FIRST(T) = FIRST(F) = (, id FIRST(E) = FIRST(T) = (, id FIRST(E) = +, FIRST(T) = *, n 由此可以推出各个产生式右部的FIRST集合 FIRST(TE) = FIRST(T) = (, idFIRST(+TE) = +47FIRST/FOLLOW的例子 (2)FOLLOW集合的计算过程 $在FOLLOW(E)中(E是开始符号) 由规则F (E)可知,)也在FOLLOW(E)中 由规则E TE可知FOLLOW(E)也包含了$和) 由规则E +TE,FIRST(E)中的+在FOLL

24、OW(T)中;且FIRST(E) 包含,因此FOLLOW(E)中的$和)也在FOLLOW(T)中 因为T只出现在T和T的产生式的末尾,可以得到FOLLOW(T) = FOLLOW(T) 由规则T FT,FIRST(T)中的*在FOLLOW(F)中;且FIRST(T)包含,因此FOLLOW(T)中的+, $, )也在FOLLOW(F)中因此nn FOLLOW(E) = $, )FOLLOW(E) = $, ) FOLLOW(T) = FOLLOW(T) = +, $, ) FOLLOW(F) = *, +, $, )48LL(1)(1)的任意两个不同的产生式A | 定义:对终结符号a使得和都可以

25、推导出以a开头的串不和最多只有一个可以推导出空串如果可以推导出空串,那么不能推导出以FOLLOW(A)中任何终结符号开头的串等价于FIRST() FIRST() = (条件一、二)如果 FIRST(),那么FIRST() FOLLOW(A) = ; 反之亦然 (条件三)49LL(1)(2)对于LL(1),可以在自顶向下分析过程中,根据当前输入符号来确定使用的产生式产生式:stmt if (exp) stmt else stmt |while (exp) stmt | a输入:if (exp) while (exp) a else a首先选择产生式stmt if (exp) stmt else

26、stmt 得到句型if(exp) stmt else stmt然后发现要把句型中的第一个stmt展开,选择产生式stmt while (exp) stmt,得到句型if (exp) while (exp) stmt else stmt再展开下个stmt,得到if (exp) while (exp) a else stmt 50分析表构造算法G分析表Mn 输入:n 输出:n 方法 对于G的每个产生式A n 对于FIRST()中的每个终结符号a,将A 加入到MA, a中n 如果在FIRST(),那么对于FOLLOW(A)中的每个符号b,将A 加入到MA, b中 最后在所有的空白条目中填入error

27、51分析表的例子这个例子恰巧使得每个产生式的右部的第一个符号的FIRST集合 就等于产生式右部的FIRST集合; 但是在一般情况下不总是这样的E TE T FTF (E) | idE +TE | T *FT | FIRST集F:(, idE, T:(, idE:+, T:*, FOLLOW集E, E:$, )T, T:+, $, )F:*, +, $, )分析表的例子:S iEtSS | a;S eS | ;E bFIRST(eS) = e,使得S eS在MS, e中FOLLOW(S) = $, e使得S 也在MS, e中注意:LL(1)法是二义性的必然不是二义性的;而这个文53LL(1)的递

28、归下降分析递归下降语法分析一组过程组成每个非终结符号对应于一个过程,该过程负责扫描非终结符号对应的结构可以使用当前的输入符号来唯一地选择产生式如果当前输入符号为a,那么选择MA, a中的产生式54分析 (1)非递归的n 在自顶向下分析的过程中,我们总是 匹配掉句型中左边的所有终结符号 对 匹配边的非终结符号,选择适当的产生式展开的终结符号再被考虑,因此只需要记住句型的余下部分,以及尚未匹配的输入终结符号串 由于展开的动作总是发生在余下部分的以用栈来存放这些符号,我们可55分析 (2)非递归的n 分析时的处理过程 初始化时,栈中仅包含开始符号S (和$) 如果栈顶元素是终结符号,那么进行匹配 如

29、果栈顶元素是非终结符号n 使用分析表来选择适当的产生式n 在栈顶用产生式右部替换产生式左部n 对所有的分析都可以用同样的驱动程序56分析表驱动的分析器如果栈中的符号序列为,w是已经被读入的部分输入,w是尚未处理的输入;那么wS推导出w我们试图从推导出余下的输入终结符号串w分析程序使用awMX, a来扩展X,将此产生式的右部按倒序压入栈中57w分析算法输入:串w,分析表M输出:如果w是句子,输出w的最左推导;否则报错(1)(2)初始化:输入缓冲区中为w$,栈中为S$;ip指向w的第一个符号令X = 栈顶符号,ip指向输入符号aif (X = a) X出栈,ip向前移动 /* 和终结符号的匹配 *

30、/ else if (X是终结符号) error() /* 失配 */else if (MX, a是报错条目) error() /* 无适当的产生式 */ else if (MX, a = X Y1Y2Yk) 输出产生式X Y1Y2Yk弹出栈顶符号X;将Yk, Yk-1, , Y1压入栈中不断执行第二步,直到要么报错,要么栈中为空(3)58分析表驱动分析的例子输入:id + id * id59注意:已经匹配部分加上栈中符号必然是一个最左句型自底向上的语法分析n 为一个输入串构造语法分析树的过程n 从叶子 (输入串中的终结符号,将位于分析树的底端) 开始,向上到达根结点 在实际的语法分析过程中并

31、真的构造出相应的分析树,但是分析树概念可以方便理解n 重要的自底向上语法分析的通用框架 移入-归约 (shift-reduce)n 简单LR技术 (SLR)、LR技术 (LR)60分析过程示例61归约w“归约”为n 自底向上语法分析过程看开始符号S的过程n 归约步骤 一个与某产生式体相匹配的特定子串被替换为该产生式头部的非终结符号n 问题 何时归约 (归约哪些符号串) ? 归约到哪个非终结符号?62归约的例子id * id的归约过程id * id,F * id,T * id,T * F,T,E对于句型T * id,有两个子串和某产生式右部匹配T是E T的右部id是F id的右部为什么选择将id

32、归约为F,而不是将T归约为E?:T归约为E之后,E * id不再是句型问题:如何确定这一点?63句柄n 对输入从左到右扫描,并进行自底向上语法分析, 实际上可以反向构造出一个最右推导n 句柄 最右句型中和某个产生式体匹配的子串,对它的归约代表了该最右句型的最右推导的最后一步 正式定义:如果S是A 的一个句柄Aww,那么紧跟之后的n 在一个最右句型中,句柄右边只有终结符号n 如果是无二义性的,那么每个句型都有且只有一个句柄64句柄的例子n 输入:id * id65移入-归约分析技术使用一个栈来保存归约/扫描移入的符号栈中符号 (从底向上) 和待扫描的符号组成了一个最右句型开始时刻:栈中只包含$,

33、而输入为w$ 结束时刻:栈中$S,而输入$在分析过程中,不断地移入符号,并在识别到句柄时进行归约句柄被识别时总是出现在栈的顶部66主要分析动作n 移入:将下一个输入符号移动到栈顶n 归约:将句柄归约为相应的非终结符号 句柄总是在栈顶 具体操作时弹出句柄,压入被归约到的非终结符号n 接受:宣布分析过程完成n 报错:发现语法错误,调用错误恢复子程序67归约分析过程的例子68为什么句柄总是在栈顶?n 为什么每次归约得到的新句型的句柄仍在栈顶(不在栈的中间) ?n 考虑最右推导的两个连续步骤的两种情况 情况(1):A被替换为By,然后产生式体中的最右非终结符号B被替换为 (归约之后句柄为By) 情况(

34、2):A首先被展开,产生式体中只包含终结符号; 下一个最右非终结符号B位于y左侧移入-归约分析中的对于有些不能使用移入-归约分析的,不管用什么样的移入-归约分析器都会到达这样的格局即使知道了栈中所有内容、以及下面k个输入符号,人们仍然无法知道是否该进行归约 (移入-归约者不知道按照什么产生式进行归约 (归约-归约),或)例如:设栈中符号串是,接下来的k个符号是x,产生移入/归约的是y和y使得axy是最右句型且是句柄 (需归约),而axy也是最右句型,但是句柄还在右边 (需移入)70移入-归约的例子71归约-归约的例子n 输入为id ( id , id )时的格局 栈: id ( idn输入:,

35、 id ) 72LR语法分析技术LR(k)的语法分析概念L表示最左扫描,R表示反向构造出最右推导k表示最多向前看k个符号当k增大时,相应的语法分析器的规模急剧增大k = 2时,程序语言的语法分析器的规模通常非常庞大当k = 0, 1时,已经可以解决很多语法分析问题,因此具有实践意义因此,我们只考虑k 12w,那么我们说项A 12是可行前缀1的有效项97SLR的原理:可行前缀 (2)如果我们知道项A 12对1有效 当2不等于空,表示句柄尚未出现在栈中,应该移入 如果2等于空,表示句柄已出现在栈中,应该归约n如果某个时刻两个有效项要求执行不同的动n作,那么就应该设法解决实际上表示可行前缀可能是两个最右句型的前缀, 第一个包含了句柄,而另一个尚未包含句柄 也可能都认为包含句柄,但

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论