A -> B
B -> BC|C
C -> 0|1|2|3|4|5|6|7|8|9
A -> aBc
B -> b
==================
aBc是abc的归约
abc是aBc的推导
规范推导:最右推导
规范规约:最左规约
无符号串
=》数字串
=》数字串+数字
=》数字串6
=》数字6
=》56
由产生式到最终状态之间的中间串
例如<数字>9
产生式最终匹配的终态
例如56是文法无符号整数的一个句子
确定有限自动机:每个状态在接收下一个输入,只会转移到唯一一个下一个状态
非确定有限自动机,自动机中含有某些状态,在接收下一个输入后,会转移到多于一个的状态
每个NFA都存在一个DFA,使得L(NFA) = L(DFA),也就是说等价
NFA的确定化就是,从NFA转变为DFA的过程
子集构造法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sideDoGL-1594611776650)(http://upload-images.jianshu.io/upload_images/24077087-6f91da5d1ba4bd27.PNG)]
然后把I列表标记为状态,并画出DFA
在NFA->DFA后,得到的DFA并不是最简的,必须通过DFA最简化处理,来提高分析的效率
简化步骤为:
逆过程
P->Pa|b => ba+
P ->bM
M -> aM|空
A -> Bc|d
B -> aA|Ab
=>
A -> aAc|Abc|d
=>
A -> (aAc|d)M
M -> bcM|空
若X->a…则a加入X的First集中,如果X->空,则空加入到X的First集中
X->amm|bk|空
=> First(X) = {a,b,空}
X->Ym|b
Y->a|d|空
=> First(X) = {a, d, m, b}
L:最左推导
1:向前看1个字符
对文法G的句子进行确定的自顶向下语法分析的充要条件是
产生式A->B|C满足
LL(1)文法不能由二义性,也不能含有左递归,对LL(1)文法的所有句子都可以进行自顶向下的语法分析
并不是所有语言都可以用LL(1)来描述
非终结符T的最左终结符集合
非终结符T的最右终结符集合
E->aA|bB
A->cA|d
B->cB|d
通过子集构造法
通过从左向右扫描句子,通过下一输入,决定从Si归约到Sj,并最终到达终态
LR(0)文法,如果遇到在一个状态中,同时出现移进和规约的冲突,则会让LR(0)无法判断此步骤应该如何处理
S3状态,已经满足归约条件,则无论下一个字符是什么,都需要进行归约操作;但是如果下一个字符是‘,’,则应该i进行移进操作
SLR(1)为了解决移进归约冲突,则遇到冲突时向前看一个字符,来解决冲突
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DQ3JlhdP-1594611776668)(http://upload-images.jianshu.io/upload_images/24077087-9a4197381846ba73.PNG)]
当某个状态遇到移进归约冲突,并且下一个移进的符号,与归约符号的下一个符号相同,则无法使用SLR(1)进行分析
SLR(1)通过Follow(A)来计算,而LR(1)通过First(A.next)来决定来缩小范围
a+b*(c-d)+e/(c-d)
=>
abcd-*+ecd-/+
内部节点代表操作符,叶子节点为操作数
把抽象语法树的公共部分进行合并,可以减少公共表达式的计算
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6lOWYI7v-1594611776674)(http://upload-images.jianshu.io/upload_images/24077087-096fe6b09bf7c078.PNG)]
可以看作抽象语法树或者DAG的一种线性表示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JHYv2uLH-1594611776675)(http://upload-images.jianshu.io/upload_images/24077087-6e9d2568672ef3c0.PNG)]
result = arg1 op arg2
=>
(op, arg1 arg2, result)
result = arg1 op arg2
=>
(i) (op, arg1, arg2)
用i位置来保存临时结果
x[i]=y =>
(0) ([]=, x, i)
(1) (assign, (0), y)
y=x[i] =>
(0) (=[], x, i)
(1) (assign, y, (0))
LOC(A[i]) = base + (i-low)*w
= (base-low*w) + i*w
= conspart + varpart
Loc(A[i][j]) = base + ((i-low1)*n2+j-low)*w
= (base-(low1*n2+low2)*w)+(i*n2+j)*w
可见任意维度的数组元素的计算都可以分为不变计算和可变计算组成,在编译时首先计算出conspart,可以达到优化的目的
S -> if(E) S1|if(E) S1 else S2
对于E.true的未来地址,在三地址码中,先通过打标志的方式,在后续确定下地址后,再回填到标志的位置
S -> while(E) S1
变长字段通过指针链接到另外的内存区存储
通过顺序查找
自适应线性表:通过新增一列,通过LRU算法,构成链表,最新访问的元素会出现在链头
建立树索引
建立hash索引
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v5nVcRnB-1594611776682)(http://upload-images.jianshu.io/upload_images/24077087-ee90a0b563e37fb6.PNG)]
用于管理函数变量的信息
通过变更top和sp指针,实现活动记录的栈式处理
指向直接外层函数的首地址
指向上一层函数的首地址
所有外层函数的首地址
基于基本块范围内的优化
对于循环变量i,由于L中有其他变量A是跟I有线性关系的,可以用A来代替i在循环的控制,以减少对循环变量的计算