編譯原理的活前綴
⑴ 編譯原理 語法
編譯原理不同教材用的表示不太一樣,翻譯也五花八門,我不是很確定你這個活前綴是什麼意思。我按我知道的告訴你,我用「。」表示狀態的位置,你的書上可能通常是一個黑點表示,先要建立文法的狀態集合:
S1:S->。a
S2:S->a。
S3:S->。^
S4:S->^。
S5:S->。(T)
S6:S->(。T)
S7:S->(T。)
S8:S->(T)。
S9:T->。T,S
S10:T->T。,S
S11:T->T,。S
S12:T->T,S。
S13:T->。S
S14:T->S。
歸集狀態,和狀態轉換關系(這應該是要畫成圖的,這里沒法畫。。。)用I表示
I0:S1 S3 S5 S9 S13
輸入a,I0->I1
I1:S2
輸入^,I0->I2
I2:S4
輸入(,I0->I3
I3:S6 S9 S13 S1 S3 S5
歸約S,I0->I4
I4:S14
歸約T,I0->I5
I5:S10
歸約T,I3->I6
I6:S7
輸入),I6->I7
I7:S8
輸入,,I5->I8
I8:S11 S1 S3 S5
歸約S,I8->I9
I9:S12
輸入a,I8->I1
輸入^,I8->I2
輸入(,I8->I3
輸入a,I3->I1
輸入^,I3->I2
輸入(,I3->I3
然後你要建立狀態轉換表,網路不能畫表格。。。,你將就看看( $是結束符啊.還有你的文法沒有開始,即S')
先把題目中的規則編個號:
(1) S->a
(2) S->^
(3) S->(T)
(4) T->T,S
(5) T->S
action goto
狀態集 a ^ ( ) , $ S T
0 s1 s2 s3 14 10
1 acc
2 acc
3 s1
因為沒有S'不知道最終怎麼規約
⑵ 編譯原理筆記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(1) 那個向前搜索符怎麼求的 跪求高手解答 復制粘貼或者答非所問的別來
1、首先第一步就是項目[S』-> . S,],自動生成搜索符],自動生成搜索符],自動生成搜索符,從項目[A->α.Bβ,?]生成項目[B->…,first(β)]。
⑷ 有關編譯原理的幾個問題
最左推到就是從最左邊的非終結符開始替換,一個一個替換,直到替換為題目要求的。預測分析表什麼的太煩了,不高興寫。你按著書上例題步驟一步一步寫就可以了。給你寫個第五題。
⑸ 識別文法活前綴的NFA的程序 用c++實現
我雖然不會,但是給你一個建議,這種高難度的東東放在這有點浪費時間。 如果米多可以去專用網站求人去寫, 如果想cost down那麼也可以去豬八戒或威克天地等在線懸賞網站,也許出不了很多錢很快幫你解決問題。
⑹ 編譯原理求解答案
編譯原理是計算機軟體專業中的非常重要一門課程。例如:如何把我們編寫的高級語言源程序,翻譯成機器可執行的目標程序,這個就需要用到編譯原理技術。
但是學習編譯原理這門課程時,是需要頭腦中對編譯原理課程中涉及到的所有概念必須是相當清楚的,別人才能夠對你的這些問題進行准確的回答。而不是看到這些似曾親切的內容就敢於回答你的內容的。
故我個人的建議還是:你可以向專門講授編譯原理的老師請教你的問題。
以上就是我很多年前學習編譯原理的親身體會。
⑺ 什麼叫活前綴,用通俗的話解答下,或者簡單的例子。 這個題是編譯原理的。
活前綴:右句型的前綴,而且其右端不會超過該句型的最右邊句柄的末端。
右句型:最右推導可得到的句型。
最右推導:每步推導都替代最右非終結符的推導。
推導:我們說αBγ推導出αβγ,是說存在產生式B->β。
產生式:左邊為非終結符,右邊為終結符與非終結符組合成的串。
非終結符:是字元串的集合。
終結符:組成語言的詞。如c語言中的2,a,int,if等。
句型:開始符經過若干步推導後得到的串。
前綴:如abc的前綴為a、ab、abc。
開始符:開始符是整個語言的集合。
句柄:非形式的,句柄是和某個產生式右部匹配的字元串,把句柄歸約成產生式左部的非終結符,可以得到最右推導的逆過程的一步。形式的定義為:開始符s經過若干步最右推導得到αBγ,αBγ經過一步最右推導得到αβγ,若γ為終結符的集合,則β為句柄。舉例:
E->E+E|E*E|-E|(E)|id,對於id+id*id,其中一個最右推導為E->E+E->E+E*E->E+E*id->E+id*id->id+id*id。在id+id*id歸約成E+id*id的過程中,最左邊的id是句柄。E+id*id歸約成E+E*id時,最左邊的id是句柄,把E+E*id歸約成E+E*E時,id是句柄。把E+E*E歸約成E+E時E*E是句柄。E+E歸約成E時,E+E是句柄。
歸約:可理解為把產生式右邊的串用產生式左邊的非終結符代替。
注1:再說一下活前綴,舉個例子,比如E+E*E歸約成E+E,句柄是E*E,那麼它的活前綴就是E、E+、E+E、E+E*、E+E*E。又比如id+id*id歸約成E+id*id,句柄是最左邊的id,那麼它的活前綴是id,因為不能超過句柄。
注2:至於為什麼要給出活前綴的定義和如何用歸約的方法實現語法分析,還要進一步學習。
⑻ 有關編譯原理
⑴拓廣文法 1 分
G[S ′ ]: S ′→ S ⑴
S → SaA ⑵ S → a ⑶ A → AbS ⑷ A → b ⑸
該文法的以 LR(0) 項目集為狀態的識別規范句型活前綴的 DFA :
⑵ 該文法的 LR(0) 分析表:
狀態 ACTION GOTO
a b # S A
0 S 2 1
1 S 3 acc
2 r 3 r 3 r 3
3 S 5 4
4 r 2 r 2 /S 6 r 2
5 r 5 r 5 r 5
6 S 2 7
7 r 4 /S 3 r 4 r 4
⑶ LR(0) 文法:該文法的以 LR(0) 項目集為狀態的識別規范句型活前綴的 DFA 中沒有沖突狀態。
該文法不是 LR(0) 文法
因為存在沖突狀態: I 4 和 I 7
⑷ SLR(1) 文法:該文法的以 LR(0) 項目集為狀態的識別規范句型活前綴的 DFA 中有沖突狀態,沖突可用 FOLLOW 集解決。
該文法不是 SLR(1) 文法。
因為 FOLLOW(S)={a,b,#} ,所以無法解決沖突
⑼ 急急急,編譯原理
using namespace std;
struct BiNode
{
char data;
BiNode *lchild, *rchild;
};
typedef BiNode *BiTree;
int CreateBiTree(BiTree &T, const char *s1, const char *s2, int len)
{
if (len<=0)
{
T = NULL;
return 1;
}
else
{
T = new BiNode;
T->data = *s1;
int i;
for ( i=0; i<len; i++) if (s2[i]==*s1) break;
CreateBiTree(T->lchild, s1+1, s2, i);
CreateBiTree(T->rchild, s1+i+1, s2+i+1, len-(i+1));
}
return 1;
}
int DestroyBiTree(BiTree &T)
{
if (T==NULL) return 1;
DestroyBiTree(T->lchild);
DestroyBiTree(T->rchild);
delete T;
T = NULL;
return 1;
}
int ATraverse(BiTree &T)
{
if (T==NULL) return 1;
ATraverse(T->lchild);
ATraverse(T->rchild);
cout<<T->data;
return 1;
}
main()
{
char a[2000],b[2000];
while(cin>>a>>b)
{
BiTree T;
int count=0;
int n;
for(n=0;a[n]!='\0';n++);
CreateBiTree(T,a,b,n);
ATraverse(T);
cout<<" ";
cout<<endl;
DestroyBiTree(T);