編譯SLR
① 編譯原理筆記17:自下而上語法分析(4)LR(0)、SLR(1) 分析表的構造
(移進項目就是指圓點右邊是終結符的項目,規約項目指的就是圓點在右部最右端的項目)
LR(0) 文法可以直接通過識別活前綴的 DFA 來構造 LR 分析表
假定 C = {I 0 , I 1 , ... , I n } (aka. LR(0) 項目規范族、DFA 狀態集)
首先為文法產生式進行編號,拓廣文法的產生式要標記為 0(這里就是後面分析表中 rj 的產生式編號 j 的由來)
然後令每個項目集 I k 的下標 k 作為分析器的狀態(行首),包含 S' → .S 的集合下標為分析器的初態(也就是 DFA 的初態,一般都是 0 )。
下面用一個例子來說明 ACTION、GOTO 子表的構造:
SLR(1) 為解決沖突提出了一個簡單的方法:通過識別活前綴的 DFA 和【簡單向前看一個終結符】構造 SLR(1) 分析表。
如果我們的識別活前綴的 DFA 中存在移進-規約沖突、規約-規約沖突,都可以嘗試使用這個方法來解決沖突。(這里說【嘗試】,當然是因為 SLR 也只能解決一部分問題,並不是萬能的靈丹妙葯。。)
這里,我們拿前面那個 LR(0) 解決不了的文法來舉例
該文法不是 LR(0) 文法,但是是 SLR(1) 文法。
觀察上圖 DFA 中的狀態2,想像當我們的自動機正處於這個狀態:次棧頂已經規約為 T 了,棧頂也是當前的狀態 2 ,而當前剩餘輸入為 *。
如果這個自動機不會【往前多看一步】的話,那麼對處於這個狀態的自動機來說,看起來狀態 2 中的移進項目和規約項目都是可選的。這就是移進-規約沖突。
想要解決這個沖突,就輪到【往前多看一步】上場了——把當前剩餘輸入考慮進來,輔助進行項目的選擇:
對其他的沖突也使用同樣的方法進行判斷。
這種沖突性動作的解決辦法叫做 SLR(1) 解決辦法
准備工作部分,與 LR(0) 分析表的構造差不多:同樣使用每個項目集的狀態編號作為分析器的狀態編號,也就同樣用作行下標;同樣使用拓廣文法產生式作為 0 號產生式。
填表也和 LR(0) 類似,唯一的不同體現在對規約項的處理方法上:如果當前狀態有項目 A → α.aβ 和 A → α. ,而次棧頂此時是 α 且讀寫頭讀到的是 a,那麼當且僅當 a∈FOLLOW(A) 時,我們才會用 A → α 對 α 進行規約。
如果構造出來的表的每個入口都不含多重定義(也就是如上圖中表格那樣的,每個格子裡面最多隻有一個動作),那麼該表就是該文法的 SLR(1) 表,這個文法就是 SLR(1) 文法。使用 SLR(1) 表的分析器叫做一個 SLR(1) 分析器。
任意的二義文法都不能構造出 SLR(1) 分析表
例:懸空 else
例:
這里的 L 可以理解為左值,R 可以理解為右值
經過計算可以確定其 DFA 如下圖所示。
在 狀態4 中,由於 "=" 同時存在於 FOLLOW(L) 與 FOLLOW(R) 中,因此該狀態內存在移進-規約沖突,故該文法不是 SLR(1) 文法。
這樣的非二義文法可以通過增加向前看終結符的個數來解決沖突(比如LL(2)、LR(2))但這會讓問題更加復雜,故一般不採用。而二義文法無論向前看多少個終結符都無法解決二義性。
② 編譯原理LR分析法中的SLR(1)分析表和LR分析過程、語法樹怎麼求
第二題和第三題拿去,剛做的:
由B->cAa|c就可知該文法不是LR(0)文法了
③ 編譯原理怎麼判斷是否為slr文法
LL(1)就是向前只搜索1個符號,即與FIRST()匹配,如果FIRST為空則還要考慮FELLOW.
LR需要構造一張LR分析表,此表用於當面臨輸入字元時,將它移進,規約(即自下而上分析思想),接受還是出錯.
LR(0)找出句柄前綴,構造分析表,然後根據輸入符號進行規約.
SLR(1)使用LR(0)時若有沖突,不知道規約,移進,活移進哪一個,所以需要向前搜索,則只把有問題的地方向前搜索一次.
LR(1)1.在每個項目中增加搜索符.2.舉個列子如有A->α.Bβ,則還需將B的規則也加入.
LALR(1)就是假如兩個產生式集相同則將它們合並為一個,幾合並同心集.
④ 編譯原理用C語言實現基於LR(1)或SLR(1)語法分析程序代碼,最好還有報告,急。。。
這個是精簡的語法分析程序,如果符合的話,hi我
給你實驗報告
#include <stdio.h>
#include<dos.h>
#include<stdlib.h>
#include<string.h>
char a[50] ,b[50];
char ch;
int n1,i1=0,n=5;
int E();int T();int E1();int T1();int F();
void main() /*遞歸分析*/
{
int f,j=0;
printf("請輸入字元串(長度<50,以#號結束)\n");
do{
scanf("%c",&ch);
a[j]=ch;
j++;
}while(ch!='#');
n1=j;
ch=b[0]=a[0];
f=E();
if (f==0) return;
if (ch=='#') printf("accept\n");
else printf("error\n");
}
int E() // E→TE'
{ int f,t;
f=T();
if (f==0) return(0);
t=E1();
if (t==0) return(0);
else return(1);
}
int T() // T→FT'
{ int f,t;
f=F();
if (f==0) return(0);
t=T1();
if (t==0) return(0);
else return(1);
}
int E1()/*E』*/ // E'→+TE'
{ int f;
if(ch=='+') {
b[i1]=ch;
ch=a[++i1];
f=T();
if (f==0) return(0);
E1();
return(1);
}
return(1);
}
int T1()/*T』*/ // T'→*FT'
{
int f,t;
if(ch=='*') {
b[i1]=ch;
ch=a[++i1];
f=F();
if (f==0) return(0);
t=T1();
if (t==0) return(0);
else return(1);}
a[i1]=ch;
return(1);
}
int F() // F→(E)
{ int f;
if(ch=='(') {
b[i1]=ch;
ch=a[++i1];
f=E();
if (f==0) return(0);
if(ch==')') {
b[i1]=ch;
ch=a[++i1];
}
else {
printf("error\n");
return(0);
}
}
else if(ch=='i') {
b[i1]=ch;
ch=a[++i1];
}
else {printf("error\n");return(0);}
return(1);
}
⑤ C語言的SLR(1)分析表
編譯原理 還是SLR 哎 最頭疼這個
寫個LL(1)都花了 3天 盡是些小問題
書上都有演算法 自己看吧
⑥ SLR語法分析器的Java實現
沒有實際利益的不說
⑦ slr的「單反相機」縮寫
單鏡頭反光相機(Single Lens Reflex,縮寫為SLR),也被簡稱為「單反」或「單反相機」。詳見網路詞條:單鏡頭反光相機
SLR(Satellite Laser Ranging,縮寫為SLR),即衛星激光測距,利用安置在地面上的衛星激光測距系統發射的激光脈沖,跟蹤裝有激光反射棱鏡的人造地球衛星,以測定站星距離的技術和方法。
編譯技術裡面的一種語法分析技術
SLR又一個意思是編譯技術裡面的一種語法分析技術,又叫簡單的LR分析技術,而LR分析技術是一種高效的、自下而上的分析一大類上下文無關文法的分析技術。L是指從左向右掃描,R是指構造最右推導的逆。
⑧ 編譯原理,構造SLR分析表時,產生式中出現F的星閉包該怎麼處理
仔細分析你的文法
F->F*|a|b也就是說,寫成正則表達式的話 F就是[ab]*
同樣的T也是[ab]*
你的整個文法就是[ab]+ [ab\+]*第一個+是+closure,第二個+是符號+,所以用了\符號
個人感覺這個文法是有問題的,因為根本不需要用上下文無關文法表達,只需要正則表達式就可以了。
⑨ 編譯器筆記14-語法分析-SLR分析
當在狀態2時輸入符號為 * 時候,可以採取移入操作也可以採取歸約操作。那到底選用哪一個操作呢?歸根結底還是一個如何識別句柄的問題。如果棧頂的T為句柄的話就使用歸約操作,否則的話就不能使用歸約操作。由此可見LR(0)的信息已經不能幫助我們確定是否進行歸約。
事實上LR(0)分析在構造時,向前查看了零個符號,也就是沒有向前查看符號,即沒有考慮文法符號的上下環境。
上圖例子中狀態2在下一個符號是*時,如果把棧頂的T歸約成E。由上圖可知 * 不在FOLLOW(E)中,所以即便歸約成E,E後也不可能跟 * ,所以不應該歸約,T不是句柄。由此可見FOLLOW集可以幫助判斷在哪些情況下不能進行歸約,這也是SLR分析法的基本思想。
解決LR(0)文法的移入歸約沖突,其實就是加強對文法的約束以避免沖突,其實分析方法中並沒因此做出任何改變。
如果給定文法的SLR分析表中不存在有沖突的動作,那麼該文法成為SLR文法。
由上圖可知當狀態2遇到等號時遇到了移入歸約沖突。某些情況下僅利用FOLLOW集的信息去化解沖突是不夠的。為了消解這種沖突需要使用更強大的 LR(1)分析法 。