編譯原理之理解文法和語言
簡介
一個程式設計語言是一個記號系統,如同自然語言一樣,它的完整定義應包括語法和語義兩個方面。所謂一個語言的語法是指一組規則,用它可以形成和產生一個合適的程式。目前廣泛使用的手段是上下文無關文法,即用上下文無關文法作為程式設計語言語法的描述工具。語法只是定義什麼樣的符號序列是合法的,與這些符號的含義毫無關係,比如對於一個Pascal程式來說,一個上下文無關文法可以定義符號串A:=B+C是一個合乎語法的賦值語句,而A:=B+就不是。但是,如果B是實型的,而C是布林型的,或者B、C中任何一個變數沒有事先說明,則A:=B+C仍不是正確的程式,也就是說程式結構上的這種特點——型別匹配、變數作用域等是無法用上下文無關手段檢查的,這些工作屬於語義分析工作。程式設計語言的語義常常分為兩類:靜態語義和動態語義。靜態語義是一系列限定規則,並確定哪些合乎語法的程式是合適的;動態語義也稱作執行語義或執行語義,表明程式要做些什麼,要計算什麼。
闡明語義要比闡明語法困難得多,儘管形式語義學的研究已取得重大進展,但是仍沒有哪一種公認的形式系統可用來自動構造出正確的編譯系統。本書不對形式語義學進行介紹。
1.理解符號串與集合運算。
L={A,B, … ,Z,a,b, … ,z}
D={0,1, … ,9}
說明下表示的含義:
LUD L和D都是集合,那麼LUD即為L的D的並集合,即L={A,B, … ,Z,a,b, … ,z,0,1, … ,9}
LD =>> {xy | x∈L且y∈D}
L4 L集合的4位組合即{AAAA, AAAB, ..., zzzz}
L* 集合L的閉包
D+ 表示D的正閉包
L(LUD)* L並D的正閉包與L的乘積,即{xy | x∈L且y∈(LUD)*}
2.文法G(Z):Z->aZb|ab定義的是什麼樣的語言?
定義的是規則,也稱作重寫規則,產生式或生成式。
Z->aZb|ab,即Z->aZb->aaZbb->aaabbb
則:L(G) = {anbn | n > 1}
3.寫出教材22頁例2.2中識別符號的文法四元組形式(VN,NT,P,S)。
例2.2有文法G=(VN,VT,P,S)。
其中,
VN={識別符號,字母,數字},
VT={a,b,c,... ,x,y,z,0,1,... ,9},
P={<識別符號>→<字母>
<識別符號>→<識別符號><字母>
<識別符號>→<識別符號><數字>
<字母>→a
<字母>→b
...
<字母>→z
<數字>→0
<數字>→1
...
<數字>→9}
S=<識別符號>
解:由此例題可設<識別符號>為I,<字母>為L,<數字>為D則
P={I→L
I→IL
I→ID
L→a
L→b
...
L→z
D→0
D→1
...
D→9}
S = I
則
I-> L|IL|ID
L-> a|b|c|...|x|y|z
D-> 0|1|2|...|8|9
4.寫出下列表達式的最左推導、最右推導。
G(E):
E=> E + T | T
T=>T * F | F
F=>(E)| i
- i*i+i
最左推導:E => E + T => T+T => T*F+T => F*F+T => i*F+T => i*i+T => i*i+F => i*i+i
最右推導:E => E + T => E+F => E+i => T+i => T*F+i => T*i+i => F*i+i => i*i+i
- i+i*i
最左推導:E => E + T => T+T => F + T => i + T*F => i + F*F => i + i*F => i+i*i
最右推導:E => E + T => E + T*F => E + T*i => E + F*i => E + i*i => T +i*i => F+i*i => i+i*i
- i+(i+i)
最左推導:E => E + T => T+T => F + T => i + F => i+(E)=> i+(E+T) => i+(T+T) => i+(F+T) => i+(i+T) => i+(i+F) => i+(i+i)
最右推導:E => E + T => E + (E) => E + (E) => E + (E+T) => E+(E+F)=> E+(E+i) => E+(T+i) => E+(F+i) => E+(i+i) => T+(i+i) => F+(i+i) => i+(i+i)
注意觀察最左和最右推導過程的不同。