注释:测试博客园的MarkDown功能。贴下旧笔记。
阶段
使用
上下文无关文法
递归下降算法Lex
递归可枚举语言,上下文相关语言,上下文无关语言,正规语言
lex and parser
->
tree正规表达式
正规表达式转NFA
Thompson
构造法将正规表达式分解为最基本的子表达式,分别构造其NFA,然后组合
-[s]->(i)-[e]->(f)
-[s]->(i)-[a]->(f)
-[s]->(i)
(-[e]->(()N(s)())-[e]
|-[e]->(()N(t)())-[e]
) ->(f)
-[s]->(i)N(s)()N(t)(f)
-[s]->(i)-[e]->(()N(s)())-[e]->(f)
&(i)-[e]->(f)
&()-[e]->()
NFA
子集构造法->DFA
function NFA2DFA(inputs,s0,Dstates,Dtrans)
A=e-closure({s0})
Dstates.Add(A,false)
while T in Dstates.PopUnlableSet() do
for c in inputs do
U = e-closure(move(T,c))
if not Dstates.Contain(U) then
Dstates.Add(U,false)
end
Dtrans[T,c]=U
end
end
end
function e-closure(states,T)
closure=T
stack=T
while not stack.IsEmpty() do
t = stack.top();
stack.pop();
for u in states do
if edege(t,u)==e then
if not closure.Contain(u) then
closure.add(u)
stack.push(u)
end
end
end
end
end
双堆栈模型
function (S,F,a,s0,nextchar,e-closure,move)
S=e-closure({s0})
a=nextchar()
while not a=eof do
S=e-closure(move(S,a)
a=nextchar()
end
if not S.Intersect(F).IsEmpty() then return "yes" end
return "no"
end
DFA
基于DFA 模式匹配
r
右边链接一个结束符#
,cat-
节点,or-
或者star-
节点。正规表达式节点位置函数:nullable(n),firstpos(n),lastpos(n),followpos(n)
function nullable(node)
if node.IsLeaf() and node.IsE() then
return true
end
if node.IsLeaf() and (not node.IsE()) then
return false
end
if node.IsOrNode() then
c1=node.Left()
c2=node.Right()
return nullable(c1) or nullable(c2)
end
if node.IsCatNode() then
c1=node.Left()
c2=node.Right()
return nullable(c1) and nullable(c2)
end
if node.IsStarNode() then
return true
end
end
function firstpos(node)
if node.IsLeaf() and node.IsE() then
return {}
end
if node.IsLeaf() and (not node.IsE()) then
i=node.pos()
return {i}
end
if node.IsOrNode() then
c1=node.Left()
c2=node.Right()
return firstpos(c1).Union(firstpos(c2))
end
if node.IsCatNode() then
c1=node.Left()
c2=node.Right()
if nullable(c1) then
return firstpos(c1).Union(firstpos(c2))
else
return firstpos(c1)
end
end
if node.IsStarNode() then
return true
end
end
lastpos的计算和firstpos类似,只需调换c1和c2,则计算followpos的股则如下:
从正规表达式构造DFA
function (r,inputs)
r=root(concat('(',r,')#'))
Dstates={firstpos(r))
while Dstates.HasUnLabel() do
T=Dstates.GetNextUnLable()
for a in inputs do
for p in T do
U=followpos(p)
a=getnode(p).Symbol()
if not U.IsEmpty() and (not Dstates.Contain(U)) then
Dstates.Add(U,unlable=true)
end
Dtran[T,a]=U
end
end
end
end
最小化DFA的状态数
典型语法分析算法
语法错误处理
错误类型
错误恢复
上下文无关文法
正规表达式和上下文无关文法比较
使用正规表达式的场景
功能差别
嵌套结构
,正规表达式此时无力消除左递归
A->Aα1|...|Aαm|β1|...|βn => A->β1A'|...|βnA' + A'->α1A'|...αmA'|e
消除隐式左递归
function(A1,A2,...,An)
for i=1:n do
for j=1:i-1 do
Ai->Ajγ+Aj->δ1|δ2|...|δk => Ai->δ1γ1|δ2γ2|...|δkγk
end
Ai->Aiα1|...|Aiαm|β1|...|βn => Ai->β1Ai'|...|βnAi' + Ai'->α1Ai'|...αmAi'|e
end
end
提取左因子
function(A1,A2,...,An)
for i=1:n do
Ai->αiβi1|...|αiβin|γ => Ai->αiAi'|γ+Ai'->βi1|...|βin
end
end
非上下文无关语言结构
不可用上下文无关文法表示的例子:
L1={wcw|w \in (a|b)*}
标识符的声明先于引用L2={a^nb^mc^nd^m|m>=1,n>=1}
过程声明的形参个数和过程引用的实参个数应该一致L3={a^nb^nc^n|n>=0}
在键盘上敲打字母键,退格同样次数,敲打同样次数下划线:下划线标记的单词集合,正规表达式(abc)*则可以描述之可用上下文无关文法表示的例子:
L1'={wcw^R|w \in (a|b)*,w^R表示w的逆序}
L2'={a^nb^nc^md^m|m>=1,n>=1}
L3'={a^nb^n|n>=1}
这个例子不能用正规表达式表示两个性质
预测语法分析
functions look(products,inputs)
a=inputs.begin();
<s,t>=products.states.begin()
while a and <s,t> do
if a is terminal then
if match(s,t,a) then
a=inputs.next()
<s,t>=products.states.next()
else
return false
end
else
store.a=a
store.inputs=inputs
subproducts = a.getproducts()
for subproduct in subproducts do//递归下降
if look(a.getproducts(),inputs.rest()) then
<s,t>=products.states.next()
a=inputs.next()
break
else//回朔
a=store.a
inputs=store.inputs
end
end
end
end
return products.states.finish()
end
非递归的预测语法分析(表格驱动),对比NFA双堆栈模型
function look(stack,table,inputs,outputs)
--stack是文法符号序列,栈底是$,初始时stack含有文法的开始符号和下边的$
--table是分析表M,value=M[A,a],A是非终结符,a是终结符或$
--inputs是输入符号序列,末尾是$
--outputs是输出的语法树
ip=inputs.First()
while true do
X,a=stack.Top(),ip.Symbol()
if X.IsTerminalOr$() then
if X==a then
stack.Pop(),ip=inputs.Next()
else
error()
end
else
if not M[X,a]==error then --M[X,a]={X={Y1,Y2,...,Yk}},表示X->Y1Y2...Yk
stack.Pop()
Y=M[x,a][X]
outpus.Dump(X).Dump('->')
for i=1,k do
stack.Push(Y[k-i])
outpus.Dump(Y[i])
end
else
error()
end
end
if X==$ then break end
end
end
λ记法和λ演算系统
λx:σ.M
λx:σ.M->λy:σ[y/x]M
(λx:σ.M)N->[N/x]M
(M1=M2,N1=N2)/M1N1=M2N2
类型与类型系统简述
罗素悖论
编译器类型检查
集合论基本知识
集合论是数学的机器语言
(x|P(x))
,不会导致悖论的集合定义(x \in A|P(x))
。良序(基):集合A上的二元关系良序,其性质是不存在无限下降序列a0>a1>a2>...
关系
函数
上下文无关文法
<<编译原理>>
笔记第二章归纳法基本知识
公理与推理规则通常写成模式,借以表达一个给定形式的所有公式或证明步骤。
e=e
,每个形如e=e
的等式为公理。(A1 ... An)/B
,若有形如A1,...,An的公式的证明,则可组合它们得到对应公式B的证明。(e1=e2,e2=e3)/(e1=e3)
形式化而言,一个证明可定义为一个公式序列,其中每个公式或者证明是一个公理,不然则由前面的公式通过单一推理规则而得。由于每个推理规则通常有一系列前件和一个后件,很容易将证明看成一颗以公式标记的叶和内节点的形式的树。
(A1 ... An)/B
作为可能的内部的分支节点,其子树比为A1,...,An的证明。良序归纳法:设<是集合A上的良序二元关系,并且设P为A的某性质。若当P(A)对所有b<a成立时P(a)都成立,则P(a)对所有a \in A
成立。
PCF语法
每个PCF表达式都有唯一类型
nat
bool
,值:true
false
σxτ
、函数σ->τ
(以σ为定义域,τ为值域),函数是右结合的。表达式文法
boolexp
=true
|false
|if boolexp then boolexp else boolexp
|Eq? natexp natexp
natexp
=digital*
|natexp+natexp
|natexp x natexp
|if boolexp then natexp else natexp
digital
=0
|1
|2
|3
|4
|5
|6
|7
|8
|9
σexp
=if boolexp then σexp then σexp
公理
0
+0
=0
,0
+1
=1
,1
+0
=1
,1
+1
=2
,...if true then M else N=M
,if false then M else N=N
Eq? n n = true
, Eq? m n = false (m,n not equal)
配对及其函数
配对
M
具有类型σ
,N
具有类型τ
,则<M,N>
具有类型 σxτ
公理:
Proj1<M,N>=M
Proj2<M,N>=N
<Proj1<M,N>,Proj2<M,N>>=<M,N>
满射配对函数:
comp def= λf:nat->nat.λg:nat->nat.λx:nat.f(g(x))
公理:
λx:σ.M=λy:σ.[y/x]M, y在M中不是自由的
β: (λx.σ.M)N=[N/x]M
[N/x]x=N
[N/x]a=a
a
是常量或a
不等x
[N/x](PQ)=([N/x]P)([N/x]Q)
[N/x]λx:σ.M=λx:σ.M
[N/x]λy:σ.M=λy.σ.[N/x]M
x
不等y
且y
不属于FV(N)
[N/x]λy:σ.M=λz.σ.[N/x][z/y]M
z
,y
不等x
且z
不属于FV(MN)
λx.σ.Mx=M
x
不属于FV(M)
参数分离:
Curry=λf:(natxnat)->nat.λx:nat.λy:nat.f<x,y>
add=λp:natxnat.(Proj1p)+(Proj2p)
Curry(add)=(λf:(natxnat)->nat.λx:nat.λy:nat.f<x,y>)add
=λx:nat.λy:nat.add<x,y>
=λx:nat.λy:nat.(Proj1<x,y>)+(Proj2<x,y>)
=λx:nat.λy:nat.x+y
惯用形化
let x:σ=M in N def= (λx:σ.N)M
例子+去惯用形+规约:
let compose=λf:nat->nat.λg:nat->nat.λx:nat.f(g x) in
let h=λx:nat.x+x in
compose h h 3
//
(λcompse:(nat->nat)->(nat->nat)->nat->nat.
(λh:nat->nat.compose h h 3) λx:nat.x+x)
λf:nat->nat.λg:nat->nat.λx:nat.f(g x)
//
->(λh:nat->nat.(λf.nat->nat.λg:nat->nat.λx:nat.f(g x)) h h 3) λx:nat.x+x
->(λf.nat->nat.λg:nat->nat.λx:nat.f(g x))(λx:nat.x+x)(λx:nat.x+x) 3
->(λg:nat->nat.λx:nat.(λy:nat.y+y)(g x))(λx:nat.x+x) 3
->(λx:nat.(λy:nat.y+y)((λz:nat.z+z) x) 3
->(λy:nat.y+y)((λz:nat.z+z) 3)
->(λy:nat.y+y)(3+3)
->(3+3)+(3+3)
->12
不动点
引入
letrec f:σ->σ=M in N
let f:nat->nat=λy:nat.(if Eq? y 0 then 1 else y*f(y-1)) in f 5
F def= λf:nat->nat.λy:nat.if Eq? y 0 then 1 else y*f(y-1)
fixσ:(σ->σ)->(σ->σ)
letrec f:σ->σ=M in N def= let f:σ->σ=(fixσ λf:σ.M) in N
公理:
fix: fixσ=λf:σ->σ.f(fixσ f)
fixσ M = M(fixσ M)
fact n = (fix F) n
-->-> F(fix F)n
= (λf:nat->nat.λy:nat.if Eq? y 0 then 1 else y*f(y-1)) (fix F) n
-->-> if Eq? n 0 then 1 else n*(fix F)(n-1)
联立递归:
f = F f g
g = G f g
fixσxτ =λ<f,g>:<σ,τ>.<F f g,G f g>
公理语义
基本公理
add
Eq?
cond
proj
sp
α
β
η
fix
推理规则
(M=N)/(N=M)
(M=N,N=P)=(M=P)
(M=N,P=Q)/(M+P=N+Q)
(M=N,P=Q)/(Eq? M P=Eq? N Q)
(M1=M2,N1=N2,P1=P2)/(if M1 then N1 else P1=if M2 then N2 else P2)
(M=N)/(ProjiM=ProjiN)
(M=N,P=Q)/(<M,P>=<N,Q>)
(M=N)/(λx:σ.M=λx:σ.N)
(M=N,P=Q)/(MP=NQ)