A. 編譯原理用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);
}
B. 編譯原理筆記7:語法分析(1)語法分析器的任務、語法錯誤的處理
語法分析器的兩項主要任務,分別:
源程序中的錯誤可以分為詞法/語法錯誤、語義錯誤兩類。前者主要形式是命名不合虛悄雹法、關鍵字書寫錯誤、語法結構有問題(比如缺分號、該配對的東西不配對)等;後者則可分為靜態/動態兩種,靜態例如類型使用錯誤、參數使用錯誤等,動態語義錯誤則是無窮遞歸這類邏輯性的問題。
例如:
緊急恢復:x = a+b+d; // 丟運芹棄掉 b 後的記號,直到遇到 +
短語級恢復: x = a+b; // 加入分號
在寫程序時,要養成減少錯誤的好習慣:每次用變數、參數時,要在使用之前進行初始化,並在差帆直接使用之前檢查一下是否出現值為空等問題,防止出現不可預知的錯誤
C. 編譯原理LR(1)中的R和1分別是什麼意思
優質解答
LR分析法是一種自下而上進行規范歸約的語法分析法,L指從左到右掃描輸入符號串,R是指構造最右推導的逆過程.LR(1)中的1是每次搜索符號需要向前參考一步,即參考下一個符號確定當前構造.
L:Left (左) R:Right (右)
D. 編譯原理——LR分析表
自底向上的語法分析
LR分析表的結構如上,其分為兩個部分 Action Goto
兩個參數狀態i,終結符號a(s(i)代表第i個狀態,r(i)代表第i條表達式)
Goto[i,A]=j
文法
容易得知這個文法可以推出 0 1 00 01 等的字元串。因為它是 左遞歸 。不適用於 LL 文法分析,只能使用 LR 分析。
因為本題入口有兩個—— S → L·L S → L ,所以需要構造額外的產生式 S'->S
2.1 第一次遍歷
我們從 [S -> . L·L] 開始,構造這個狀態的閉包,也就是加上所有能從這個產生式推出的表項。
首先,判斷 . 後面是否為 非終結符號A 。如果是,那我們就得找所有由 A-> 推出的產生式,並將它們添加進入 閉包 里(也就是State包里)。循環做即可。
因此我們可以得到 State 0 有
下一步,就是我的 . 往下一位移動。對每個符號X後有個 . 的項,都可以從 State 0 過渡到其他狀態。
由以上6條式子可以得知下一位符號可以是 S L B 0 1 。所以自然可以得到5個狀態。
State 1 是由 State 0 通過 S 轉移到這里的,所以我們找出所有 State 0 中在 S 前有 . 的項。
此狀態作為結束狀態 Accept ,不需要繼續狀態轉移了。
State 2 是由 State 0 通過 L 轉移到這里的,所以我們找出所有 State 0 中在 L 前有 . 的項。
S -> . L·L S -> . L L -> . LB
有3條式子,現在我們將 . 向後推一格,就得到 State 1 的項了。
但是 . 之後的符號分別是 · $ B , B 為非終結符號,我們得包含 B -> 的項
State 3 是由 State 0 通過 B 轉移到這里的,所以我們找出所有 State 0 中在 B 前有 . 的項。
因為 . 後沒有其他符號了,因此這個狀態不需要繼續轉移了。
State 4 是由 State 0 通過 0 轉移到這里的,所以我們找出所有 State 0 中在 0 前有 . 的項。
因為 . 後沒有其他符號了,因此這個狀態不需要繼續轉移了。
很簡單,同樣的道理找 State 5
State 5 是由 State 0 通過 1 轉移到這里的,所以我們找出所有 State 0 中在 1 前有 . 的項。
因為 . 後沒有其他符號了,因此這個狀態不需要繼續轉移了。
好的,現在我們第一次遍歷完成。
2.2 第二次遍歷
第二次遍歷自然從 State 2 開始。
我們回到 State2 ,可以看出 . 之後的符號有 · B 0 1 。
State 6 是由 State 2 通過 · 轉移到這里的,所以我們找出所有 State 2 中在 · 前有 . 的項。
S -> L. ·L 只有1條,我們往後移發現 L 又為非終結符號,參考 State 0 做的操作,我們得找出所有的式子。
共有5條式子,共同組成 State 6 ,由上面的式子可以看出我們還得繼續下一次遍歷。先不管著,我們進行下一次狀態查找。
State 7 是由 State 2 通過 B 轉移到這里的,所以我們找出所有 State 2 中在 B 前有 . 的項。
L -> L. B 也是只有1條,我們往後移發現沒有非終結符號了,那就不需要再繼續添加其他式子了。
這個狀態也不需要繼續進行轉移了。
接下來很關鍵,因為我們通過 State2 的 . 後的符號找出了 State 6 State 7 ,接下來還差符號 0 1 ,那麼是否像之前一樣按例添加狀態呢, 答案是不是的 ,因為我們發現通過 0 1 找到的閉包集分別是 B -> 0 B -> 1 ,這與我們的之前的 State 4 State 5 相同。所以我們得將其整合起來,相當於 State 2 通過 0 1 符號找到了 State 4 State 5 狀態。
2.3 第三次遍歷
回頭看第二次遍歷,可以看出只有 State 6 可以進行狀態轉移了。
那麼就將 State 6 作為第三次遍歷的源頭,可以看出 . 之後的符號有 L B 0 1 。
State 8 是由 State 6 通過 L 轉移到這里的,所以我們找出所有 State 6 在 L 前有 . 的項。
S -> L· .L L -> . LB 有兩條式子,往後移發現有非終結符號 B ,所以經過整合可以得到
可以看出 . 的後面還有一個符號,所以這里我們還得再進行一次遍歷。
接下來,又是遇到重復的包的情況,可以看出我們由 State 6 通過 B 0 1 得到的閉包分別是 L->B B->0 B->1 ,很明顯,這分別對應於 State 3 State 4 State 5 。
第三次遍歷也就結束了。
2.4 第四次遍歷
回看第三次遍歷,可以看出只有 State 8 可以進行狀態轉移,其 . 之後的符號分別是 B 0 1 。
誒,感覺很熟悉,就是上面幾行剛說的情況,也就是說通過這三個符號找到的閉包是我們之前遇到的狀態,分別是 State 3 State 4 State 5 。
做到這里,我們發現我們已經全部遍歷完畢!
總共有8個狀態,通過以上流程做成個圖是什麼樣子的?來看看!
這么一看就很清晰明了了,我們就可以通過這個圖做出我們的 LR分析表
其實就是我們之前呈現的表
在狀態 I2 和 I8 中,既有 移入 項目,也有 規約 項目,存在 移入 - 規約的沖突 ,所以不是 LR(0) 文法,但是因為 FOLLOW(S) ∩ {0, 1} = ∅,所以可以用 FOLLOW 集解決沖突,所以該文法是 SLR(1) 文法。
上表我們發現還有 r1,r2,r3 等。這個其實就是代表狀態停止轉移時為 第幾條表達式 ,r3代表第三條表達式 L -> LB 。
當我們構建了表之後,我們如何運用起來呢?
下面我們通過一個例子來說明
以上字元串是如何被SLR分析器識別的呢?
E. [高分,急!]編譯原理LR(1)分析表題目
I0: S->.T,# T->.T(T),#
I1: S->T.,# T->T.(T),#
I2: S->T(.T),# T->.T(T),) T->.ε,)
I3: S->T(T.),# T->T.(T),)
(1,() 是s2
(1,#) 是acc (就是接受)
T下1 是1
T下3 是3
F. 編譯原理中LR(1) 那個向前搜索符怎麼求的 跪求高手解答 復制粘貼或者答非所問的別來
1、首先第一步就是項目[S』-> . S,],自動生成搜索符],自動生成搜索符],自動生成搜索符,從項目[A->α.Bβ,?]生成項目[B->…,first(β)]。
G. 編譯原理筆記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))但這會讓問題更加復雜,故一般不採用。而二義文法無論向前看多少個終結符都無法解決二義性。
H. 編譯原理題,在建立LL(1)語法分析器時,提左因子和消除左遞歸的目的是什麼
消除左遞歸是因為LL文法不能處理含有左遞歸的文法。
提左因子只是推後產生式的選擇決定,等到獲取足夠多的輸入再作選擇。
I. 編譯原理實驗二 LL(1)分析法
通過完成預測分析法的語法分析程序,了解預測分析法和遞歸子程序法的區別和聯系。使學生了解語法分析的功能,掌握語法分析程序設計的原理和構造方法,訓練學生掌握開發應用程序的基本方法。有利於提高學生的專業素質,為培養適應社會多方面需要的能力。
根據某一文法編制調試 LL(1)分析程序,以便對任意輸入的符號串進行分析。
構造預測分析表,並利用分析表和一個棧來實現對上述程序設計語言的分析程序。
分析法的功能是利用LL(1)控製程序根據顯示棧棧頂內容、向前看符號以及LL(1)分析表,對輸入符號串自上而下的分析過程。
對文法 的句子進行不含回溯的自上向下語法分析的充分必要條件是:
(1)文法不含左遞歸;
(2)對於文法中的每一個非終結符 的各個產生式的候選首符集兩兩不相交,即,若
Follow集合構造:
對於文法 的每個非終結符 構造 的演算法是,連續使用下面的規則,直至每個 不再增大為止:
僅給出核心部分
(1) GrammerSymbol.java
(2) GrammerSymbols.java
(3) Grammer.java
(4) LL1Grammer.java