编译程序:源语言是高级语言,目标语言是诸如汇编语言或机器语言之类的低级语言的翻译程序。(系统软件)
高级语言运行一般分为两大阶段,编译阶段和运行阶段。
如果编译阶段生成的是汇编语言程序,则新增汇编阶段。
解释程序:将源程序作为输入并执行,边解释边执行。
与编译程序主要区别是在解释程序的执行过程中不产生目标代码。
词法分析:根据词法规则从字符串中识别单词符号 有限自动机
语法分析:根据语法规则从单词符号串中识别语法单位并进行语法检查 上下文无关文法
语义分析和中间代码生成:静态的语义审查,然后分析其含义,根据语义规则用另一种语言来描述这种语义 属性文法 中间代码:三元式、四元式、树
代码优化:对前阶段生成的中间代码进行等价变换或改造,更高效。包括局部优化、循环优化。 程序的等价变换规则
目标代码生成:将中间代码变换成特定机器上的绝对指令代码或可重定位的指令代码或汇编指令代码。
上述各个阶段都涉及表格管理和出错处理。
表格管理:是记录源程序中所使用的变量的名字,并且收集与名字属性相关的各种信息。名字属性包括一个名字的存储分配、类型、作用域等信息。如果名字是一个函数名,还会包括其参数数量、类型、参数的传递方式以及返回类型等信息。
符号表数据结构可以为变量名字创建记录条目,来登记源程序中所提供的或在编译过程中所产生的这些信息,编译程序在工作过程的各个阶段需要构造、查找、修改或存取有关表格中
的信息
下图只是逻辑关系,不一定是执行时间上的先后关系。因为整个程序可以执行多遍,每遍仅仅执行部分内容。
多遍扫描:少占空间,各遍所要完成的功能独立而单纯,编译程序逻辑结构清晰,但降低编译效率。主存可能的前提下,遍数少一点为好
1 分析源语言
2 设计编译算法:关键一步,期望易读性、易改性、易扩充
3 选择语言编制程序:早期机器语言、汇编,效率高可靠性差不便于阅读、修改、移植;目前高级语言开发效率高,增加易读性、易改性、可移植性。
4 调试编译程序
5 提交相关文档资料
词法分析程序自动生成:Lex,flex
语法分析程序自动生成:yacc,bison
整个编译程序自动生成:填写词法规则、语法规则、语义解释
自编译:先用目标机的汇编语言或机器语言对源语言的核心部分构造一个小小的编译程序再以它为工具构造一个能够编译更多语言成分的较大编译程序。
移植:是把某机器上已有的编译程序移植到另一台机器上去。
交叉编译技术:指一个源语言在宿主机(运行编译程序的计算机)上经过编译产生目标机的机器语言或汇编语言代码。
并行编译技术:处理并行语言
自动并行编译技术:将串行程序转换成并行程序
(下面可能有错,个人理解)
高级语言书写:直接书写,或已知L1语言去表示L2语言,先用L1完成L2的代码,再编译表示后的代码,已知L2语言和最终生成的目标代码推出L2的编译程序
移植方法:p2上的L语言编译程序先形成A上可执行的代码,再在A上用可执行代码对同一编译程序生成B上的可执行的编译代码。
设计词法分析器的串匹配技术:正文编辑器、信息检索系统、模式识别程序。
上下文无关文法和语法制导定义:创建诸如排版、绘图和语言结构化编辑器
代码优化技术:程序验证器和从非结构化的程序产生结构化程序的编程
日常软件开发:需要将某种语言开发的程序转换成另一种语言程序,这种转换过程和编译程序的工作过程是类似的,需要对被转换的语言进行词法分析和语法分析,只不过生成的目标语言不一定是可执行的机器语言或汇编语言
对程序设计语言的描述是从语法、语义和语用3个因素来考虑的。
e.g. 对于赋值语句 s=2*3.1416*r*(r+h)的非形式化的描述如下
语法:对语言结构的定义,如赋值语句由一个变量、一个赋值符号’=',一个表达式组成。
语义:描述了语言的含义,如首先计算右部表达式的值,然后所得结果送入左部表达式中。
语用:从使用的角度去描述语言,如赋值语句可用来计算和保存表达式的值。
字母表:元素的非空有穷集合,字母表至少包含一个元素
符号:字母表中的元素称为符号或字符
符号串:符号的有穷序列称为符号串,符号串建立在字母表上,且有穷。空符号串ε长度为0
符号串的连接:类似字符串连接
符号串集合的乘积:不同集合间每个元素两两连接。
符号串的幂运算:自身连接的,0次为ε
符号串集合的幂运算:集合自身乘积,0次为{ε}
形式语言:序列的集合,具体来说,每个形式语言都是某个字母表上按某种规则构成的所有符号的集合,反之,任何一个字母表上符号串的集合均可定义为一个形式语言。
有穷描述:枚举法
无穷描述:文法
规则:一组规则规定了一个语言的语法结构
非终结符号:出现在规则左部能派生出符号或符号串的符号,每个非终结符表示一定符号串的集合。大写字母表示
终结符号:不属于非终结符,组成语言的基本符号,小写表示。
直接推导:有相应产生式存在
推导:一次或多次直接推导组成
广义推导:0次或多次直接推导
句型和句子:
语言:当文法给定,语言就确定;L(G)是VT闭包的子集,L(G)是根据规则规定的语法结构形成的。
总结:文法可以唯一确定语言;语言能确定一类文法,不能确定唯一一种文法
最左最右推导:规范推导是最右推导,推导出的句型为规范句型;规范推导的逆过程为最左规约
递归规则:所有规则都不是递归规则并不能决定文法无递归性
文法递归性:当一个语言是无穷集合时,定义该语言的文法一定递归
给出形式化定义,但使用语法树会大大简化求三者的过程
短语和直接短语:
句柄:最左直接短语
语法树:形式化定义很复杂,其生成就是画出某个句型的推导,再根据推导画树。
子树:由某非叶子结点连同其所有分支。
简单子树:只有单层分支的子树
短语、直接短语、句柄的语法树求法
判断:最左推导不唯一,最右推导不唯一,语法树不唯一
消除:加非形式化规定,比如确定优先级;构造等价的无二义性文法(难)
语言二义性:语言确定一类文法,如果这一类文法都是二义性的,则语言是二义性的。即对该语言来说,不存在无二义性的文法表示。
0型文法,无限制文法,图灵机,左部至少一个非终结符
1型文法,上下文有关文法,线性有界自动机,每一个规则,左部的长度不大于右部的长度,但α->ε满足1型文法
2型文法,上下文无关文法,下推自动机,规则左部只有一个非终结符
3型文法,正规文法,有限状态自动机,2型文法基础上,右部的非终结符个数不大于1
文法限制:文法中不能含有A->A的规则,有害规则;文法中不存在多余规则。
编译程序中词法分析器所完成的任务是从源程序中识别岀一个一个具有独立意义的单词符号
词法分析程序的功能是从左到右扫描源程序字符串,根据语言的词法规则识别出各类单词符号。输出单词符号的形式是二元组:(单词种别,单词自身值)
正规文法或正规式
正规式与正规集
Q:有穷状态集合,每一个元素称为一个状态
Σ:有穷输入字母表,每个元素称为一个输人字符
Z⊆Q:终态集
f:从Q×Σ到Q的单值映射
S∈Q:唯一初态
f:从Q×Σ到Q的多值映射
S⊂Q:非空初态集
以词法分析器生成的单词符号序列作为输入,根据语言的语法规则(描述程序语言语法结构的上下文无关语法),识别出各种语法成分(如表达式、语句、程序段乃至整个程序等),并在分析过程中进行语法检查,检查所给的但此符号序列是否是该语言的一个句子。若是,则以该句子的某种形式的语法树作为输出;若不是,则表明有错误,并指出错误的性质和位置。
词法分析中,文法的终结符代表由源程序输入的字符;语法分析中,可以将终结符视为经过词法分析后得到的单词符号,如b,可以理解为begin缩写
自上而下的分析方法:从树根开始,往下构造语法树,直到建立每个树叶的分析方法。
自下而上的分析方法:从语法树末端开始,步步向上规约,直至根节点的分析方法
非确定的自上而下分析法的基本思想是,对任何输入串W试图用一切可能的办法,从文法的开始符号岀发,自上而下地为它建立一棵语法树。或者说,为输人串寻找一个最左推导。如果试探成功,则W为相应文法的一个句子,否则就不是文法句子。本质是穷举试探
确定的自上而下的分析法必须要求文法为LL(1):无左递归、无回溯
不是所有非LL(1)文法都能改写为LL(1)文法
对下列文法构造递归向下分析程序
E->TE’
E’->+TE’|ε
T->FT’
T’->*FT’|ε
F->(E)|id
Main
main() {
Scaner();
E();
if (sym=='$')
printf("success");
else printf ("fail");
}
E->TE’
E() {
T();
E'();
}
E’->+TE’|ε
E'( ) {
if (sym == '+') {
Scaner();
T();
E'();
}
else if ((sym!=‘)’)&&(sym!=‘$’)) error( );
}
T->FT’
T() {
F();
T'();
}
T’->*FT’|ε
T'() {
if (sym == '*') {
Scaner();
F();
T'();
}
else if (sym!∈follow(T')) error( );
}
F->(E)|id
F() {
if(sym == 'id') Scaner();
else if(sym == '(') {
Scanner();
E();
if(sym == ')') Scanner();
else error();
}
else error();
}
下面主要是预测分析表的构造
1.求出所有FIRST,FOLLOW
2.对每一个产生式进行分析填表
3.分析时进栈倒序
错误分析:当元素的内容为“出错标志”则表明A不应该面临输入符号,无意义的元素用空表格表示,出错
用一个寄存文法符号的先进后出栈,将输入符号一个一个地按从左到右扫描顺序移入栈中,边移入边分析当栈顶符号串形成某条规则右部时就进行一次规约,即用该规则左部非终结符替换相应规则右部符号串。被规约的串称为可规约串。
重复这一过程直到输入串分析完毕。最终若栈中剩下句子右界符“ $ ” 和文法的开始符号,则所分析的输入符号串是文法的正确句子,否则,就不是文法的正确句子,报告错误
可规约串的刻画有多种:规范规约分析法,用句柄;算符优先分析法,用最左素短语;
识别可规约串方法有多种:简单优先分析法和LR分析法都是规范规约分析法,都是用句柄刻画可规约串,但识别句柄的方法不同。LR根据历史、现实、展望确定栈顶是否形成句柄;简单有限分析法根据文法符号之间的优先关系确定
所谓算符优先分析法就是依照算术表达式的四则运算过程而设计的一种语法分析方法。
这种分析方法首先要规定运算符之间(确切地说是终结符之间)的优先关系和结合性质,
然后借助这种关系,比较相邻运算符的优先级来确定句型的可归约串并进行归约。
算符优先分析法不是规范规约的分析方法,因为仅在终结符号之间定义优先关系而未对非终结符定义优先关系,从而无法使用优先关系表去识别由单个非终结符组成的可规约串,因为它使用最左素短语来刻画可规约串
算符文法OG:不存在相邻非终结符
算符优先文法:不存在矛盾的算符优先关系
算符优先分析表构造
1.FIRSTVT,LASTVT集
2.逐个产生式找等价
3.找算符关系
4.$
LR 分析法是一种自下而上进行规范归约的语法分析方法。这里 L 是指从左到右扫描输
人符号串,R 是指构造最右推导的逆过程。
LR 分析法是表格驱动的,比递归下降分析法、预测分析法和算符优先分析法对文法的
限制要少得多,也就是说,对于大多数用无二义性上下文无关文法描述的语言都可以用 LR 分析法进行有效地分析
优点:快、准确、适用于大多数无二义性上下文无关文法
是否构成句柄:根据分析栈中记录的已移进和归约出的整个符号串(即历史) 和根据使用的规则推测未来可能遇到的输入符号(即展望),以及现实读到的输人符号这 3 个方面的信息来确定
基本思想:上下文无关文法=>构造识别文法规范句型活前缀的DFA=>DFA转换为LR分析表
文法规范句型的活前缀:规范句型活前缀是指规范句型的前缀,可以是一个或若干个规范句型的前缀。
LR(0)分析就是在分析的每一步,只需根据当前栈顶状态而不必向前查看输人符号就
能确定应采取的分析动作
LR(0)项目集分类:
LR(0)项目集族
LR(0)分析表的构造
LR(0)要求无冲突,太苛刻。
为了对语言句子进行确定性的分析,需要解决 “移进-归约” 或 “归约-归约” 冲突,SLR(1)向前查看一个输入符号的办法来解决冲突。
SLR(1)分析表构造(仅有这里不同)
LR(1)分析法的思想是在分析过程中,当试图用某一规则归约栈顶的符号串a时,不仅应该査看栈中符号串如,还应向前扫视一个输入符号 a,只有当&Aa的确构成文法某一规范句型的前缀时,才能用此规则进行归约
LR(1)项目集族
LR(1)分析表构造
LR(1)分析法虽然可以解决SLR(1)方法所难以解决的“移进-归约” 或 “归约-归约” 冲突,但是对同一个文法而言,当搜索符不同时,使得同一个项目集被分裂成多个项目集从而引起状态数的剧烈增长,导致了时间和内存空间的急剧上升,它的应用也相应地受到了一定的限制。为了克服 LR(1 )分析法的这种缺点,我们可以采用 LALR(1)分析法
LALR(1)分析表构造
ACTION和GOTO标志没写,偷懒了
任何一个二义性文法绝不是LR文法,与其相应的 LR 分析表一定含有多重定义的元素。但是对于某些二义性文法,若在含多重定义的 LR 分析表中加进足够的无二义性规则,则可以构造出比相应非二义性文法更优越的 LR 分析器
词法错误、语法错误、语义错误、逻辑错误
语法分析器中错误处理程序的基本目标是:
① 清楚、准确地报告错误的出现;
② 快速地从错误中恢复,继续检査后面的错误;
③ 尽可能少地增加处理正确程序时的开销。
错误恢复策略
紧急方式恢复策略:发现错误时,语法分析器开始抛弃输入符号,每次抛弃一个
符号,直到发现某个指定的同步符号为止。
短语级恢复策略:发现错误时,语法分析器对剩余的输人符号进行局部纠正,用
一个能使语法分析器继续工作的符号串代替剩余输人的前缀
出错产生式策略:扩充语言的文法,增加产生错误结构的产生式
全局纠正策略:希望编译器在处理有错误的输入字符串时尽可能少改动。其主要
思想是,如果给定包含错误的输人串% 和文法 C,算法会发现符号串 y 的一棵分析树,并且使用最少的符号插人、删除和修改,将x变换成正确的输人符号串y。
我们可以在语法分析表动作域部分,为原来表示出错的空白项填上一个指针,它指向编译器设计者为之设计的错误处理程序。
对语法分析后的语法单位进行语义分析,首先编译程序审查每个语法结构的静态语义,如果静态语义正确,再生成中间代码,也有的编译程序不生成中间代码而直接生成实际的目标代码。
文法符号配备属性值,代表与其相关的信息,如类型、值、存储位置等。属性值可以在语法分析过程中计算和传递。
综合属性:自下而上,继承属性:自上而下
终结符只有综合属性,通过词法分析提供
非终结符既可有综合属性也可有继承属性,开始富豪的继承属性作为属性计算的初始值
属性文法包含一个上下文无关文法和一系列语义规则。为文法的每一个规则配备的计算属性的规则, 称为语义规则(描述语义处理的加工动作)。
语义规则包括:属性计算、静态语义检查、符号表操作、代码生成等。
依赖图,树遍历,一遍扫描
S-属性文法:只含有综合属性的属性文法
L-属性文法:A->X1X2X3…Xn, Xj仅继承X1~Xj-1和A的继承属性
提高代码质量的技术常称为代码优化。分为两大类:与机器有关的优化,与机器无关的优化。
与机器有关的优化一般在目标代码上进行。具体的有对寄存器的优化、多处理机的优化、特殊指令的优化。因为只观察中间代码或目标代码,也叫窥孔优化。
与机器无关的优化,在中间代码上进行。根据对象所涉及的范围,分为局部优化、循环优化、全局优化等
局部优化:合并已知量、删除公共子表达式(删除多余运算)、删除无用赋值
循环优化:代码外提、删除归纳变量、强度削弱
全局优化:数据流分析
代码优化的原则:等价原则、有效原则、合算原则
循环体内有始终不变的代码
强度削弱是指在不改变运算结果的前提下,将程序中执行时间长的运算替换成执行时间短的运算
尽量不引用那些只传递信息不改变值的变量
算法可以不记,自己根据例题画一画即可。