1. 編譯原理實現判斷是不是一個文法的句子
構造LL(1)語法分析程序,任意輸入一個文法符號串,並判斷它是否為文法的一個句子。程序要求為該文法構造預測分析表,並按照預測分析演算法對輸入串進行語法分析,判別程序是否符合已知的語法規則,如果不符合(編譯出錯),則輸出錯誤信息。
2. 編譯原理怎麼判斷是否為slr文法
LL(1)就是向前只搜索1個符號,即與FIRST()匹配,如果FIRST為空則還要考慮FELLOW.
LR需要構造一張LR分析表,此表用於當面臨輸入字元時,將它移進,規約(即自下而上分析思想),接受還是出錯.
LR(0)找出句柄前綴,構造分析表,然後根據輸入符號進行規約.
SLR(1)使用LR(0)時若有沖突,不知道規約,移進,活移進哪一個,所以需要向前搜索,則只把有問題的地方向前搜索一次.
LR(1)1.在每個項目中增加搜索符.2.舉個列子如有A->α.Bβ,則還需將B的規則也加入.
LALR(1)就是假如兩個產生式集相同則將它們合並為一個,幾合並同心集.
3. 編譯原理全部的名詞解釋
書上有別那麼懶!.
編譯過程的六個階段:詞法分析,語法分析,語義分析,中間代碼生成,代碼優化,目標代碼生成
解釋程序:把某種語言的源程序轉換成等價的另一種語言程序——目標語言程序,然後再執行目標程序.解釋方式是接受某高級語言的一個語句輸入,進行解釋並控制計算機執行,馬上得到這句的執行結果,然後再接受下一句.
編譯程序:就是指這樣一種程序,通過它能夠將用高級語言編寫的源程序轉換成與之在邏輯上等價的低級語言形式的目標程序(機器語言程序或匯編語言程序).
解釋程序和編譯程序的根本區別:是否生成目標代碼
句子的二義性(這里的二義性是指語法結構上的.):文法G[S]的一個句子如果能找到兩種不同的最左推導(或最右推導),或者存在兩棵不同的語法樹,則稱這個句子是二義性的.
文法的二義性:一個文法如果包含二義性的句子,則這個文法是二義文法,否則是無二義文法.
LL(1)的含義:(LL(1)文法是無二義的; LL(1)文法不含左遞歸)
第1個L:從左到右掃描輸入串 第2個L:生成的是最左推導
1 :向右看1個輸入符號便可決定選擇哪個產生式
某些非LL(1)文法到LL(1)文法的等價變換: 1. 提取公因子 2. 消除左遞歸
文法符號的屬性:單詞的含義,即與文法符號相關的一些信息.如,類型、值、存儲地址等.
一個屬性文法(attribute grammar)是一個三元組A=(G, V, F)
G:上下文無關文法.
V:屬性的有窮集.每個屬性與文法的一個終結符或非終結符相連.屬性與變數一樣,可以進行計算和傳遞.
F:關於屬性的斷言或謂詞(一組屬性的計算規則)的有窮集.斷言或語義規則與一個產生式相聯,只引用該產生式左端或右端的終結符或非終結符相聯的屬性.
綜合屬性:若產生式左部的單非終結符A的屬性值由右部各非終結符的屬性值決定,則A的屬性稱為綜合屬
繼承屬性:若產生式右部符號B的屬性值是根據左部非終結符的屬性值或者右部其它符號的屬性值決定的,則B的屬性為繼承屬性.
(1)非終結符既可有綜合屬性也可有繼承屬性,但文法開始符號沒有繼承屬性.
(2) 終結符只有綜合屬性,沒有繼承屬性,它們由詞法程序提供.
在計算時: 綜合屬性沿屬性語法樹向上傳遞;繼承屬性沿屬性語法樹向下傳遞.
語法制導翻譯:是指在語法分析過程中,完成附加在所使用的產生式上的語義規則描述的動作.
語法制導翻譯實現:對單詞符號串進行語法分析,構造語法分析樹,然後根據需要構造屬性依賴圖,遍歷語法樹並在語法樹的各結點處按語義規則進行計算.
中間代碼(中間語言)
1、是復雜性介於源程序語言和機器語言的一種表示形式.
2、一般,快速編譯程序直接生成目標代碼.
3、為了使編譯程序結構在邏輯上更為簡單明確,常採用中間代碼,這樣可以將與機器相關的某些實現細節置於代碼生成階段仔細處理,並且可以在中間代碼一級進行優化工作,使得代碼優化比較容易實現.
何謂中間代碼:源程序的一種內部表示,不依賴目標機的結構,易於代碼的機械生成.
為何要轉換成中間代碼:(1)邏輯結構清楚;利於不同目標機上實現同一種語言.
(2)便於移植,便於修改,便於進行與機器無關的優化.
中間代碼的幾種形式:逆波蘭記號 ,三元式和樹形表示 ,四元式
符號表的一般形式:一張符號表的的組成包括兩項,即名字欄和信息欄.
信息欄包含許多子欄和標志位,用來記錄相應名字和種種不同屬性,名字欄也稱主欄.主欄的內容稱為關鍵字(key word).
符號表的功能:(1)收集符號屬性 (2) 上下文語義的合法性檢查的依據: 檢查標識符屬性在上下文中的一致性和合法性.(3)作為目標代碼生成階段地址分配的依據
符號的主要屬性及作用:
1. 符號名 2. 符號的類型 (整型、實型、字元串型等))3. 符號的存儲類別(公共、私有)
4. 符號的作用域及可視性 (全局、局部) 5. 符號變數的存儲分配信息 (靜態存儲區、動態存儲區)
存儲分配方案策略:靜態存儲分配;動態存儲分配:棧式、 堆式.
靜態存儲分配
1、基本策略
在編譯時就安排好目標程序運行時的全部數據空間,並能確定每個數據項的單元地址.
2、適用的分配對象:子程序的目標代碼段;全局數據目標(全局變數)
3、靜態存儲分配的要求:不允許遞歸調用,不含有可變數組.
FORTRAN程序是段結構,不允許遞歸,數據名大小、性質固定. 是典型的靜態分配
動態存儲分配
1、如果一個程序設計語言允許遞歸過程、可變數組或允許用戶自由申請和釋放空間,那麼,就需要採用動態存儲管理技術.
2、兩種動態存儲分配方式:棧式,堆式
棧式動態存儲分配
分配策略:將整個程序的數據空間設計為一個棧.
【例】在具有遞歸結構的語言程序中,每當調用一個過程時,它所需的數據空間就分配在棧頂,每當過程工作結束時就釋放這部分空間.
過程所需的數據空間包括兩部分
一部分是生存期在本過程這次活動中的數據對象.如局部變數、參數單元、臨時變數等;
另一部分則是用以管理過程活動的記錄信息(連接數據).
活動記錄(AR)
一個過程的一次執行所需要的信息使用一個連續的存儲區來管理,這個區 (塊)叫做一個活動記錄.
構成
1、臨時工作單元;2、局部變數;3、機器狀態信息;4、存取鏈;
5、控制鏈;6、實參;7、返回地址
什麼是代碼優化
所謂優化,就是對代碼進行等價變換,使得變換後的代碼運行結果與變換前代碼運行結果相同,而運行速度加快或佔用存儲空間減少.
優化原則:等價原則:經過優化後不應改變程序運行的結果.
有效原則:使優化後所產生的目標代碼運行時間較短,佔用的存儲空間較小.
合算原則:以盡可能低的代價取得較好的優化效果.
常見的優化技術
(1) 刪除多餘運算(刪除公共子表達式) (2) 代碼外提 +刪除歸納變數+ (3)強度削弱; (4)變換循環控制條件 (5)合並已知量與復寫傳播 (6)刪除無用賦值
基本塊定義
程序中只有一個入口和一個出口的一段順序執行的語句序列,稱為程序的一個基本塊.
給我分數啊.
4. 在編譯原理中,語法規則和詞法規則有什麼不同..
通俗的說,
規則主要識別單詞
語法主要識別多個單片語成的句子
5. 急求:編譯原理判斷文法類型的C語言源代碼!!!!!!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/**//*全局變數定義*/
char inputString[10]; /**//*用來存儲用戶輸入的字元串,最長為20個字元*/
char stack[10]; /**//*用來進行語法分析的棧結構*/
int base=0; /**//*棧底指針*/
int top=1; /**//*棧頂指針*/
char VT[4]={'a','d','b','e'}; /**//*用來存放5個終結符*/
char chanShengShi[10]; /**//*用來存放預測分析表M[A,a]中的一條產生式*/
int firstCharIntex=0; /**//*如果a匹配產生式,則每次firstCharIntex 自增 1 */
/**//*firstCharIntex用來存放用戶輸入串的第一個元素的下標*/
/**//*自定義函數聲明*/
char pop() ; /**//*彈出棧頂元素*/
int push(char) ; /**//*向棧內添加一個元素,成功返回1,若棧已滿則返回0*/
int search(char temp) ; /**//*查找非終結符集合VT中是否存在變數temp,存在返回1,不存在返回0*/
int M(char A, char a) ; /**//* 若預測分析表M[A,a]中存在產生式,
則將該產生式賦給字元數組chanShengShi[10],並返回 1,
若M[A,a]中無定義產生式則返回 0
*/
void init() ; /**//*初始化數組inputString[10] 、棧 stack[10] 和 chanShengShi[10]*/
int yuCeFenXi() ; /**//* 進行輸入串的預測分析的主功能函數,
若輸入串滿足文法則返回 1,不滿足則返回0
*/
void printStack(); /**//*列印棧內元素 */
void printinputString(); /**//*列印用戶輸入串 */
/**//*進入主函數*/
void main()
{
system("cls");
yuCeFenXi(); /**//*調用語法預測分析函數*/
system("pause");
}
/**//*函數的定義*/
int yuCeFenXi()
{
char X; /**//*X變數存儲每次彈出的棧頂元素*/
char a; /**//*a變數存儲用戶輸入串的第一個元素*/
int i;
int counter=1; /**//*該變數記錄語法分析的步驟數*/
init(); /**//*初始化數組*/
printf("wen fa : \n"); /**//*輸出文法做為提示*/
printf("S -> aH \n");
printf("H -> aMd | d \n");
printf("M -> Ab | \n");
printf("A -> aM | e \n");
printf("\ninput string ,'#' is a end sign !!(aaabd#) \n"); /**//*提示用戶輸入將要測試的字元串*/
scanf("%s",inputString);
push('#');
push('S');
printf("\nCounter-----Stack---------------Input string \n"); /**//*輸出結果提示語句*/
while(1) /**//*while循環為語法分析主功能語句塊*/
{
printf(" ");
printf(" %d",counter); /**//*輸出分析步驟數*/
printf(" "); /**//*輸出格式控制語句*/
printStack(); /**//*輸出當前棧內所有元素*/
X=pop(); /**//*彈出棧頂元素賦給變數X*/
printinputString(); /**//*輸出當前用戶輸入的字元串*/
if( search(X)==0 ) /**//*在終結符集合VT中查找變數X的值,存在返回 1,否則返回 0*/
{
if(X == '#') /**//*棧已經彈空,語法分析結果正確,返回 1*/
{
printf("success \n"); /**//*語法分析結束,輸入字元串符合文法定義*/
return 1;
}
else
{
a = inputString[firstCharIntex];
if( M(X,a)==1 ) /**//*查看預測分析表M[A,a]是否存在產生式,存在返回1,不存在返回0*/
{
for(i=0;i<10;i++) /**//* '$'為產生式的結束符,for循環找出該產生式的最後一個元素的下標*/
{
if( chanShengShi[i]=='$' ) break;
}
i-- ; /**//*因為 '$' 不是產生式,只是一個產生式的結束標志,所以i自減1*/
while(i>=0)
{
push( chanShengShi[i] ); /**//*將當前產生式逆序壓入棧內*/
i-- ;
}
}
else
{
printf(" error(1) !!\n"); /**//*若預測分析表M[A,a]不存在產生式,說明語法錯誤*/
return 0;
}
}
}
else /**//*說明X為終結符*/
{
if( X==inputString[firstCharIntex] ) /**//*如果X等於a,說明a匹配*/
{
firstCharIntex++; /**//*輸入串的第一個元素被約去,下一個元素成為新的頭元素*/
}
else
{
printf(" error(2) !! \n");
return 0;
}
}
counter++;
}
}
void init()
{
int i;
for(i=0;i<10;i++)
{
inputString[i]=NULL; /**//*初始化數組inputString[10] */
stack[i]=NULL; /**//*初始化棧stack[10] */
chanShengShi[i]=NULL; /**//*初始化數組chanShengShi[10]*/
}
}
int M(char A, char a) /**//*文法定義因實際情況而定,該文法為課本例題的文法*/
{ /**//*該函數模擬預測分析表中的二維數組 */
if( A=='S'&& a=='a' ) { strcpy(&chanShengShi[0],"aH$"); return 1; }
if( A=='H'&& a=='a' ) { strcpy(&chanShengShi[0],"aMd$"); return 1; }
if( A=='H'&& a=='d' ) { strcpy(&chanShengShi[0],"d$"); return 1; }
if( A=='M'&& a=='a' ) { strcpy(&chanShengShi[0],"Ab$"); return 1; }
if( A=='M'&& a=='d' ) { strcpy(&chanShengShi[0],"$"); return 1; }
if( A=='M'&& a=='b' ) { strcpy(&chanShengShi[0],"$"); return 1; }
if( A=='M'&& a=='e' ) { strcpy(&chanShengShi[0],"Ab$"); return 1; }
if( A=='A'&& a=='a' ) { strcpy(&chanShengShi[0],"aM$"); return 1; }
if( A=='A'&& a=='e' ) { strcpy(&chanShengShi[0],"e$"); return 1; }
else return 0; /**//*沒有定義產生式則返回0*/
}
char pop() /**//*彈出棧頂元素,用topChar返回*/
{
char topChar;
topChar=stack[--top];
return topChar;
}
int push(char ch)
{
if( top>9 )
{
printf(" error : stack overflow "); /**//*棧空間溢出*/
return 0;
}
else
{
stack[top]=ch; /**//*給棧頂空間賦值*/
top++;
return 1;
}
}
int search(char temp)
{
int i,flag=0; /**//*flag變數做為標志,若找到temp則賦1,否則賦0*/
for(i=0;i<4;i++)
{
if( temp==VT[i] ) /**//*終結符集合中存在temp*/
{
flag=1;
break;
}
}
if(flag==1) return 1; /**//*flag==1說明已找到等於temp的元素*/
else return 0;
}
void printStack() /**//*輸出棧內內容*/
{
int temp;
for(temp=1;temp<top;temp++)
{
printf("%c",stack[temp]);
}
}
void printinputString() /**//*輸出用戶輸入的字元串*/
{
int temp=firstCharIntex ;
printf(" "); /**//*該句控制輸出格式*/
do{
printf("%c",inputString[temp]);
temp++;
}while(inputString[temp-1]!='#');
printf(" \n");
}
6. C璇璦:璇烽棶鍦–璇璦閲岄潰, a=b>0;榪欎釜璇鍙ュ悎娉曞悧
鍚堟硶錛岄栧厛鍒ゆ柇a鏄鍚︾瓑浜巄錛屽亣濡傜浉絳夊垯涓1,1>0涓虹湡錛岀粨鏋滃氨鏄1錛涘亣濡俛鍜宐涓嶇浉絳夛紝鍒欎負0,0>0涓哄亣錛屽垯緇撴灉涓0.