編譯原理lr分析
A. 編譯原理筆記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))但這會讓問題更加復雜,故一般不採用。而二義文法無論向前看多少個終結符都無法解決二義性。
B. 編譯原理問題,高手進。
回答下列問題:(30分)
(6分)對於下面程序段
program test (input, output)
var i, j: integer;
procere CAL(x, y: integer);
begin
y:=y*y; x:=x-y; y:=y-x
end;
begin
i:=2; j:=3; CAL(i, j)
writeln(j)
end.
若參數傳遞的方法分別為(1)傳值、(2)傳地址,(3)傳名,請寫出程序執行的輸出結果。
答: (1) 3 (2) 16 (3) 16 (每個值2分)
(6分)計算文法G(M)的每個非終結符的FIRST和FOLLOW集合,並判斷該文法是否是LL(1)的,請說明理由。
G(M):
M → TB
T → Ba |
B → Db | eT |
D → d |
解答:
計算文法的FIRST和FOLLOW集合:(4分)
FIRST(M) = { a,b,e,d, } FIRST(T) = { a,b,e,d, }
FIRST(B) = {b,e,d, } FIRST(D) = {d,}
FOLLOW (M) = {#} FOLLOW (T) = { a,b,e,d,#}
FOLLOW (B) = {a,# } FOLLOW (D) = { b}
檢查文法的所有產生式,我們可以得到:
1. 該文法不含左遞歸,
2. 該文法中每一個非終結符M,T,B,D的各個產生式的候選首符集兩兩不相交。
3. 該文法的非終結符T、B和D,它們都有候選式,而且
FIRST(T)∩FOLLOW(T)={ a,b,e,d }≠
所以該文法不是LL(1)文法。(2分)
(4分)考慮下面的屬性文法
產 生 式 語 義 規 則
S→ABC
A→a
B→b
C→c B.u := S.u
A.u := B.v + C.v
S.v := A.v
A.v :=3*A.u
B.v := B.u
C.v := 1
畫出字元串abc的語法樹;
對於該語法樹,假設S.u的初始值為5,屬性計算完成後,S.v的值為多少。
答:(1) (2分)
(2) S.v的值為18 (2分)
(4分)運行時的DISPLAY表的內容是什麼?它的作用是什麼?
答:DISPLAY表是嵌套層次顯示表。每當進入一個過程後,在建立它的活動記錄區的同時建立一張嵌套層次顯示表diaplay.假定現在進入的過程層次為i,則它的diaplay表含有i+1個單元,自頂向下每個單元依次存放著現行層、直接外層、…、直至最外層(主程序,0層)等每層過程的最新活動記錄的起始地址。通過DISPLAY表可以訪問其外層過程的變數。
(5分)對下列四元式序列生成目標代碼:
A:=B*C
D:=E+A
G:=B+C
H:=G*D
其中,H在基本塊出口之後是活躍變數, R0和R1是可用寄存器。
答: 目標代碼序列
LD R0 B
MUL R0 C
LD R1 E
ADD R1 R0
LD R0 B
ADD R0 C
MUL R0 R1
ST R0 H
(5分)寫出表達式a+b*(c-d)對應的逆波蘭式、三元式序列和抽象語法樹。
答:
逆波蘭式:(abcd-*+) (1分)
三元式序列: (2分)
OP ARG1 ARG2
(1) - c d
(2) * b (1)
(3) + a (2)
抽象語法樹:(2分)
(8分)構造一個DFA,它接受={a,b}上所有包含ab的字元串。
答:
(2分)構造相應的正規式:(a|b)*ab(a|b)*
(3分)
a a
a b
b b
(3分)確定化:
I
{0,1,2} {1,2,3} {1,2}
{1,2,3} {1,2,3} {1,2,4,5,6}
{1,2} {1,2,3} {1,2}
{1,2,4,5,6} {1,2,3,5,6} {1,2,5,6}
{1,2,3,5,6} {1,2,3,5,6} {1,2,4,5,6}
{1,2,5,6} {1,2,3,5,6} {1,2,5,6}
b b
b a
a a a a
a b b
b
最小化:
{0,1,2} {3,4,5}
{0, 2},1, {3,4,5}
(6分)寫一個文法使其語言為L(G)={anbncm| m,n≥1,n為奇數,m為偶數}。
答:
文法G(S):
(8分)對於文法G(S):
1. 寫出句型b(Ma)b的最右推導並畫出語法樹。
2. 寫出上述句型的短語,直接短語和句柄。
答:
1. (4分)
2. (4分)
短語: Ma), (Ma), b(Ma)b
直接短語: Ma)
句柄: Ma)
(12分)對文法G(S):
S → a | ^ | (T)
T → T,S | S
(1) 構造各非終結符的FIRSTVT和LASTVT集合;
(2) 構造算符優先表;
(3) 是算符優先文法嗎?
(4) 構造優先函數。
答:
(1) (4分)
(2) (4分)
a ^ ( ) ,
a > >
^ > >
( < < < = <
) > >
, < < < > >
(3) 是算符優先文法,因為任何兩個終結符之間至多隻有一種優先關系。 (1分)
(4) 優先函數(3分)
a ^ ( ) ,
F 4 4 2 4 4
G 5 5 5 2 3
(8分)設某語言的do-while語句的語法形式為
S do S(1) While E
其語義解釋為:
針對自下而上的語法分析器,按如下要求構造該語句的翻譯模式,將該語句翻譯成四元式:
(1) 寫出適合語法制導翻譯的產生式;
(2) 寫出每個產生式對應的語義動作。
答:(1). 適合語法制導翻譯的文法(4分)
G(S):
R do
UR S(1) While
SU E
(2). (4分)
R do
{ R.QUAD:=NXQ }
UR S(1) While
{ U.QUAD:=R.QUAD;
BACKPATCH(S.CHAIN, NXQ) }
SU E
{ BACKPATCH(E.TC, U.QUAD);
S.CHAIN:=E.FC }
答案二:
(1) S do M1 S(1) While M2 E
M ε (4分)
(2) M ε { M.QUAD := NXQ } (4分)
S do M1 S(1) While M2 E
{
BACKPATCH(S(1).CHAIN, M2.QUAD);
BACKPATCH(E.TC, M1.QUAD);
S.CHAIN:=E. FC
}
(10分)將語句
while C>0 do if A B=0 then C:=C+D else C:=C*D
翻譯成四元式。
答:
100 (j>, C, 0, 102)
101 (j, -, -, 112)
102 (jnz, A, -, 106)
103 (j, -, -, 104)
104 (j=, B, 0, 106)
105 (j, -, -, 109)
106 (+, C, D, T1)
107 (:=, T1, -, C)
108 (j, -, -, 100)
109 (*, C, D, T2)
110 (:=, T2, -, C)
111 (j, -, -, 100)
112
(10分)設有基本塊如下:
T1:=3
T2:=A*B
T3:=9+T1
M:=A*B
T4:=C-D
L:=T3*T4
T2:=C+D
N:=T2
畫出DAG圖;
設L,M,N 是出基本塊後的活躍變數,請給出優化後的四元式序列。
答:
1. (6分)
L
*
T2,M T4 T2,N
* - +
T1 T3
3 A B 12 C D
2. (4分)
M:=A*B
S1:=C-D
L:=12*S1
N:=C+D
(8分)文法G(S)及其LR分析表如下,請給出串baba#的分析過程。
(1) S → DbB (2) D → d (3) D → ε
(4) B → a (5) B → Bba (6) B → ε
LR分析表
ACTION GOTO
b D a # S B D
0 r3 s3 1 2
1 acc
2 s4
3 r2
4 r6 S5 r6 6
5 r4 r4
6 s7 r1
7 S8
8 r5 r5
解答:
步驟 狀態 符號 輸入串
0 0 # baba#
1 02 #D baba#
2 024 #Db aba#
3 0245 #Dba ba#
4 0246 #DbB ba#
5 02467 #DbBb a#
6 024678 #DbBba #
7 0246 #DbB #
8 01 #S # acc
哈哈,估計認識!!
C. 編譯原理求解答案
編譯原理是計算機軟體專業中的非常重要一門課程。例如:如何把我們編寫的高級語言源程序,翻譯成機器可執行的目標程序,這個就需要用到編譯原理技術。
但是學習編譯原理這門課程時,是需要頭腦中對編譯原理課程中涉及到的所有概念必須是相當清楚的,別人才能夠對你的這些問題進行准確的回答。而不是看到這些似曾親切的內容就敢於回答你的內容的。
故我個人的建議還是:你可以向專門講授編譯原理的老師請教你的問題。
以上就是我很多年前學習編譯原理的親身體會。
D. 編譯原理中 「句子」的概念 LR(1)分析法中「L」 「 R」的含義分別是
字母表上符合某種規則構成的串稱作句子。
L:自左至右掃描,R:最右推倒的逆過程。
E. 編譯原理LR(1)中的R和1分別是什麼意思
LR分析法是一種自下而上進行規范歸約的語法分析法,L指從左到右掃描輸入符號串,R是指構造最右推導的逆過程.LR(1)中的1是每次搜索符號需要向前參考一步,即參考下一個符號確定當前構造.
F. 編譯原理用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);
}
G. 編譯原理中語法分析的一道問題
LALR我做著做著覺得不對,但SLR還是沒問題的,這道題工程量非常龐大,想必以後也一定有人問,我就簡要的帶過吧,我歸納的解題步驟是:
構造LR(0)項目集規范族
求出FOLLOW集
根據規則圈出sj和rj對應的產生式
算出goto數
構造分析表
H. 編譯原理實驗二 算術表達式擴充
你是需要解釋分析過程,還是需要用代碼寫出你的程序的分析過程?
I. 有關編譯原理
⑴拓廣文法 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,#} ,所以無法解決沖突