[XJTUSE编译原理]第四章 语法分析——自上而下分析
文章目錄
- 第四章 語(yǔ)法分析——自上而下分析
- 語(yǔ)法分析的任務(wù)與分類
- 自上而下分析面臨的問(wèn)題
- 自上而下分析的問(wèn)題如何解決
- 區(qū)分三種類型的左遞歸
- 直接左遞歸的消除
- 間接和潛在左遞歸的消除
- 消除一個(gè)文法一切左遞歸的算法
- 消除回溯、提左因子
- 遞歸下降分析程序構(gòu)造
- 預(yù)測(cè)分析程序
- 預(yù)測(cè)分析程序的工作過(guò)程
- 預(yù)測(cè)分析程序有四部分
- 分析程序的動(dòng)作
- 分析表格式
- 舉例說(shuō)明
- 分析表的構(gòu)造[考點(diǎn)]
- ?舉例1?
- ?舉例2?
- LL(1)文法
- LL(1)文法
- LL(1)文法的條件
- 參考資料
第四章 語(yǔ)法分析——自上而下分析
語(yǔ)法分析的前提
對(duì)語(yǔ)言的語(yǔ)法結(jié)構(gòu)進(jìn)行描述
采用正規(guī)式和有限自動(dòng)機(jī)描述和識(shí)別語(yǔ)言的單詞符號(hào)
用上下文無(wú)關(guān)文法來(lái)描述語(yǔ)法規(guī)則
語(yǔ)法分析的任務(wù):分析一個(gè)文法的句子的結(jié)構(gòu)
語(yǔ)法分析器的功能:按照文法的產(chǎn)生式(語(yǔ)言的語(yǔ)法規(guī)則),識(shí)別輸入符號(hào)串是否為一個(gè)句子(合式程序)
語(yǔ)法分析的方法
1?? 自上而下Top-down
從文法的開(kāi)始符號(hào)出發(fā),反復(fù)使用各種產(chǎn)生式,尋找"匹配"的推導(dǎo)
推導(dǎo):根據(jù)文法的產(chǎn)生式規(guī)則,把串中出現(xiàn)的產(chǎn)生式的左部符號(hào)替換成右部
從樹(shù)的根開(kāi)始,構(gòu)造語(yǔ)法
遞歸下降分析法、預(yù)測(cè)分析程序
2?? 自下而上Bottom-up
從輸入串開(kāi)始, 逐步進(jìn)行歸約,直到文法的開(kāi)始符
歸約:根據(jù)文法的產(chǎn)生式規(guī)則,把串中出現(xiàn)的產(chǎn)生式的右部替換成左部符號(hào)
從樹(shù)葉節(jié)點(diǎn)開(kāi)始,構(gòu)造語(yǔ)法樹(shù)
算符優(yōu)先分析法、LR分析法
語(yǔ)法分析的任務(wù)與分類
語(yǔ)法分析的任務(wù):對(duì)任一給定w∈VT?,判斷w∈L(G)對(duì)任一給定w\in V_T^*,判斷w\in L(G)對(duì)任一給定w∈VT??,判斷w∈L(G)
w表示終結(jié)符串
句子的全體是一個(gè)語(yǔ)言,記作L(G)
語(yǔ)法分析器是一個(gè)程序,它按照P,做識(shí)別w的工作
自上而下分析面臨的問(wèn)題
主旨:從文法開(kāi)始符號(hào)出發(fā),自上而下地為輸入串建立一棵語(yǔ)法樹(shù)。
舉例:文法G1: S -> cAd A -> ab|a,輸入串:w=cad,為它建立語(yǔ)法樹(shù)
上述分析方法的實(shí)現(xiàn):
1?? 每一非終結(jié)符對(duì)應(yīng)一個(gè)遞歸子程序,在只生成兩個(gè)串的文法中過(guò)程無(wú)須遞歸;但是,對(duì)于生成無(wú)數(shù)個(gè)串的文法而言,遞歸不可避免。
2?? 遞歸子程序是一個(gè)布爾過(guò)程,一旦它發(fā)現(xiàn)自己的某個(gè)候選式與輸入串匹配,它就按此式擴(kuò)充語(yǔ)法樹(shù),返回true,指針移過(guò)已匹配子串;否則,返回false,保持原來(lái)的語(yǔ)法樹(shù)和指針不變。
程序?qū)崿F(xiàn)
使用兩個(gè)過(guò)程: S()和A(), 它們送回true or false,決定于它們是否在輸入串中找到相應(yīng)的終結(jié)符所構(gòu)成的串。
使用記號(hào)
input_ symbol:當(dāng)前符號(hào)內(nèi)容
input_ pointer: 輸入字符指針
使用過(guò)程
ADVANCE():把input_ pointer移 到下一輸入符號(hào)位置,置input_symbol是當(dāng)前符號(hào)內(nèi)容。
procedure S(); begin if input_symbol = 'c' thenbeginADVANCE();if A() then//A擴(kuò)展if input_symbol = 'd'then beginADVANCE();//指針后移return true;end;end;return false; end;procedure A(); beginisave := input_pointer;//記錄輸入指針,防止回滾if input_symbol = 'a' thenbeginADVANCE();if input_symbol = 'b' thenbeginADVANCE();return true;end;end; /* 匹配ab失敗,則匹配a*/input_pointer := isave//將之前記錄的輸入指針賦值給輸入指針if input_symbol = 'a' thenbeginADVANCE();return true;end;elsereturn false; end;困難和問(wèn)題
- 文法的左遞歸
- 回溯
- 使用候選式的順序會(huì)影響所接受的語(yǔ)言: 如: A -> ab|a改為A->a|ab
- 難以報(bào)告出錯(cuò)的確切位置
- 窮舉試探法一 低效的分析方法
自上而下分析的問(wèn)題如何解決
消除文法左遞歸以及回溯問(wèn)題
區(qū)分三種類型的左遞歸
1?? 直接左遞歸
形如:N->Nα
2?? 間接左遞歸
形如:N->Aα A->Bβ B->Nγ
3?? 潛在左遞歸
形如:N->α N β,而α?+ε\alpha\overset{+}{\Rightarrow}εα?+ε
直接左遞歸的消除
候選式:A->Aα|β,可以得到文法符號(hào)串:βα、βαα、βααα……
? A->βA’ A’->α A’|ε,也可以得到文法符號(hào)串:βα、βαα、βααα……
一般化可以得到直接左遞歸的消除方法
若:A->Aα|β,其中β不以A開(kāi)頭,則修改規(guī)則為A->βA’ A’->α A’|ε
可以進(jìn)行推廣:假定P的全部產(chǎn)生式為
P→Pα1∣Pα2∣...∣Pαm∣β1∣β2∣...∣βnP\rightarrow P\alpha_1|P\alpha_2|...|P\alpha_m|\beta_1|\beta_2|...|\beta_n P→Pα1?∣Pα2?∣...∣Pαm?∣β1?∣β2?∣...∣βn?
每個(gè)α都不等于ε,每個(gè)β都不以P開(kāi)頭
則將左遞歸變?yōu)橛疫f歸如下
P→β1P′∣β2P′∣...∣βnP′P′→α1P′∣α2P′∣...∣αmP′∣εP\rightarrow\beta_1P'|\beta_2P'|...|\beta_nP'\\ P'\rightarrow\alpha_1P'|\alpha_2P'|...|\alpha_mP'|ε P→β1?P′∣β2?P′∣...∣βn?P′P′→α1?P′∣α2?P′∣...∣αm?P′∣ε
舉例:文法:E->E+T|T T->T*F|F F->(E)|i
消除直接左遞歸后
E->TE’
E’->+TE’|ε
T->FT’
T’->*FT’|ε
F->(E)|i
間接和潛在左遞歸的消除
一個(gè)文法消除左遞歸的條件:不含以ε為右部的產(chǎn)生式;不含回路P?+PP\overset{+}{\Rightarrow}PP?+P
代入法
將一個(gè)產(chǎn)生式規(guī)則右部的a中的非終結(jié)符N替換為“N的候選式”。如果N有n個(gè)候選式,則右邊的a重復(fù)n次,而且每一次重復(fù)都用N的不同候選式來(lái)代替N。
舉例:(改寫之后的)N->a|Bc|ε在S->pNq中的代入結(jié)果:S->paq|pBcq|pq
消除一個(gè)文法一切左遞歸的算法
1?? 對(duì)文法G的所有非終結(jié)符進(jìn)行排序;
2?? 按上述順序?qū)γ恳粋€(gè)非終結(jié)符Pi依次執(zhí)行:
for(j=1;j< i-1;j++)將Pj代入Pi的產(chǎn)生式(若可代入的話); 消除關(guān)于Pi的直接左遞歸;3?? 化簡(jiǎn)上述所得文法。
舉例
對(duì)于文法:S->Qc|c Q->Rb|b R->Sa|a
雖然沒(méi)有直接左遞歸,但是S,Q,R都是左遞歸的,比如有S=>Qc=>Rbc=>Sabc
1?? 將非終結(jié)符排序?yàn)?#xff1a;R、Q、S
2?? 對(duì)于R,不存在直接左遞歸,將R帶入到Q的有關(guān)候選后,我們把Q的規(guī)則變?yōu)镼->Sab|ab|b
現(xiàn)在的Q同樣不含有直接左遞歸,把它帶入到S的有關(guān)候選后,S變?yōu)镾->Sabc|abc|bc|c,消除S的直接左遞歸,可以得到整個(gè)文法
S->abcS’|bcS’|cS’
S’->abcS’|ε
Q->Sab|ab|b
R->Sa|a
其中Q和R的規(guī)則已經(jīng)多余,化簡(jiǎn)以后可以得到
S->abcS’|bcS’|cS’
S’->abcS’|ε
由于排序不同,最后得到的文法在形式上可能不一樣,但是都是等價(jià)的
消除回溯、提左因子
回溯原因
若當(dāng)前符號(hào) = a,對(duì) A 展開(kāi),而 A -> α1|α2|…|αm那么,要知道哪一個(gè)αi是獲得以a開(kāi)頭的串的唯一替換式。
即:選擇哪一個(gè)αi,亦即通過(guò)查看第一個(gè)(當(dāng)前)符號(hào)來(lái)發(fā)現(xiàn)合適的替換式α。
如何選擇αi?
以a為開(kāi)頭的αi
如果有多個(gè)αi以a開(kāi)頭,則這是文法的問(wèn)題
舉例
有產(chǎn)生式
語(yǔ)句->if 條件 then 語(yǔ)句 else 語(yǔ)句|while 條件 do 語(yǔ)句|begin 語(yǔ)句表 end
若要尋找一個(gè)語(yǔ)句,那么關(guān)鍵字if,while,begin就提示我們哪一個(gè)替換式是最右可能成功的替換式
若要求不得回溯,文法G(不含有左遞歸)的必要條件是什么?
若由αi?+a...\alpha_i\overset{+}{\Rightarrow}a...αi??+a...(某個(gè)文法符號(hào)串經(jīng)過(guò)若干步推導(dǎo)可以得到以a(終結(jié)符)開(kāi)頭的串),選該αi必中,但若αj?+a...\alpha_j\overset{+}{\Rightarrow}a...αj??+a...,就會(huì)導(dǎo)致無(wú)法百發(fā)百中。解決辦法是對(duì)文法本身提出要求:不要出現(xiàn)以上情況”。把上述要求闡明清楚可以采用如下定義的FIRST(α),即α的首符集。由于空串的存在,不能稱為首終結(jié)符集。
首符集定義FIRST(α)
FIRST(α)={a∣α??a…,a∈VT}ifα??ε,defineε∈FIRST(α)FIRST(\alpha)=\{a|\alpha\overset{*}{\Rightarrow}a…,a\in V_T\}\\ if\ \alpha\overset{*}{\Rightarrow}ε,define\ ε\in FIRST(\alpha) FIRST(α)={a∣α??a…,a∈VT?}if?α??ε,define?ε∈FIRST(α)
定理
若一個(gè)A∈VNA∈V_NA∈VN?有許多FIRST(αi)FIRST(\alpha_i)FIRST(αi?)。如果A的任何兩個(gè)候選式αi\alpha_iαi?和αj\alpha_jαj?之間均滿足
FIRST(αi)∩FIRST(αj)=?FIRST(\alpha_i)\cap FIRST(\alpha_j)=\empty FIRST(αi?)∩FIRST(αj?)=?
意味著,A的每一候選式α推導(dǎo)后所得的字符串第一個(gè)VTV_TVT?均不同。
于是,對(duì)輸入符號(hào)α,如果α∈FIRST(αi), 則α not∈FIRST(αj), (j≠i)。因此,對(duì)A的展開(kāi)無(wú)疑應(yīng)選候選式αi,否則無(wú)法命中。
消除回溯目的
使非終結(jié)符A所有候選式的首符集兩兩不相交
方法:提取公共因子
若:A?>δβ1∣δβ2∣...∣δβn∣γ1∣γ2∣...∣γmA->\delta \beta_1|\delta \beta_2|...|\delta \beta_n|γ_1|γ_2|...|γ_mA?>δβ1?∣δβ2?∣...∣δβn?∣γ1?∣γ2?∣...∣γm?,其中每個(gè)γ不以δ開(kāi)頭
那么可以把這些規(guī)則改寫成
A→δA′∣γ1∣γ2∣...∣γmA′→β1∣β2∣...∣βnA\rightarrow \delta A'|γ_1|γ_2|...|γ_m\\ A'\rightarrow \beta_1|\beta_2|...|\beta_n A→δA′∣γ1?∣γ2?∣...∣γm?A′→β1?∣β2?∣...∣βn?
遞歸下降分析程序構(gòu)造
在不含左遞歸和每個(gè)非終結(jié)符的所有候選式的首符集都兩兩不相交條件下,構(gòu)造一個(gè)不帶回溯的自上而下分析程序,該分析程序由一組遞歸過(guò)程組成,每個(gè)過(guò)程對(duì)應(yīng)文法的一個(gè)非終結(jié)符。這樣的一個(gè)分析程序稱為遞歸下降分析器。
舉例
文法G:
E->TE’
E’=>+TE’|ε
T->FT’
T’->*FT’|ε
F->(E)|i
每個(gè)非終結(jié)符對(duì)應(yīng)的遞歸子程序如下:
面臨輸入:i1+i2*i3的分析步驟如下
構(gòu)造語(yǔ)法樹(shù)時(shí),注意點(diǎn)
有ε,自動(dòng)匹配,不會(huì)失敗
無(wú)成功/失敗消息返回
出錯(cuò)位置不確切
構(gòu)造遞歸下降分析程序時(shí),它由一組遞歸過(guò)程組成。每個(gè)遞歸過(guò)程對(duì)應(yīng)文法的一個(gè)非終結(jié)符。
預(yù)測(cè)分析程序
? 問(wèn)題:
用遞歸子程序描寫遞歸下降分析器,要求實(shí)現(xiàn)該編譯程序的語(yǔ)言(高級(jí)或匯編)允許遞歸。
🚗 改進(jìn):
使用一張分析表和一個(gè)棧同樣可實(shí)現(xiàn)遞歸下降分析。用這種方法實(shí)現(xiàn)的語(yǔ)法分析程序叫預(yù)測(cè)分析程序。
預(yù)測(cè)分析程序的工作過(guò)程
預(yù)測(cè)分析表事先已經(jīng)準(zhǔn)備好了。
預(yù)測(cè)分析程序有四部分
1?? 一個(gè)輸入:含有要分析的終結(jié)符串,右端有#。
2?? 一個(gè)棧:棧底是#,棧內(nèi)是一系列文法符號(hào);開(kāi)始時(shí),#和S先進(jìn)棧。
3?? 分析表:二維數(shù)組M[A, a], 其中a∈VT;A∈VNa∈V_T; A\in V_Na∈VT?;A∈VN?,#要占一列,多了一列
4?? 輸出:根據(jù)分析表內(nèi)元素做規(guī)定的語(yǔ)法分析動(dòng)作。
分析程序的動(dòng)作
程序測(cè)定棧頂符號(hào)X和當(dāng)前輸入符號(hào)a,由(X, a)決定程序動(dòng)作,三種可能:
1?? 若X=a=#,分析停止,宣告成功地完成分析;
2?? 若X=a≠#,則X彈出棧,前移輸入指針;
3?? 若X∈VNX∈V_NX∈VN?,則去查分析表M的元素M[X,a],該元素或?yàn)閄的產(chǎn)生式,或?yàn)橐粋€(gè)出錯(cuò)元素。
對(duì)第3)條,X∈VNX∈V_NX∈VN?,查分析表M的元素M[X, a]后
如:M[X,a]={X->UVV},就用WVU(U在頂)替換棧頂?shù)腦;
如: M[X, a]=error,則調(diào)用error程序。
分析表格式
文法G:
E->TE’
E’=>+TE’|ε
T->FT’
T’->*FT’|ε
F->(E)|i
| E | E->TE’ | E->TE’ | ||||
| E’ | E’->TE’ | E’->ε | E’->ε | |||
| T | T->FT’ | T->FT’ | ||||
| T’ | T’->ε | T’->*FT’ | T’->ε | T’->ε | ||
| F | F->id | F->(E) |
#(界符)視為特殊的終結(jié)符
所有的行跟非終結(jié)符對(duì)應(yīng),所有的列跟終結(jié)符對(duì)應(yīng)
隱去了出錯(cuò)處理
舉例說(shuō)明
按照預(yù)測(cè)分析程序,對(duì)于輸入id+id*id所作
結(jié)論
①輸出的產(chǎn)生式就是最左推導(dǎo)的產(chǎn)生式。棧中放右部,等待與α匹配;
②分析表中出現(xiàn)(棧頂,a)時(shí),指出如何擴(kuò)充樹(shù),并且能馬上發(fā)現(xiàn)錯(cuò)誤。
實(shí)質(zhì)
棧:殘缺規(guī)范句型
表:指出VNV_NVN?按哪一條擴(kuò)充,依賴于VTV_TVT?
分析表的構(gòu)造[考點(diǎn)]
按照α???\alpha\overset{*}{\Rightarrow}?α???將產(chǎn)生式分成兩種
α??a……\alpha\overset{*}{\Rightarrow}a……α??a……
α??ε\alpha\overset{*}{\Rightarrow}εα??ε
先要構(gòu)造兩個(gè)與G有關(guān)的集合:FIRST(α)首符集和FOLLOW(A)后繼符集(跟在非終結(jié)符A后面的終結(jié)符)
1?? 定義:對(duì)于文法G,α∈V?\alpha\in V*α∈V?,S、A∈VN\in V_N∈VN?
KaTeX parse error: No such environment: align at position 8: \begin{?a?l?i?g?n?}? &\text{FIRST}(…
2?? 構(gòu)造FIRST(α)
🍎 對(duì)于單符號(hào):先構(gòu)造FIRST(X),X∈VT∪VNFIRST(X),X∈V_T\cup V_NFIRST(X),X∈VT?∪VN?
連續(xù)應(yīng)用以下規(guī)則,直到再無(wú)終結(jié)符或ε加入任一FIRST集為止
① 若X∈VTX\in V_TX∈VT?,則FIRST(X)={X}
② 若X∈VN,且X→aαX\in V_N,且X\rightarrow a\alphaX∈VN?,且X→aα,則{a}∪FIRST(X);若X∈VN,且X→εX\in V_N,且X\rightarrow εX∈VN?,且X→ε,則{ε}∪FIRST(X)
③ 若X∈VN,且X→Y…,Y∈VNX\in V_N,且X\rightarrow Y…,Y\in V_NX∈VN?,且X→Y…,Y∈VN?,則FIRST(Y)\{ε}∪FIRST(X);若X→Y1Y2…Yk,Y1,...,Yi?1∈VNX\rightarrow Y_1Y_2…Y_k,Y_1,...,Y_{i-1}\in V_NX→Y1?Y2?…Yk?,Y1?,...,Yi?1?∈VN?是一個(gè)產(chǎn)生式,而且對(duì)于任何j,1≤j≤i?11\le j\le i-11≤j≤i?1,FIRST(Yj)FIRST(Y_j)FIRST(Yj?)中都含有ε,即Y1...Yi?1??εY_1...Y_{i-1}\overset{*}{\Rightarrow}εY1?...Yi?1???ε,則把FIRST(Yi)FIRST(Y_i)FIRST(Yi?)中的所有非ε元素加入到FIRST(X)中;如果所有的FIRST(Yj),j=1,2,...,kFIRST(Y_j),j=1,2,...,kFIRST(Yj?),j=1,2,...,k都有ε,則把ε也加入FIRST(X)
所有的非終結(jié)符最后都會(huì)變成終結(jié)符串
🍎 對(duì)于符號(hào)串:再進(jìn)而構(gòu)造FIRST(X1X2...Xn)即FIRST(α)FIRST(X_1X_2...X_n)即FIRST(\alpha)FIRST(X1?X2?...Xn?)即FIRST(α)
① FIRST(X1)FIRST(X_1)FIRST(X1?)的非ε終結(jié)符加入FIRST(α)FIRST(\alpha)FIRST(α)
② 若ε∈FIRST(X1)ε\in FIRST(X_1)ε∈FIRST(X1?),則FIRST(X2)FIRST(X_2)FIRST(X2?)的所有非ε終結(jié)符加入FIRST(α)FIRST(\alpha)FIRST(α)
③ 若ε∈FIRST(X1),ε∈FIRST(X2)ε\in FIRST(X_1),ε\in FIRST(X_2)ε∈FIRST(X1?),ε∈FIRST(X2?),則FIRST(X3)FIRST(X_3)FIRST(X3?)的所有非ε終結(jié)符加入FIRST(α)FIRST(\alpha)FIRST(α)
最后,若ε∈FIRST(Xi),i=1,...,nε\in FIRST(X_i),i=1,...,nε∈FIRST(Xi?),i=1,...,n,則{ε}加入FIRST(α)FIRST(\alpha)FIRST(α)
終結(jié)符、非終結(jié)符、文法符號(hào)串、候選式都可以構(gòu)造首符集;后繼符集只能用終結(jié)符定義!
3?? 構(gòu)造FOLLOW(A)
對(duì)于文法G的每個(gè)非終結(jié)符A構(gòu)造FOLLOW(A)的辦法是,連續(xù)使用下面的規(guī)則,直到每個(gè)FOLLOW不再增大為止
① 對(duì)于文法的開(kāi)始符號(hào)S,置#于FOLLOW(S)中——#不能忽視!
② 若A→αBβA\rightarrow \alpha B\betaA→αBβ,則把FIRST(β)\{ε}加入到FOLLOW(B)中
③ 若有A→αBA\rightarrow \alpha BA→αB。或者A→αBβA\rightarrow \alpha B\betaA→αBβ是一個(gè)產(chǎn)生式而B?εB\Rightarrow εB?ε(即ε∈FIRST(β)),則把FOLLOW(A)加入到FOLLOW(B)中
?舉例1?
已知文法G:
E->TE’ T’->*FT’|ε E’->+TE’|ε F->(E)|i T->FT’
求它的FIRST(α),FOLLOW(A)
1?? 構(gòu)造首符集
首先看產(chǎn)生式右邊,如果第一個(gè)符號(hào)是終結(jié)符,則把其加入非終結(jié)符的首符集中,再看一下候選式中有沒(méi)有ε,有的話也加入首符集中,如由F->(E)|i可知FIRST(F)={(,i}FIRST(F)=\{(,i\}FIRST(F)={(,i}
還有一些推到關(guān)系,如T->FT’,E->TE’,則F首符集中非ε的元素也是T中首符集的元素,T首符集中非ε的元素也是E中首符集的元素:FIRST(F)={ ( , i }=FIRST(T)=FIRST(E)
2?? 構(gòu)造非終后繼符集
由法則①:FOLLOW(E)={#}
由法則②
E->TE’,則將 FIRST(E’) \ {ε} 加入 FOLLOW(T):FOLLOW(T)={+}
T->FT’,則將 FIRST(T’) \ {ε} 加入 FOLLOW(F):FOLLOW(F)={*}
F->(E),則將FIRST( ) )加入FOLLOW(E):FOLLOW(E)={ # , ) }
由FISRT①,FIRST( ) )=)
由法則③
E->TE’,將FOLLOW(E)加入到FOLLOW(E’)中:FOLLOW(E’)={ ) , #}}
E->TE’,且E’->ε,則將FOLLOW(E)加入到FOLLOW(T)中:FOLLOW(T)={ + , ) , #}
T->FT’,將FOLLOW(T)加入到FOLLOW(T’)中:FOLLOW(T’)={ + , ) , #}
T->FT’,且T’->ε,將FOLLOW(T)加入到FOLLOW(F)中:FOLLOW(F)={*, + , ) , #}
| FIRST(E)={ ( , i } | FOLLOW(E)={ ) , #} |
| FIRST(E’)={+ , ε} | FOLLOW(E’)={ ) , #}} |
| FIRST(T)={ ( , i } | FOLLOW(T)={ + , ) , #} |
| FIRST(T’)={* , ε} | FOLLOW(T’)={ + , ) , #} |
| FIRST(F)={ ( , i } | FOLLOW(F)={*, + , ) , #} |
4?? 分析表的構(gòu)造
算法:輸入:G1文法,輸出:分析表M
① 對(duì)文法的每一個(gè)A->α,做②和③
② 對(duì)于任一a∈FIRST(α),把A->α加入到M[A,a](可能不止一個(gè))
③ 若ε∈FIRST(α),則把A->α加入M[A,b],b∈FOLLOW(A);若ε∈FIRST(α),#∈FOLLOW(A),則把A->α加進(jìn)M[A,#]
④ 把所有無(wú)定義的M[A,a]標(biāo)上“出錯(cuò)標(biāo)志”
?舉例2?
將算法應(yīng)用于上述文法G:E->TE’ T’->*FT’|ε E’->+TE’|ε F->(E)|i T->FT’
① E->TE’
因?yàn)镕IRST(TE’)=FIRST(T)={(,i)},即產(chǎn)生式E->TE’保證了M[E,i]和M[E, (]中持有E->TE’
所以M[E,(]={E->TE’} M[E,id]={E->TE’}
② E’->+TE’
因?yàn)镕IRST(+TE’)={+},所以M[E’,+]={E’->+TE’}
③ E’->ε
因?yàn)橛笑?#xff0c;需要去看產(chǎn)生式的左部非終結(jié)符的FOLLOW集中有哪些終結(jié)符
FOLLOW(E’)={),#},所以M[E’,)]={E’->ε},M[E’,#]={E’->ε}
最終可以得到如下分析表
| E | E->TE’ | E->TE’ | ||||
| E’ | E’->TE’ | E’->ε | E’->ε | |||
| T | T->FT’ | T->FT’ | ||||
| T’ | T’->ε | T’->*FT’ | T’->ε | T’->ε | ||
| F | F->id | F->(E) |
上述算法可應(yīng)用于任何文法G以構(gòu)造它的分析表M。但對(duì)于某些文法,有些M[A,a]可能持有若干個(gè)產(chǎn)生式,或者說(shuō)有些M[A,a]可能是多重定義的。如果G是左遞歸或二義的,那么,M至少含有一個(gè)多重定義人口。因此,消除左遞歸和提取左因子將有助于獲得無(wú)多重定義的分析表M。
可以證明,一個(gè)文法G的預(yù)測(cè)分析表M不含多重定義入口,當(dāng)且僅當(dāng)該文法為L(zhǎng)L(1)的。
LL(1)文法
LL:第一個(gè)L表示從左到右掃描輸入串;第二個(gè)L表示最左推導(dǎo)
(1):表示分析時(shí)每一步只需要向前查看一個(gè)符號(hào)
LL(1)文法
一個(gè)文法G,若它的分析表M不含多重定義入口(同一個(gè)格子里面有兩個(gè)產(chǎn)生式),則稱它為一個(gè)LL(1)文法
LL(1)文法的條件
文法G式LL(1)的,則對(duì)于G的每一個(gè)非終結(jié)符A的任何兩個(gè)不同產(chǎn)生式A->α|β,有:
1?? FIRST(α)∩FIRST(β)=Φ
2?? 若某一個(gè)候選式β??ε\beta\mathop\Rightarrow\limits ^* εβ??ε,則FIRST(α)∩FOLLOW(A)=Φ
🍌 說(shuō)明
使用LL(1)文法,一定可以實(shí)現(xiàn)不帶回溯的自上而下分析
若某文法G為L(zhǎng)L(1)文法,則下列那些描述正確?
?該文法的預(yù)測(cè)分析表必?zé)o多重入口。
?所有非終結(jié)符各候選式的首符集兩兩之間交集必為空。
?非終結(jié)符的某個(gè)候選式的首符集中有空串時(shí),該非終結(jié)符的后繼符集與其余各個(gè)候選式首符集交集必為空。
但是,條件語(yǔ)句文法不能改造成LL(1)文法
語(yǔ)句->if 條件 then 語(yǔ)句 else 語(yǔ)句|if 條件 then 語(yǔ)句
例如:S->iCtS|iCtSeS|a C->b
提公因子以后,文法變?yōu)镾->iCtSS’|a S’->eS|ε C->b
計(jì)算該文法的FIRST集和FOLLOW集如下:
FIRST(S)={i,a} FIRST(S’)={e,ε} FIRST?={b}
FOLLOW(S)={#,e} FOLLOW(S’)={#,e} FOLLOW?={t}
分析表如下:
| S | S->a | S->iCtSS’ | ||||
| S’ | S’->eS | |||||
| C | C->b |
上表未填滿
對(duì)于候選式S’->ε,因?yàn)棣拧蔉IRST(S’)={e,ε},而FOLLOW(S’)={#,e},所以S’->ε填入M[S’,#]和M[S’,e],有多重入口,不是LL(1)文法
解決:強(qiáng)制令M[S’,e]={S’->eS},即堅(jiān)持將e與最近的t相結(jié)合,從程序語(yǔ)言來(lái)看,相當(dāng)于規(guī)定ELSE堅(jiān)持與最近的THEN相結(jié)合
參考資料
[1] 西安交通大學(xué)軟件工程專業(yè)編譯原理 吳曉軍 2022春
[2] 陳火旺,劉春林,譚慶平,趙克佳,劉越. 程序設(shè)計(jì)語(yǔ)言編譯原理(第3版). 北京:國(guó)防工業(yè)出版社,2010
總結(jié)
以上是生活随笔為你收集整理的[XJTUSE编译原理]第四章 语法分析——自上而下分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 产品需求文档(PRD)札记
- 下一篇: 《把时间当朋友》 第六章交流 读书笔记