第一篇:編譯原理實(shí)驗(yàn) 編譯器 綜合報(bào)告(附源代碼)
編譯原理 編譯器綜合實(shí)驗(yàn)
---------------工程精品
神刀公子
一. 實(shí)驗(yàn)背景
編譯器就是將“一種語言(通常為高級語言)”翻譯為“另一種語言(通常為低級語言)”的程序。一個(gè)現(xiàn)代編譯器的主要工作流程:源代碼(source code)→ 預(yù)處理器(preprocessor)→ 編譯器(compiler)→ 目標(biāo)代碼(object code)→ 鏈接器(Linker)→ 可執(zhí)行程序(executables)高級計(jì)算機(jī)語言便于人編寫,閱讀交流,維護(hù)。機(jī)器語言是計(jì)算機(jī)能直接解讀、運(yùn)行的。編譯器將匯編或高級計(jì)算機(jī)語言源程序(Source program)作為輸入,翻譯成目標(biāo)語言(Target language)機(jī)器代碼的等價(jià)程序。源代碼一般為高級語言(High-level language),如Pascal、C、C++、Java、漢語編程等或匯編語言,而目標(biāo)則是機(jī)器語言的目標(biāo)代碼(Object code),有時(shí)也稱作機(jī)器代碼(Machine code)。
對于C#、VB等高級語言而言,此時(shí)編譯器完成的功能是把源碼(SourceCode)編譯成通用中間語言(MSIL/CIL)的字節(jié)碼(ByteCode)。最后運(yùn)行的時(shí)候通過通用語言運(yùn)行庫的轉(zhuǎn)換,編程最終可以被CPU直接計(jì)算的機(jī)器碼(NativeCode)。
二. 算法設(shè)計(jì)
典型的編譯器輸出是由包含入口點(diǎn)的名字和地址,以及外部調(diào)用(到不在這個(gè)目標(biāo)文件中的函數(shù)調(diào)用)的機(jī)器代碼所組成的目標(biāo)文件。一組目標(biāo)文件,不必是同一編譯器產(chǎn)生,但使用的編譯器必需采用同樣的輸出格式,可以鏈接在一起并生成可以由用戶直接執(zhí)行的EXE, 詞法分析程序 ? 語法分析程序 ? 語義分析程序 ?編譯器。不斷完善,不斷改進(jìn)。漸變的過程。
。。函數(shù)。。
void scanner();//掃描 void lrparser();
void staBlock(int *nChain);//語句塊 void staString(int *nChain);//語句串 void sta(int *nChain);//語句 void fuzhi();//賦值語句
void tiaojian(int *nChain);//條件語句 void xunhuan();//循環(huán)語句 char* E();//Expresiion表達(dá)式 char* T();//Term項(xiàng) char* F();//Factor因子
char *newTemp();//自動(dòng)生成臨時(shí)變量 void backpatch(int p,int t);//回填
int merge(int p1,int p2);//合并p1和p2 void emit(char *res,char *num1,char *op,char *num2);//生成四元式
截圖說明:
綜合輸入:(賦值,循環(huán),條件。。結(jié)合,自己定義即可)
源代碼:
//************編譯器******************** // //***Erin*** //***軟件工程0801班*** //***HUST*** // //**************************************
#include
char prog[80];//存放所有輸入字符
char token[8];//存放詞組
char ch;//單個(gè)字符
int syn,p,m,n,i;//syn:種別編碼
double sum;
int count;
int isSignal;//是否帶正負(fù)號(0不帶,1負(fù)號,2正號)int isError;int isDecimal;//是否是小數(shù)
double decimal;//小數(shù)
int isExp;//是否是指數(shù)
int index;//指數(shù)冪
int isNegative;//是否帶負(fù)號
double temp;
int temp2;
int repeat;//是否連續(xù)出現(xiàn)+,{
if(syn==22)//+
strcpy(op,“+”);
else
strcpy(op,“-”);
scanner();
strcpy(num2,T());
strcpy(res,newTemp());
emit(res,num1,op,num2);
strcpy(num1,res);} return num1;}
char* T()//Term項(xiàng) { char *res,*num1,*op,*num2;res=(char *)malloc(10);num1=(char *)malloc(10);op=(char *)malloc(10);num2=(char *)malloc(10);strcpy(num1,F());while((syn==24)||(syn==25))//* / {
if(syn==24)
strcpy(op,“*”);
else
strcpy(op,“/”);
scanner();
strcpy(num2,F());
strcpy(res,newTemp());
emit(res,num1,op,num2);
strcpy(num1,res);} return num1;}
char* F()//Factor因子 { char *res;
res=(char *)malloc(10);if(syn==10)//字符串 { strcpy(res,token);scanner();} else if(syn==20)//二進(jìn)制數(shù) {
itoa((int)sum,res,10);//整數(shù)轉(zhuǎn)換為字符串
scanner();} else if(syn==26)//({
scanner();
res=E();
if(syn==27)//)
{
scanner();
}
else isError=1;} else
isError=1;return res;}
char *newTemp(){ char *p;char varTemp[10];p=(char *)malloc(10);kk++;itoa(kk,varTemp,10);strcpy(p+1,varTemp);p[0]='T';return p;}
//將p所鏈接的每個(gè)四元式的第四個(gè)分量都回填t void backpatch(int p,int t){ int w,circle=p;while(circle)//circle不為0的時(shí)候
{
} w=atoi(fourCom[circle].result);//四元式circle第四分量內(nèi)容
//strcpy(fourCom[circle].result,t);//把t填進(jìn)四元式circle的第四分量
sprintf(fourCom[circle].result,“%d”,t);circle=w;//w記錄的是鏈條上下一個(gè)四元式,移動(dòng)!} return;int merge(int p1,int p2)//合并p1和p2 { char circle,nResult;if(p2==0)
nResult=p1;else {
nResult=circle=p2;
} while(atoi(fourCom[circle].result))//四元式第四個(gè)分量不為0 { circle=atoi(fourCom[circle].result);
//strcpy(fourCom[circle].result,p1);sprintf(fourCom[circle].result,“%s”,p1);} //目的是用p1的值覆蓋0 return nResult;//p2是頭,p1覆蓋0,接在p2后邊 }
void emit(char *res,char *num1,char *op,char *num2){ strcpy(fourCom[nextq].result,res);strcpy(fourCom[nextq].arg1,num1);strcpy(fourCom[nextq].opera,op);strcpy(fourCom[nextq].arg2,num2);nextq++;}
void scanner()
{
sum=0;
decimal=0;
m=0;
for(n=0;n<8;n++)
token[n]=NULL;
ch=prog[p++];//從prog中讀出一個(gè)字符到ch中
while(ch==' '||ch=='n')//跳過空字符(無效輸入)
ch=prog[p++];
if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z')))//ch是字母字符
{
while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9')))
{
token[m++]=ch;//ch=>token
ch=prog[p++];//讀下一個(gè)字符
}
token[m++]='