概述
編譯程序:將高級語言的源程序翻譯成與之等價的低級語言的目標程序的這樣一種程序
源程序運行過程:編譯階段+運行階段或者編譯階段+彙編階段+運行階段
解釋程序:以源程序作爲輸入,但不產生目標程序,解釋一條執行一條
彙編程序:用於特定計算機上的彙編語言的翻譯程序。有時編譯器把彙編語言作爲目標語言,然後再由彙編程序將它翻譯成目標代碼。
連接程序:將分別在不同的目標文件中編譯或彙編的代碼收集到一個可直接執行的文件中
裝入程序:編譯器、彙編程序或連接程序生成的代碼還不能運行,裝入程序處理所有的與指定的基地址有關的可重定位地址,並將修改後的指令和數據放在內存中適當的位置。
預處理程序:預處理程序是在真正的編譯開始之前由編譯器調用的獨立程序。預處理程序可以刪除註釋、包含其它文件以及執行宏替代。
源程序+初始數據→解釋程序→計算結果
源程序→編譯程序→初始數據+目標程序+運行系統子程序→計算結果
編譯過程
一般分爲5個階段:詞法分析→語法分析→語義分析與中間代碼產生→優化→目標代碼生成
- 詞法分析:按照語言的詞法規則使用特定的工具將源程序轉換成單詞符號串
- 語法分析:按照語法規則使用上下文無關文法、確定的下推自動機將單詞符號串轉換爲各類語法範疇 (層次結構分析)
- 語義分析與中間代碼產生:按照語義規則使用屬性文法將語法範疇進行初步翻譯、產生中間代碼(中間代碼即獨立於具體硬件的記號系統,四元式、三元式、逆波蘭式等。)
- 優化:按照等價變換規則使用變換方法將中間代碼變爲更高效的中間代碼
- 目標代碼生成:將中間代碼轉換成依賴於機器的目標代碼
表格管理程序:登記源程序的各類信息和編譯程序各階段的進展情況,如符號表。
出錯處理程序:發現並指出源程序中錯誤的性質和位置;自動校正錯誤
遍:對源程序或源程序的中間結果從頭至尾掃描一次,並作有關的加工處理,生成新的中間結果或目標程序的處理過程稱爲一遍。可以把一個階段分爲若干遍,也可以把多個階段合爲一遍,通常有一遍和多遍編譯程序。
前端(front end):由與源語言有關但與目標機無關的部分組成。
後端(back end):包括與目標機有關的部分。而一般不依賴於源語言,只與中間代碼有關的編譯階段。
文法基礎
程序語言是符號語言,即一個記號系統,它主要有語法、語義和語用等三方面定義。
語法:是對語言結構的定義(什麼樣的符號序列是合法的)。任何語言程序都可看成是一定字符集上的一字符串(有限序列),語法定義語言的詞法和語法的形式規則。
- 字母表是一個有限的字符集,字符集中的字符是語言程序中可能出現的字符,它們是語言程序單詞的組成部分。
- 詞法規則定義了語言程序中單詞符號的形成規則。即什麼樣的字符串是一個合法的單詞。如標識符、數值常量、運算符等單詞的構成規則。
- 語法規則定義了語言程序中語法單位的形成規則。一般語言的語法單位有表達式、語句、分程序、函數、過程和程序等。描述語法規則和進行語法分析的有效工具是上下文無關文法。
語義:描述語言的含義;定義語言的單詞符號和語法單位的意義。目前編譯程序中常用的語義分析方法是一種基於屬性文法的語法制導翻譯。即在語法分析的同時對其中識別出的語法單位進行語義的分析與翻譯工作;在描述文法的同時爲定義的語法範疇加上它們的屬性計算規則,屬性可以是語法範疇的類型、地址、取值、執行動作等信息。
語用:是從使用的角度去描述語言。定義程序設計技術和語言成分的使用方法,它使語言的基本概念與語言的外界(如數學概念或計算機的對象和操作)聯繫起來
字母表(alphabet):字母表是元素的非空有窮集合,任何語言的字母表指出了該語言中允許出現的一切符號。
【例如】 ∑ = {a,b,c}
∑是字母表,由 a,b,c 三個元素組成。
C 語言的字母表是字母、數字和若干專用符號組成。
符號(symbol):字母表中的元素稱爲符號,或稱爲字符。
【例如】 ∑ = {a,b,c}
a,b,c 是字母表 ∑ 中的符號。
符號串(string):符號的有窮序列稱爲字符串。符號串總是建立在某個特定字母表上的且只能由字母表上的有窮多個符號組成。不包含任何符號的符號串,稱爲空符號串,用(epsilon)表示
【例如】設有字母表 ∑ = {a,b,c},
則有符號串 a,b,ab,ba,cba,abc,…
(a,b,ab,ba,cba,abc 等都是字母表∑上的符號串)
符號串的連結 catenation:設 x 和 y 是符號串,則串 xy 稱爲它們的連結。
【例如】設 x = abc,y = 10a,
則 xy = abc10a
則 yx = 10aabc
特別,對任意一符號串 x 有:
集合的乘積 product:設 A 和 B 是符號串的集合,則 A 和 B 的乘積定義爲:AB = {xy | x ∈ A, y ∈ B}
【例如】設 A = {a,b}, B = {c,d}
則 AB = {ac,ad,bc,bd}
空集 Φ empty set:Φ 表示不含任何元素的空集 { }
符號串的冪運算 power:設 x 是符號串,則 x 的冪運算定義爲:
集合的冪運算同理,只不過
集合A的正閉包A+與閉包A:設 A 是符號串的集合,則集合 A 的正閉包 A+ 和閉包 A* 定義爲:
形式語言和文法
形式語言:序列(字符串)的集合稱爲形式語言。每個形式語言都是某個字母表上按某種規則構成的所有符號串的集合;任何一個字母表上符號串的集合均可定義一個形式語言。
【例如】
C 語言是具有基本符號字母表上的符號串的集合。每個 C 語言程序是基本符號的符號串。
形式語言的描述有兩種方法:
- 當語言爲有窮集合時,用枚舉法來表示語言。
【例】設有字母表 A={a,b,c},則L1 = {a,b,c},L2 = {a,aa,ab,ac},L3 = {c,cc}均表示字母表 A 上的一個形式語言。由於這三個語言均是有限符號串的集合,可以枚舉出其全部句子來表示該語言。
- 當語言爲無窮集合時,需要設計文法來描述無窮集合的語言。
顯然由 A 生成的符號串屬於 ∑+,這就是文法描述語言,它描述了無窮集合的語言。
文法的形式定義:
規則:規則也稱產生式,它是一個符號與一個符號串的有序對(A,),通常寫做A→( 或 A::= )
其中 A 是規則左部,是一個符號;是規則右部,是一個符號串。→ 或 ::= 表示“定義爲”或“生成”,意思是左部符號用右部符號串定義或左部符號生成右部符號串。規則的作用是告訴如何用規則中的符號串生成語言中的序列。一組規則規定了一個語言的語法結構。
非終結符:出現在產生式左部能派生出符號或符號串的那些符號,即每個非終結符表示一定符號串的集合。用大寫字母表示或用尖括號把非終結符括起來。
終結符:是不屬於非終結符的那些符號,它是組成語言的基本符號,是一個語言的不可再分的基本符號,只出現在產生式右部。通常用小寫字母表示。
【例】產生式 A→A1 A→A0
A 是非終結符,0、1 是終結符
文法:文法是規則的非空集合,是一個四元式G =(,,P,S),其中:
- 是一個非空有限集,它的每個元素爲非終結符號,
- 是一個非空有限集,它的每個元素爲終結符號; ∩ = Φ
- S 是一個非終結符號,稱爲開始符號或識別符號;開始符號 S 至少必須在某個產生式的左部出現一次。
- P 是一個產生式集合(有限),每個產生式的形式是P→α,其 P ∈ , α ∈ (∪)*。
左部相同的產生式,如A→α1, A→α2, …, A→αn,可合併爲一個,縮寫爲A→ α1|α2| … |αn
設計文法示例
例1
設字母表∑={a,b},試設計文法,描述語言 L={, | n≥1}
分析:設計文法來描述一個語言,關鍵是設計一組規則生成語言中的符號串。設計語言的文法,必須分析這個語言是由怎樣一些符號串組成,即首先分析語言中符號串的結構特徵:
當 n=1 L = {aa,bb}
當 n=2 L = {aaaa,bbbb}
當 n=3 L = {aaaaaa,bbbbbb}
…
L = {aa,bb,aaaa,bbbb,aaaaaa,bbbbbb,…}
語言 L 是由偶數個 a,偶數個 b 這樣的符號串組成的集合。
很顯然,a,b是終結符,非終結符A定義完整L,需要終結符B、D來描述A,按照邏輯,該文法能描述語言L,此外,描述該語言的文法不是唯一的。
G 和 G’ 是兩個的文法,如果它們描述的語言相同,那麼稱 G 和 G’ 爲等價文法。
例2
設計一個表示所有標識符的文法
分析:標識符的定義是字母或以字母開頭的字母數字串(此處先不考慮大寫字母)
顯然,終結符是字母數字集合{a-z}∪{0-9}中的元素,標識符語言={字母*字母,字母*數字},因此設計文法
例3
用文法定義一個含+、*、()的算術表達式。
分析:變量是表達式;若 E1 和 E2 是算術表達式,則 E1+E2,E1*E2,(E) 也是算術表達式。
例4
設字母表∑={a,b},設計一個文法,描述語言 L={aa | n≥0}
語言形式定義
直接推導:令 G 是一文法,一步推導 => 表示用某一規則的右部替換其左部。如果有 xAy => xαy,僅當 A→α 是 G 的一個規則(產生式),且 x、y ∈ (∪),稱 xAy 直接推出 xαy。
推導:如果存在一個直接推導序列: => => … => 則稱這個序列是從 到 的長度爲 n 推導,記爲=>+(這個符號其實是+在=>這個符號上面,這裏表示不出來,下面這個符號都用=>+表示)
廣義推導: =>(這個符號其實是*在=>這個符號的上面,這裏表示不出來,下面這個符號都用=>*表示) 表示從α0 出發,經過 0 步或多步可推導,也就是說 =>* 意味着: = 或者 =>+
直接推導的長度爲1,推導的長度大於等於1,廣義推導的長度大於等於0
句型與句子:
設有文法 G[S],如果S=>*x, x∈(∪)*,則稱符號串 x 爲文法 G[S]的句型.
如果S==>*x, x∈,則稱符號串 x 爲文法 G[S]的句子。
【例】設有文法 G[S]: S→01 | 0S1
有
S =>*01 句型,又是句子
S =>*0S1 句型
S =>*00S11 句型
S =>*000111 句型,又是句子
【例】設有文法G[E]:E → E+E | E*E |(E) | i
試證明符號串 (i*i+i) 是文法G[E]的一個句子
分析:只要證明符號串(i*i+i) 對文法G[E]存在一個推導,就可證明符號串(i*i+i) 是文法G[E]的一個句子。
因爲
E=>(E)=>(E+E)=>(E*E+E)=>(i*E+E)=>(i*i+E)=>(i*i+i)
即有 E=>*(i*i+i)
所以符號串 (i*i+i) 是文法G[E]的一個句子。
語言:
文法 G[S] 產生的所有句子的集合稱爲文法 G 所定義的語言,記爲 L(G[S]):L(G[S]) = { x | S=>+x 且 x∈ },由語言定義可知:
(1)當文法給定,語言也就確定;
(2)L(G) 是 的子集。即屬於的符號串不一定屬於L(G)
文法求語言示例
例1
設有文法G[S]: S→01 | 0S1,求該文法所描述的語言
分析:問題歸結爲由識別符號 S 出發,將推導出什麼樣的句子,也就是說 L(G{S])是由一些什麼樣的符號串所組成的集合,找出其中的規律,用式子或自然語言描述出來。
即S >=+
所以此文法定義的語言爲 L(G[E]) = { | n≥1}
例2
設有文法G[S]: S→0S|1S|$\epsilon $求該文法所定義的語言
例3
設有文法G[A]: A→yB,B→xB|x求該文法所定義的語言
規範推導和規範歸約
文法所定義的任一句型和句子,都可以根據文法推導出來,但同一個句型(句子)可以通過不同的推導序列推導出來,這是因爲在推導過程中所選擇非終結符的次序無關。
【例】設有文法 G[N1]:N1 → N,N → ND | D,D → 0 | 1 | 2
該文法所定義的語言是由數字 0,1,2組成的所有無符號整數。符號串 12 是該文法的一個句子,它可以通過下列不同的推導序列推導出來:
(1) N1 =>N=>ND=>N2=>D2=>12
(2) N1 =>N=>ND=>DD=>1D=>12
(3) N1 =>N=>ND=>DD=>D2=>12
爲了使句子能按一種確定的推導序列來產生,以便對句子的結構進行確定性的分析。通常只考慮兩種特殊推導:
- 最左推導是指對於一個推導序列中的每一步直接推導 α=>β,都對 α 中的最左非終結符進行替換。
- 最右推導是指對於一個推導序列中的每一步直接推導 α=>β,都對 α 中的最右非終結符進行替換。
最右推導也稱爲規範推導,用規範推導推導出的句型稱爲規範句型。每個句子都有規範推導,但對句型此結論並不成立。
【例】對文法 G[N]:N →N’, N’→D | N’D, D →0 | 1 | 2 | … | 9
N=>N’=>N’D=>N’8=>D8=>88 規範推導
N=>N’=>N’D=>DD=>8D=>88 不是規範推導
歸約:推導的逆過程。歸約是與推導相對的概念,推導是把句型中的非終結符用規則的一個右部來替換的過程,而歸約是句型中的某個子串用一個非終結符來替換的過程.用 =>· (實際上·在=>這個符號上面,下面均用=>·表示這個符號)表示歸約。
【例】設 A→α是文法 G 的一個規則,則有
xAy => xαy
xαy =>· xAy
【例】設有文法 G[S]:S→AB, A→A0 | 1B, B→0 | S1
請給出句子 101001 的最左和最右推導。
分析:
最右推導是指在推導過程中任何一步α=>β(α和β都是句型),都是對α中的最右非終結符進行替換。
S=>AB=>AS1=>AAB1=>AA01=>A1B01=>A1001=>1B1001=>101001
最左推導是指在推導過程中任何一步α=>β(α和β都是句型),都是對α中的最左非終結符進行替換。
S=>AB=>1BB=>10B=>10S1=>10AB1=>101BB1=>1010B1=>101001
規範推導的逆過程,稱爲最左歸約,也稱爲規範歸約。
【例】 文法G[N1]=N1 → N, N → ND | D, D → 0 | 1 | 2
規範推導
N1 =>N=>ND=>N2=>D2=>12
則有規範歸約
12=>·D2=>·N2=>·ND=>·N=>·N1
遞歸規則與文法的遞歸性
遞歸規則:所謂遞歸規則,是指在規則的左部和右部具有相同的非終結符的規則。
如果文法中有規則 A→A... 稱爲規則左遞歸
如果文法中有規則 A→...A 稱爲規則右遞歸
如果文法中有規則 A→...A... 稱爲規則遞歸
文法的遞歸性:文法的遞歸性,是指對文法中任一非終結符,若能建立一個推導過程,在推導所得的符號串中又出現了該非終結符本身,則文法是遞歸的,否則是無遞歸性的。
若文法中有推導 A =>+ A... 稱爲文法左遞歸
若文法中有推導 A =>+ ...A.. 稱爲文法右遞歸
若文法中有推導 A =>+ ...A... 稱爲文法遞歸
文法中使用遞歸規則,使得能用有限的規則去定義無窮集合的語言。
文法中有如下規則:
U →Vx
V →Uy | z
顯然規則都不是遞歸規則,
但 U =>+ Uyx,則該文法是左遞歸的。
考慮文法 G[A]:
A → aB | bB
B → a | b
該文法無遞歸性,由它描述的語言是有窮的。L(G[A]) = {aa,ab,ba,bb}
- 文法中使用了遞歸規則,使得可用有限的規則去刻畫無窮集合的語言。
- 若不用遞歸規則來定義文法,需要用無窮多條規則去表示無窮集合的語言
- 當一個語言是無窮集合時,則定義該語言的文法一定是遞歸的。
- 程序設計語言都是無窮集合,因此描述它們的文法必定是遞歸的。
短語、直接短語和句柄
令 G 是一個文法,S 是文法的開始符號,假定αβδ是文法 G 的一個句型,如果是
S =>* αAδ 且 A =>+ β
則稱 β 是相對於非終結符 A 的句型 αβδ 的短語。
特別是,如果有
S =>* αAδ 且 A => β
則稱β是直接短語(簡單短語)。
短語是句型的一部分。
一個句型的最左直接短語稱爲該句型的句柄。
句柄特徵:
(1)它是直接短語,即某規則右部
(2)它具有最左性。
短語、直接短語和句柄都是針對某一句型的,特指句型中的哪些符號串能構成短語和直接短語,離開具體的句型來談短語、直接短語和句柄是無意義的。.
設有文法G[S]=({S,A,B},{a,b},P,S) S →AB A →Aa | bB B →a|Sb 求句型 baSb 的全部短語、直接短語和句柄
根據短語定義,可以從句型的推導過程中找出其全部短語、直接短語和句柄。建立句型的推導過程:
S=>AB=>bBB=>baB=>baSb 最左推導
S=>AB=>ASb=>bBSb=>baSb 最右推導
語法樹/推導樹
對句型的推導過程給出一種圖形表示,這種圖形表示稱爲語法樹,也稱推導樹。設文法 G=(,,S,P),對 G 的任何句型都能構造與之關聯的、滿足下列條件的一棵語法樹。
- 每個結點都有一個標記,此標記是V=∪∪{}中的一個符號。樹
- 根的標記是文法的開始符號 S。
- 若某一結點至少有一個分支結點,則該結點上的標記一定是非終結符。
- 若 A 的結點有 k 個分支結點,其分支結點的標記分別爲 A1,A2,…Ak,則 A→A1A2…Ak一定是G的一條規則
【例】設有文法 G[E] = ({E,T,F},{i,+,-,*,/,(,)},P,E)
其中P 爲E → E+T | E-T | T; T → T*F | T/F |F; F → (E) | i
根據推導,畫出句型 (i+i)*i-i 的語法樹
語法樹的構造是從文法的開始符號出發,構造一個推導的過程,因爲文法的每一個句型(句子)都存在一個推導,所以文法的每個句型(句子)都有一棵對應的語法樹。
句型 (i+i)*i-i 的最左、最右推導得到的語法樹完全相同,也就是說,一棵語法樹表示一個句型的種種可能的(但未必是所有的)不同推導過程。
子樹:語法樹的子樹是由某一個結點連同所有分支組成的部分。
簡單子樹:語法樹的簡單子樹是指只有單層分支的子樹。
根據子樹的概念,句型的短語、直接短語和句柄的直觀解釋如下:
短語:子樹的末端結點形成的符號串是相對於子樹根的短語。
直接短語:簡單子樹的末端結點形成的符號串是相對於簡單子樹根的直接短語。
句柄:最左簡單子樹的末端結點形成的符號串是句柄。
因此可以由子樹以及子樹的末端節點直接看出短語、直接短語與句柄
文法的二義性
如果一個文法存在某個句子對應兩棵不同的語法樹,則稱這個文法是二義的。也就是說,若一個文法存在某個句子,它有兩個不同的最左推導或有兩個不同的最右推導,則稱這個文法是二義的
二義性的文法將給編譯程序的執行帶來問題。對於二義性文法的句子,當編譯程序對它的結構進行語法分析時,就會產生兩種甚至多種不同的理解。語法結構上的不確定性,必將導致語義處理上的不確定性。
解決二義性問題:構造一個等價的無二義性文法;即排除二義性的規則,改寫原有的文法。
在改造文法的過程中,觀察到推導步驟中的規律:靠前的推導,所用規則結合性弱;語法樹上層次高;靠後的推導,所用規則結合性強,語法樹上層次低。
也就是說,想要讓一個規則結合性弱;就讓它出現在推導序列前面(語法樹的上層);想要讓一個規則結合性強;就讓它出現在推導序列後面(語法樹的下層),對於這樣的強弱規律正好對應於運算的優先級規律,因此將運算符的優先順序和結合規則,融合到原有文法中,可構造出無二義性文法
【例】對於文法 G<E>:E → E + E | E﹡E | (E) |i
按照終結符優先級的規律,可以構造出無二義性文法 G’[E] 如下:
E → E + T | T
T → T * F | F
F → (E) | i
改造之後的語法樹就變爲了:
文法種類
2 型文法(上下文無關文法)
若文法 G=(,,S,P)中的每條規則 A → β,其中 A∈,β∈(∪)*,則稱 G 是 2 型文法,2 型文法描述的語言是 2型語言
由定義可見,利用規則將 A 替換成 β 時,與 A 的上下文環境無關,即無需考慮 A 在上下文中出現的情況。故又稱爲上下文無關文法,相應的語言稱爲上下文無關語言。
通常定義程序設計語言的文法是上下文無關文法。
3 型文法(正規文法)
右線形文法:若文法G=(,,S,P)中的每條規則A → αB 或 A → α,其中 A,B∈,α∈,則稱 G 是右線形文法。
左線形文法:若文法G=(,,S,P)中的每條規則A → Bα 或 A → α,其中 A,B∈,α∈,則稱 G 是左線形文法。
右線形文法和左線形文法都稱爲 3 型文法或正規文法,3型文法描述的語言稱爲 3 型語言或正規語言。通常定義程序設計語言詞法規則的文法是正規文法。