一文学明白编译系统--编译系统期末复习--从入门到入考场--考前抄ppt系列

    技术2022-07-15  53

    绪论

    什么是编译(将高级语言翻译成汇编语言或者机器语言的过程)

    编译系统的组成及各部分的主要任务

    词法分析

    主要任务是从左向右逐行扫描源程序的字符,识别出各个单词,确定单词的类型,将识别出的单词转换成统一的机内表示,也就是词法单元token形式

    token的结构为 < < <种别码,属性值 > > >

    单词类型种别种别码关键字if一词一码标识符变量名多词一码常量整型一型一码运算符算术一词一码界限符{}一词一码

    语法分析

    主要任务是从词法分析器输出的token序列中识别出各类短语,并构造语法分析树创建语法分析树,要结合文法构建 p o s i t i o n = i n i t i a l + r a t e ∗ 60 position = initial + rate * 60 position=initial+rate60

    语义分析

    两个主要任务是:收集标识符的属性信息,比如种属、类型、存储位置和长度等,这些信息被存放在符号表和一个字符串表中;进行语义检查,比如变量或过程未经声明就使用,或者重复声明,运算分量类型不匹配,操作符与操作数之间的类型不匹配

    中间代码生成

    常见的中间表示有三地址码和语法结构树,其中三地址码有类似于汇编语言的指令序列组成,每个指令最多有三个操作数,三地址指令可表示为四元式、三元式和间接三元式,其中四元式的第一个元素是操作符,第二三个元素是操作数,最后一个元素是运算结果

    目标代码生成:以源程序的中间表示形式作为输入,并把它映射到目标语言,一个重要的任务是为程序中使用的变量合理分配寄存器

    代码优化

    主要任务是对代码进行等价变换,从而产生空间和时间上的优化

    程序设计语言以及语法

    在计算机中如何表示语言及其文法?

    字母表 ∑ \sum 是一个又穷符号集合,符号可以包含字母、数字、标点符号等,字母表上的运算有:乘积 ∑ 1 ∑ 2 = { a b ∣ a ∈ ∑ 1 , b ∈ ∑ 2 } \sum_1\sum_2 = \{ab|a \in \sum_1,b \in \sum_2\} 12={aba1,b2},幂运算 ∑ 0 = { ε } \sum^0 = \{\varepsilon\} 0={ε},正闭包 ∑ + = ∑ ∪ ∑ 2 ∪ … \sum^+ = \sum \cup \sum^2 \cup \dots +=2,克林闭包 ∑ ∗ = ∑ 0 ∪ ∑ ∪ ∑ 2 ∪ … \sum^* = \sum^0 \cup \sum \cup \sum^2 \cup \dots =02克林闭包中的每一个元素都是一个串,使用模计算长度,空串是单位元, x = y z x = yz x=yz中, y y y x x x的前缀、同理 z z z为后缀文法的定义 G = ( V T , V N , P , S ) G=(V_T,V_N,P,S) G=(VT,VN,P,S) V T V_T VT是终结符集合, V N V_N VN是非终结符,有时也被称为语法变量,两个集合不相交,并且他们放在一起统称为文法符号集。 P P P是产生式集合,一般形式为 α → β \alpha \rightarrow \beta αβ,读作 α \alpha α定义为 β \beta β α ∈ ( V T ∪ V N ) + \alpha \in (V_T \cup V_N)^+ α(VTVN)+,并且 α \alpha α中至少包含一个非终结符, α \alpha α被称为产生式的头或者左部, β ∈ ( V T ∪ V N ) ∗ \beta \in (V_T \cup V_N)^* β(VTVN) β \beta β称为产生式的体或者右部。 S S S是开始符号。关于符号的使用 终结符:字母表中排在前面的小写字母,运算符,标点符号,数字,粗体字符串非终结符:字母表中排在前面的大写字母, S S S 通常是开始符号,小写且斜体的名字, E , T , F E,T,F E,T,F文法符号:字母表中排在后面的大写字母终结符号串(包含空串):字母表中排在后面的小写字母文法符号串(包含空串):小写希腊字母 语言的定义: L ( G ) = { w ∣ S ⇒ ∗ w , w ∈ V T ∗ } L(G)= \{w|S\Rightarrow^*w,w\in {V_T}^*\} L(G)={wSw,wVT}推导是指用产生式的右部替换产生式的左部,与之相反的过程被称为归约,对于一个词串,如果从开始符号可以推导出该词串或者从该词串可以归约出开始符号,则可以判定它是不是某个语言的句子如果 S ⇒ ∗ α , α ∈ ( V T ∪ V N ) ∗ S \Rightarrow ^* \alpha, \alpha \in (V_T \cup V_N)^* Sα,α(VTVN),则称 α \alpha α G G G的一个句型,一个句型中既可以包含终结符,也可以包含非终结符,也可能是空串;如果 S ⇒ ∗ w , w ∈ V T ∗ S \Rightarrow ^* w, w \in {V_T}^* Sw,wVT,则称 w w w G G G的一个句子。因此,句子是只包含终结符的句型。举个例子:标识符的文法是啥?

    乔姆斯基文法分类

    0型文法,也称为无限制文法或者短语结构文法, ∀ α → β ∈ P , α \forall \alpha \rightarrow \beta \in P, \alpha αβP,α 中至少包含一个非终结符1型文法,也称为上下文有关文法, ∀ α → β ∈ P , ∣ α ∣ ≤ ∣ β ∣ \forall \alpha \rightarrow \beta \in P, |\alpha| \leq |\beta| αβP,αβ,产生式的一般形式为: α 1 A α 2 → α 1 β α 2 ( β ≠ ε ) \alpha_1A\alpha_2 \rightarrow \alpha_1\beta\alpha_2(\beta\neq\varepsilon) α1Aα2α1βα2(β=ε),因此上下文有关文法中不包含空产生式2型文法,上下文无关文法, ∀ α → β ∈ P , α ∈ V N \forall \alpha \rightarrow \beta \in P, \alpha \in V_N αβP,αVN,产生式的一般形式: A → β A\rightarrow \beta Aβ3型文法,正则文法,分为左右线性文法两种: A → w B , A → w A\rightarrow wB, A\rightarrow w AwB,Aw或者 A → B w , A → w A\rightarrow Bw, A\rightarrow w ABw,Aw,产生式的右部最多只有一个非终结符四种文法逐级限制,其包含关系为 t y p e 0 ⊃ t y p e 1 ⊃ t y p e 2 ⊃ t y p e 3 type_0\supset type_1\supset type_2\supset type_3 type0type1type2type3

    其他概念

    上下文无关文法可以描述大部分程序设计语言中的句子构造,CFG分析树的根结点对应着文法开始符号,内部结点表示对一个产生式的应用,该结点的标号是此产生式的左部,叶节点从做到右构成了产生的右部给定一个句型,其分析树中的每一棵子树的边缘称为该句型的一个短语,如果子树只有父子两代结点,那么这棵子树的边缘称为直接短语如果一个文法可以为某个句子生成多棵分析树,则称这个文法是二义性的 例子:给定文法, S → i f   E   e l s e   S   ∣   i f   E   t h e n   S   e l s e   S ∣   o t h e r S \rightarrow if\ E\ else\ S\ |\ if\ E\ then\ S\ else\ S|\ other Sif E else S  if E then S else S other,则 i f   E 1   t h e n   i f   E 2   t h e n   S 1   e l s e   S 2 if\ E_1\ then\ if\ E_2\ then\ S_1\ else\ S_2 if E1 then if E2 then S1 else S2是具有二义性的, i f   E 1   t h e n   ( i f   E 2   t h e n   S 1 )   e l s e   S 2 if\ E_1\ then\ (if\ E_2\ then\ S_1)\ else\ S_2 if E1 then (if E2 then S1) else S2 i f   E 1   t h e n   ( i f   E 2   t h e n   S 1   e l s e   S 2 ) if\ E_1\ then\ (if\ E_2\ then\ S_1\ else\ S_2) if E1 then (if E2 then S1 else S2)就是两种不同的理解方式消除上述例子中的歧义的方法是: e l s e else else只和最近的 i f if if进行匹配二义性的不可判定性:只能给出一组充分条件,满足就是无二义性的,否则不可判定

    词法分析

    基础知识(略)

    正则表达式的文字定义,以及形式化定义

    正则定义

    DFA以及DFA的分类(确定性和非确定性)

    从RE到DFA,从NFA到DFA

    词法分析

    识别单词的、无符号数、注释、token的DFA 单词 无符号数,然后通过子集构造法将NFA转换成DFA 注释 token 词法分析阶段可以检测到的错误包含:单词拼写错误,非法字符。如果当前状态与当前输入符号在转换表对应项中的信息为空则报错,也就是在当前状态不应该读入这样的符号。错误处理:查找已扫描字符串中最后一个对应于某终态的字符,如果找到了,就将该字符与其前面的字符识别成一个单词,然后输入指针退回到该字符,扫描器重新回到初始状态,继续;如果没有找到,则采取恐慌模式进行错误恢复,从剩余的输入中不断地删除字符,直到词法分析器能读到一个合法输入开始。

    语法分析

    basic

    语法分析的基本任务是从词法分析器的输出的token序列中识别各类短语,并构造语法分析树

    在最左推导中,总是选择每个句型的最左非终结符进行替换,最右推导和最左推导对应,最左推导和最右推导具有唯一性;规约是推导的反过程;最左推导得到的句型是最左句型;最左规约是规范规约,最右推导是规范推导

    topdown-basic

    计算机实现自顶向下语法分析的方法叫递归下降分析,由一组过程组成,每个过程对应一个非终结符

    在递归下降分析的过程中,递归调用时如果有多个候选式,做这个决定的过程称为预测分析。通过在输入中向前看固定个数符号来选择正确的产生式,这种方法不需要回溯。对应的文法称为 L L ( k ) LL(k) LL(k)文法

    topdown-advance

    直接应用最左推导会出现一些问题

    同一非终结符的多个候选式存在共同前缀,将导致回溯现象,可以提取公共前缀来解决这个问题左递归文法会使递归下降分析陷入无限循环(左递归的、直接左递归、间接左递归)

    消除直接左递归的一般形式, A → A α 1 ∣ A α 2 ∣ … ∣ A α n ∣ β 1 ∣ β 2 ∣ … ∣ β m ( α i ≠ ε , β j A\rightarrow A\alpha_1|A\alpha_2|\dots|A\alpha_n|\beta_1|\beta_2|\dots|\beta_m(\alpha_i \neq \varepsilon,\beta_j AAα1Aα2Aαnβ1β2βm(αi=ε,βj不以 A A A开头 ) ) )转换成 A → β 1 A ′ ∣ β 2 A ′ ∣ … ∣ β m A ′ , A ′ → α 1 A ′ ∣ α 2 A ′ ∣ … ∣ α n A ′ ∣ ε A\rightarrow \beta_1A'|\beta_2A'|\dots|\beta_mA', A' \rightarrow \alpha_1A'|\alpha_2A'|\dots|\alpha_nA'|\varepsilon Aβ1Aβ2AβmA,Aα1Aα2AαnAε

    消除间接左递归时,先通过非终结符之间的代入,将文法转换成直接左递归的,再借用上面的方法即可

    预测分析法要求提出的候选式必须是唯一的,基于此提出简单的确定性文法S_文法,它的两个条件是:每个产生式的右部都以终结符开始,同一非终结符的各个候选式的首终结符都不同。这就要求右部不包含空产生式

    后继符号集指的是可能在某个句型中紧跟在 A A A后边的终结符 a a a的集合,记为 F O L L O W ( A ) = { a ∣ S ⇒ ∗ α A a β , a ∈ V T , α , β ∈ ( V T ∪ V N ) ∗ } FOLLOW(A) = \{a|S\Rightarrow^*\alpha Aa\beta, a \in V_T,\alpha,\beta\in (V_T\cup V_N)^*\} FOLLOW(A)={aSαAaβ,aVT,α,β(VTVN)},同时如果 A A A是某个句型的最右符号,则将结束符$$ 添 加 到 后 继 符 号 集 合 中 ; 产 生 式 的 可 选 集 是 指 可 以 选 用 该 产 生 式 进 行 推 导 时 对 应 的 输 入 符 号 的 集 合 , 记 为 添加到后继符号集合中;产生式的可选集是指可以选用该产生式进行推导时对应的输入符号的集合,记为 SELECT(A\rightarrow \beta)$

    q _ q\_ q_文法的约束条件有两条:每个产生式的右部或为 ε \varepsilon ε或以终结符开始,具有相同左部的产生式有不相交的可选集。该文法不允许产生式的右部以终结符开头,为了引入更加强大的 L L ( 1 ) LL(1) LL(1)文法以及相应后继符号集的计算,需要引入串首终结符集

    F I R S T ( α ) FIRST(\alpha) FIRST(α)被定义为可以从 α \alpha α推导出的所有串首终结符构成的集合,如果可以推导出空串,则 ε \varepsilon ε也属于 F I R S T ( α ) FIRST(\alpha) FIRST(α)如果 ε ∉ F I R S T ( α ) \varepsilon \notin FIRST(\alpha) ε/FIRST(α),那么 S E L E C T ( A → α ) = F I R S T ( α ) SELECT(A\rightarrow\alpha)=FIRST(\alpha) SELECT(Aα)=FIRST(α),否则 S E L E C T ( A → α ) = ( F I R S T ( α ) − { ε } ) ∪ F O L L O W ( A ) SELECT(A\rightarrow\alpha)=(FIRST(\alpha) - \{\varepsilon\})\cup FOLLOW(A) SELECT(Aα)=(FIRST(α){ε})FOLLOW(A)

    L L ( 1 ) LL(1) LL(1)文法的定义:文法的任意两个具有相同左部的产生式 A → α ∣ β A\rightarrow \alpha|\beta Aαβ满足下面的条件(这三个条件都是为了保证各个产生式的可选集互不相交):

    不存在终结符 a a a使得 α \alpha α β \beta β都能够推导出以 a a a开头的串 α \alpha α β \beta β至多有一个能推导出 ε \varepsilon ε如果 β ⇒ ∗ ε \beta\Rightarrow^*\varepsilon βε,则 F I R S T ( α ) ∩ F O L L O W ( A ) = ∅ FIRST(\alpha)\cap FOLLOW(A)=\varnothing FIRST(α)FOLLOW(A)=,如果 α ⇒ ∗ ε \alpha\Rightarrow^*\varepsilon αε,则 F I R S T ( β ) ∩ F O L L O W ( A ) = ∅ FIRST(\beta)\cap FOLLOW(A)=\varnothing FIRST(β)FOLLOW(A)=

    topdown-ending

    递归的预测分析法是指:在递归下降分析中,编写每一个而覅终结符对应的过程时,根据预测分析表进行产生式的选择非递归的预测分析不需要为每一个非终结符编写递归下降过程,而是根据预测分析表构造一个自动机,也叫表驱动的预测分析表驱动的预测分析法的例子

    递归的方法和非递归的方法进行对比

    预测分析法的实现步骤构造文法 改造文法(消除二义性、左递归、回溯)求每个变量的 F I R S T , F O L L O W FIRST,FOLLOW FIRST,FOLLOW集,从而求得每个候选式的 S E L E C T SELECT SELECT集检查是不是 L L ( 1 ) LL(1) LL(1)文法,如果是则构造预测分析表按照递归的和非递归的分别进行相应的依赖于预测分析表的预测分析算法 预测分析的错误检测,两种情况可以检测到错误:栈顶的终结符和当前输入符号不匹配,栈顶非终结符与当前输入符号在预测分析表对应项中的信息为空。采用恐慌模式进行错误恢复:忽略输入中的一些符号,直到输入中出现同步词法单元,如果终结符在栈顶而不能匹配,一个简单的办法就是弹出此终结符。同步词法单元为根据相应的非终结符的 F O L L O W FOLLOW FOLLOW集得到的。加入了同步词法单元的预测分析表的使用方法为:如果 M [ A , a ] M[A,a] M[A,a]是空,表示检测到错误,根据恐慌模式,忽略输入符号 a a a;如果同步词法单元,则弹出栈顶的非终结符;如果栈顶的终结符和输入符号不匹配,则弹出栈顶终结符

    bottom-up

    自底向上的语法分析可以看成是将输入串 w w w规约为文法开始符号 S S S的过程,采用最左规约的方式,一个通用的框架为移入-规约分析

    移入规约

    移入规约的分析举例,其中每次规约的符号串称为句柄,句柄是句型的最左直接短语,栈内符号串加上剩余输入得到的是规范句型(最左句型)

    工作过程:在对输入串的一词从左到右扫过程中,语法分析器将零个或多个输入符号移入到栈的顶端,直到它可以对栈顶的一个文法符号串 β \beta β进行规约为止,同时进行规约;语法分析器不断地重复这个循环,直到它检测到一个语法错误,或者栈中包含了开始符号且输入缓冲区为空(成功)为止。因此基本的动作有四个:移入、规约、接受、报错

    移入规约分析中存在的问题:栈中有多个可识别的句柄(直接短语一定是某个产生式的右部,但是产生式的右部不一定是直接短语)

    LR分析(L表示从左向右推导,R表示反向构造出一个最右推导序列)

    基本原理是如何正确的识别句柄,总体结构如图所示,其中分析表在不同类型的分析技术中有所不同

    LR(0)分析

    LR(0)项目是右部某位置标有圆点的产生式,例如 A → α 1 ⋅ α 2 A\rightarrow\alpha_1\cdot\alpha_2 Aα1α2增广文法:如果 G G G是一个以 S S S为开始符号的文法,则 G G G的增广文法 G ′ G' G就是在 G G G中加上新开始符号 S ′ S' S和产生式 S ′ → S S'\rightarrow S SS而得到的文法。引入这个欣的开始产生式的目的是使得文法开始符号仅出现在一个产生式的左边,从而使得分析器只有一个接受状态等价项目判断举例,图中相同颜色为等价,可以把所有等价的项目组成一个项目集,称为项目集闭包,每个项目集闭包对应着自动机的一个状态,该闭包意味着到此状态之前为一致,之后未必LR(0)自动机在构造时,将初始状态利用等价项目写出来,后面根据输入符号和后继项目确定剩余的状态。在构造算法中,需要计算几个函数 C L O S U R E CLOSURE CLOSURE函数计算给定项目集的闭包 C L O S U R E ( I ) = I ∪ { B → ⋅ γ ∣ A → α ⋅ B β ∈ C L O S U R E ( I ) , B → γ ∈ P } CLOSURE(I)=I\cup\{B\rightarrow\cdot\gamma|A\rightarrow\alpha\cdot B\beta\in CLOSURE(I),B\rightarrow\gamma\in P\} CLOSURE(I)=I{BγAαBβCLOSURE(I),BγP} G O T O GOTO GOTO函数计算项目集 I I I对应于文法符号 X X X的后继项目集闭包 G O T O ( I , X ) = C L O S U R E ( { A → α X ⋅ β ∣ A → α ⋅ X β ∈ I } ) GOTO(I,X)=CLOSURE(\{A\rightarrow\alpha X\cdot\beta|A\rightarrow\alpha\cdot X\beta\in I\}) GOTO(I,X)=CLOSURE({AαXβAαXβI})规范 L R ( 0 ) LR(0) LR(0)项目集族 C = { I 0 } ∪ { I ∣ ∃ J ∈ C , X ∈ V N ∪ V T , I = G O T O ( J , X ) } C=\{I_0\}\cup\{I|\exists J\in C,X\in V_N \cup V_T,I = GOTO(J,X)\} C={I0}{IJC,XVNVT,I=GOTO(J,X)}最终的构造算法如图所示,非规约项目就是移入,规约项目就是规约自动机的形式化定义就是 CFG不总是LR(0)文法,构造LR(0)自动机时总是会产生冲突 移进规约冲突 规约规约冲突

    SLR分析

    SLR分析的思想是 F O L L O W FOLLOW FOLLOW集可以帮助我们判定哪些情况下不可以进行规约SLR分析中的冲突,如果 R R R F O L L O W FOLLOW FOLLOW集中包含 = = =,则会产生如下所示移进规约冲突

    LR(1)分析

    LR(1)分析法的核心:在特定位置,某非终结符的后继符号集合是 F O L L O W FOLLOW FOLLOW的子集规范LR(1)项目:一般形式为 [ A → α ⋅ β , a ] [A\rightarrow\alpha\cdot\beta,a] [Aαβ,a]的项称为 L R ( 1 ) LR(1) LR(1)项,其中 a a a是一个终结符,称为该项的展望符,它表示在当天状态下, A A A后面必须紧跟 a a a。同时,在一个形如 [ A → α ⋅ β , a ] , β ≠ ε [A\rightarrow\alpha\cdot\beta,a],\beta\neq \varepsilon [Aαβ,a],β=ε的项中,展望符 a a a没有任何作用等价LR(1)项目: [ A → α ⋅ B β , a ] [A\rightarrow\alpha\cdot B\beta,a] [AαBβ,a],一个与之等价的项目是 [ B → ⋅ γ , b ] , b ∈ F I R S T ( β a ) [B\rightarrow\cdot\gamma,b],b\in FIRST(\beta a) [Bγ,b],bFIRST(βa),利用这个可以确定展望符LR(1)自动机的构造方法,几个函数都要进行一定的修改,主要是要加上展望符,分析表的构造算法

    LALR分析

    LALR分析方法的基本思想(合并同心项集:项目的第一个分量相同)合并同心项集时有可能产生规约规约冲突,但是不会产生移进规约冲突合并同心项集即使不产生冲突,但是可能会推迟错误的发现总结一下LALR分析方法的特点

    ending

    二义性文法的LR分析举例:略LR分析错误处理:根据分析表判断,错误恢复策略有两种 恐慌模式,先找状态,再找符号短语层次,给不同的错误设定相应的处理例程

    语法制导翻译

    basic

    语义分析的结果通常表示为中间代码的形式,因此语义分析和中间代码生成放在一起叫做语义翻译;我们还可以在语义翻译的同时进行语法分析,这一技术叫语法制导翻译

    语法制导翻译的基本思想

    如何表示语义信息:为CFG中的文法符号设置语义属性,用来表示语法成分对应的语义信息语义属性如何计算:用与文法符号所在产生式相关联的语义规则来计算将语义规则和语法规则联系起来要涉及两个概念:语法制导定义SDD、语法制导翻译方案SDT

    语法制导定义SDD

    语法制导定义是对CFG的推广,将每个文法符号和一个语义属性集合相关联,将每个产生式和一组语义规则相关联,这些规则用于计算该产生式中各文法符号的属性值文法符号的属性(每个节点都带有属性值的分析树称为注释分析树) 综合属性:在分析树节点 N N N上的非终结符 A A A的综合属性只能通过 N N N的子节点或其本身的属性值来定义;终结符也可以具有综合属性,并且是由词法分析器提供的词法值,因此在SDD中没有计算终结符语义属性值的语义规则继承属性:在分析树节点 N N N上的非终结符 A A A的综合属性只能通过 N N N的父节点、兄弟节点或其本身的属性值来定义;终结符没有继承属性,从词法分析器获得的属性值被归为综合属性值 属性文法:一个没有副作用的SDD,属性文法的规则仅仅通过其它属性值和常量来定义一个属性值SDD的属性求值顺序:语义规则建立了属性之间的依赖关系,在对语法分析树节点的一个属性求值之前,必须首先求出这个属性值所依赖的所有属性值,这个依赖可以通过依赖图表示,在依赖图中,如果属性 X . a X.a X.a的值依赖于属性 Y . b Y.b Y.b的值,则依赖图中有一条从 Y . b Y.b Y.b的节点指向 X . a X.a X.a的节点的有向边 对于只具有综合属性的SDD,可以按照任何自底向上的顺序计算它们的值对于同时具有继承属性和综合属性的SDD,不能保证存在一个顺序来对各个节点的属性求值

    S-SDD是仅仅使用综合属性的SDD,可以按照任何自底向上的顺序来计算它的各个属性值,可以在自底向上的语法分析过程中实现

    L-SDD是在一个产生式所关联的各个属性之间,依赖图的边可以从左到右,单不能从右到左

    语法制导翻译方案SDT

    语法制导翻译方案是在产生式右部嵌入了程序片段的CFG,这些程序片段称为语义动作,一个语义动作在产生式中的位置决定了这个动作的执行时间

    本节主要关注如何使用SDT来实现两类重要的SDD,因为在这两种情况下,SDT可在语法分析过程中实现

    基本文法可以使用LR分析技术,且SDD是S属性的

    将S-SDD转换为SDT:将每个语义动作都放在产生式的最后,也就是规约发生时执行相应的语义动作

    基本文法可以使用LL分析技术,且SDD是L属性的,可以通过LL或者LR语法分析实现,因此总共有三种实现

    将L-SDD转换为SDT:将计算某个非终结符 A A A的继承属性的动作插入到产生式右部中紧靠在 A A A的本次出现之前的位置上,将计算一个产生式左部符号基本文法可以使用LR分析技术,且SDD是S属性的的综合属性的动作放置在这个产生式的最右端

    在非递归的预测分析过程中进行翻译(略,题目

    在递归的预测分析过程中进行翻译(略,题目

    L-属性定义的自底向上翻译(略,题目

    中间代码生成

    各类语句的翻译

    声明语句的翻译

    主要任务是收集标识符的类型等属性信息,并为每一个名字分配一个相对地址类型表达式:基本类型;为类型表达式命名的类型名也是类型表达式;将类型构造符号作用于类型表达式可以构成的新的类型表达式,比如 i n t [ 3 ]   a s   a r r a y ( 3 , i n t ) int[3]\ as\ array(3,int) int[3] as array(3,int),举个例子如下:存储分配:从类型表达式可以知道该类型在运行时所需的存储单元数量,称为类型的宽度;在编译时刻,可以使用类型的宽度为每一个名字分配一个相对地址。ps:名字的类型和相对地址信息保存在相应的符号表记录中 e n t e r ( n a m e , t y p e , o f f s e t ) enter(name,type,offset) enter(name,type,offset)动作,在符号表中为名字 n a m e name name创建记录,将 n a m e name named的类型设置为 t y p e type type,相对地址设置为 o f f s e t offset offset翻译时,每个非终结符添加两个综合属性:类型和偏移量,举例

    赋值语句

    主要任务是生成对表达式求值的三地址码action中有新增的函数 l o o k u p ( n a m e ) lookup(name) lookup(name):查询符号表返回 n a m e name name对应的记录 g e n ( c o d e ) gen(code) gen(code):生成三地址指令 c o d e code code,在增量方法中, g e n ( ) gen() gen()不仅要构造出一个新的三地址指令,还要将它添加到至今为止已生成的指令序列之后 n e w t e m p ( ) newtemp() newtemp():生成一个新的临时变量 t t t,返回 t t t的地址 带有数组引用的赋值翻译 翻译成三地址码时要解决的主要问题是确定数组元素的存放地址,也就是数组元素的寻址

    控制语句

    控制流语句的代码结构为 S → i f   B   t h e n   S 1   e l s e   S 2 S\rightarrow if\ B\ then\ S_1\ else\ S_2 Sif B then S1 else S2

    新增属性 S . n e x t S.next S.next是一个地址,指向该控制流结束之后要执行的位置, B . t r u e , B . f a l s e B.true,B.false B.true,B.false分别指向了判断条件为真或假时控制流的跳转位置

    新增action函数

    n e w l a b e l ( ) newlabel() newlabel():生成一个用于存放标号的新的临时变量 L L L,返回变量地址 l a b e l ( L ) label(L) label(L):将下一条三地址指令的标号(注意不是地址)赋给 L L L

    if-then-else

    if-then

    while-do

    逻辑运算符被翻译成跳转指令,运算符本身不出现在代码中,布尔表达式的值是通过代码序列中的位置来表示的

    或逻辑的SDT

    回填

    在为控制流语句和布尔表达式生成中间代码时,关键的问题是确定跳转指令的目标标号布尔表达式控制流语句

    switch语句

    过程调用语句

    运行存储分配

    概述

    编译器在工作过程中,必须为源程序中出现的一些数据对象分配运行时的存储空间,依据是否可以在编译时刻确定存储空间大小分为静态存储分配和动态存储分配,动态又包含栈式和堆式两种运行时内存的划分,其中栈中存储活动记录 活动记录:使用过程作为用户自定义动作的单元的语言,其编译器通常以过程为单位分配存储空间。过程体的每次执行称为该过程的一个活动,过程每执行一次,就为它分配一块连续存储区,用来管理过程一次执行所需的信息,这块连续存储区称为活动记录,其一般形式如图

    静态存储分配

    静态存储分配需要满足的限制条件常用的静态存储分配方法 顺序分配法层次分配法

    栈式存储分配是怎样的?

    活动树用来描述程序运行期间控制进入和离开各个活动的情况的树,树中的每个节点对应于一个活动,根节点是启动程序执行的main过程的活动

    调用序列和返回序列

    调用序列返回序列

    变长数据的存储分配

    如何进行非局部数据的访问

    访问链的建立

    符号表:为每个作用域建立一个独立的符号表,一个过程的非局部名字的信息可以通过扫描外围过程的符号表而得到。一个例子如图所示

    代码优化

    优化的分类 机器无关优化(针对中间代码)和机器相关优化(针对目标代码)局部代码优化(单个基本块内的优化)和全局代码优化(面向多个基本块的优化) 流图是用来描述程序控制流程的工具 基本块是满足下列条件的最大的连续三地址指令序列 控制流只能从基本跨的第一个指令进入该块,也就是说,没有跳转到基本块中间或末尾的指令除了基本块的最后一个指令,控制流在离开基本块之前不会跳转或者停机 基本块划分算法 首先确定哪些指令是首指令 指令序列的第一个三地址指令任意一个条件或无条件转移指令的目标指令紧跟在一个条件或无条件转移指令之后的指令 然后,每个首指令对应的基本块包括了从它自己开始,直到下一个首指令(不含)或者指令序列结尾之间的所有指令 流图的节点是基本块,如果两个块有可能有连接关系,就加一条边 常用的代码优化方法 删除公共子表达式删除无用代码常量合并代码移动强度削弱:用较快的操作代替较慢的操作删除归纳变量 基本块的优化 基于DAG的删除 数据流分析 数据流分析模式,这里讲的是语句流到达定值分析,定值和到达定值如下所示活跃变量分析 活跃变量主要用途 删除无用变量为基本块分配寄存器 可用表达式分析

    代码生成

    ~~~未完待续~

    Processed: 0.015, SQL: 9