编译原理
词法分析
一、正规式,正规文法,NFA相互转换
正规文法->正规式(A*闭包可以为空集ε):
正规式->NFA:
NFA->正规式:
正规文法->NFA。
右线性文法形如A→tB,引一条A到B的弧并标记为t;A→t则引一条A到终态的弧并标记为t。开始符号作为开始节点,增加一个终态节点。
左线性文法形如A→Bt,引一条B到A的弧并标记为t;A→t则引一条开始态到A的弧并标记为t。开始符号作为终态节点,增加一个开始节点。
NFA->正规文法直接转换成右线性文法,随后每个终态再推出个ε即可。
二、NFA与DFA的关系与转换
对于NFA而言,每一个状态输入一个字符后,下一个状态是不确定的,而DFA是确定的。
NFA转换为DFA时,有两种运算,ε-closure(A)等于A的状态+A输入ε所能到达的状态;move(A,a)等于A集合状态输入a后所能到达的状态集合,不包含A本身。转换过程如下:
三、DFA化简
由于DFA状态中,存在两类无用状态,包括没有通路到达终态,或者是从开始状态出发永远不能到达的状态。
①根据是终态还是非终态分为两个集合(1,2,3,4)和(5,6,7)
②(5,6,7)中5状态输入a转换到集合2中,而6,7输入a转换到集合1,因此集合2划分为(5)和(6,7)新的两个集合。
③集合1中,1,2输入a转换到集合3,而3,4输入a转换到集合1,因此集合1划分为(1,2)和(3,4)
④对于集合(3,4)根据输入b转换到不同集合又可以进一步划分为(3)和(4)
语法分析
一、First,Follow,Select
First(A):对于产生式:X→Y1Y2…Yn,则first(X) = (first(Y1)-{ε})∪(first(Y2)-{ε})∪ …… ∪(first(Yn)-{ε})∪{ε},空集ε是可以属于first集的。
Follow(A)={a|S→αAβ(所有包含A的产生式) 且 a∈FIRST(β)}相当于求出所有右部的A中后面第一个终结符。注意若β能推出ε,则follow(S)∈follow(A)。follow集中不能有空集,若A为开始符号,则把#加入到follow(A)。
若α推不出空ε,则Select(A→α)=first(α);若能退出空,则select(A→α)=(first(α)-ε)∪follow(A)。
二、LL(1)判定
自顶向下分析法LL(1)文法,满足所有左部非终结符相同的产生式,他们的select集交集为空。LL1的含义在于从左向右扫描输入串,最左推导,只需向右看一个字符就能决定选择哪个产生式进行推导。
三、非LL1转化为LL1
消除左公共因子:①显式的左公共因子合并后通过引入新的非终结符替代非公共部分来进行化简。
②隐式的左公共因子,把产生隐含左公共因子的产生式用另一个对应的非终结符的所有产生式替换,再同①化简。注意要去掉多余的产生式(由开始符推导到达不了的产生式)
消除左递归:①直接左递归转化为右递归,引入一个新的非终结符替代递归重复的部分,并让他能推出ε。
②间接左递归先转化为直接左递归,再同①做法。
多个非终结符相互套用形成的左递归,只需要破坏这个循环链,消除最顶层或者最底层的非终结符递归即可。
四、预测分析
行号为非终结符,列号为终结符(加入#)。对于a∈SELECT(A→α),则把A→α放入A行α列中。
根据分析栈栈顶非终结符和剩余输入串栈顶终结符,来查看预测表选择产生式对分析栈栈顶元素进行转换规约,注意匹配入栈时所使用产生式右部倒序入栈;若分析栈栈顶的终结符等于剩余输入串的终结符,则两边同时出栈;若使用的产生式是A→ε,则分析栈栈顶直接出栈。
翻译方案
综合属性:非终结符(产生式左部)的值由计算出的底层非终结符传递。
继承属性:非终结符(产生式右部)的值由父节点或者兄弟节点传递。
翻译方案需要往产生式插入语义动作。综合属性插入在产生式右部最后面,继承属性插入在该非终结符左边。