1. 程式人生 > >編譯原理上機題簡單實現

編譯原理上機題簡單實現

一、實驗目的

          通過本實驗使學生進一步熟悉和掌握程式設計語言的詞法分析程式的設計原理及相關的設計技術,如何針對確定的有限狀態自動機進行程式設計序;熟悉和掌握程式設計語言的語法分析程式的設計原理、熟悉和掌握算符優先分析方法。

二、實驗要求

          本實驗要求:①要求能熟練使用C++程式設計語言程式設計;②在上機之前要有詳細的設計報告(預習報告);③要編寫出完成相應任務的程式並在計算機上準確地執行;④實驗結束後要寫出上機實驗報告。

三、實驗題目

          針對下面文法G(S)

S→ v = E

EE+EE-EE*EE/E│(E)│ │ i

       其中,v

為識別符號,i為整型或實型數。

       該文法為:G(Vn,Vt,P,S)

       Vn={S,E}

Vt={v,i,+,-,*,/,(,),=}

P={S→v = E, 

EE+E, 

EE-E,

EE*E, 

EE/E, 

E(E), 

Ev, 

Ei

}

要求完成

① 使用自動機技術實現一個詞法分析程式;

② 使用算符優先分析方法實現其語法分析程式;

解答:①.演算法思想:製造自動機狀態,掃描輸入的表示式字串,每個狀態對應若干字元,識別出狀態,歸納出"單詞"

     自動機狀態圖:

程式碼:

#include<iostream>
using namespace std;
/*
編號規定:
001:加法運算子
002:減法運算子
003:乘法運算子
004:除法運算子
005:界符
008.識別符號
010.整數
011.等號運算子
012.浮點數
error:錯誤欄位
*/
void State11(int j);
void State1(int j);
void State2(int j);
void State3(int j);
void State4(int j);
void State5(int j);
void State6(int i,int j);
void State7(int i,int j);
void State8(int i,int j);
void State9(int i,int j);
void State10(int i,int j);
void State12(int i,int j);
char Code[10000];//儲存“原始碼 ”的字元陣列 ,即詞法分析的物件
bool IsDengHao(char ch)//判斷是否是字元'='
{
  if(ch=='=')
  {
    return true;
  }
  else
  {
    return false;
  }
}

bool IsJiaHao(char ch)//判斷是否是字元'+'
{
  if(ch=='+')
  {
    return true;
  }
  else
  {
    return false;
  }
}

bool IsJianHao(char ch)//判斷是否是字元'-'
{
  if(ch=='-')
  {
    return true;
  }
  else
  {
    return false;
  }
}

bool IsChengHao(char ch)//判斷是否是字元'*'
{
  if(ch=='*')
  {
    return true;
  }
  else
  {
    return false;
  }
}

bool IsChuHao(char ch)//判斷是否是字元'-'
{
  if(ch=='/')
  {
    return true;
  }
  else
  {
    return false;
  }
}

bool IsJieFu(char ch)//判斷是否是界符
{
  if(ch=='('||ch==')')
  {
    return true;
  }
  else
  {
    return false;
  }
}

void State0(int i,int j)//狀態0,初始狀態
{
   if(Code[j]=='#')
   {
     return ;
   }
   if(IsDengHao(Code[j])==true)//如果當前字元是加號進入狀態11
   {
     State11(j);
     return ;
   }
   if(IsJiaHao(Code[j])==true)//如果當前字元是加號進入狀態1
   {
     State1(j);
     return ;
   }
   if(IsJianHao(Code[j])==true)//如果當前字元是減號進入狀態2
   {
     State2(j);
     return ;
   }
   if(IsChengHao(Code[j])==true)//如果當前字元是乘號進入狀態3
   {
     State3(j);
     return ;
   }
   if(IsChuHao(Code[j])==true)//如果當前字元是除號進入狀態4
   {
     State4(j);
     return ;
   }
   if(IsJieFu(Code[j])==true)//如果當前字元是界符進入狀態5
   {
     State5(j);
     return;
   }
  
   if(isalpha(Code[j])!=0)//直接呼叫系統函式isalpha判斷字元是否為英文字母
   {
     State6(i,j+1);//是字母就進入狀態6
     return ;
   } 
   if(isdigit(Code[j])!=0)//直接呼叫系統函式isdigit判斷字元是否是數字
   {
     State7(i,j+1);//是數字就進入狀態7
  return ;
   }
   cout<<"(error,"<<Code[j]<<")" <<endl;
   State0(i,j+1);
}

void State11(int j)//狀態11,表示字元為等號運算子
{
 cout<<"(011,"<<Code[j]<<")" <<endl;
 State0(j+1,j+1);
}
void State1(int j)//狀態1,表示字元為加法運算子
{
 cout<<"(001,"<<Code[j]<<")" <<endl;
 State0(j+1,j+1);
}
void State2(int j)//狀態2,表示字元為減法運算子
{
 cout<<"(002,"<<Code[j]<<")" <<endl;
 State0(j+1,j+1);
}
void State3(int j)//狀態3,表示字元為乘法運算子
{
 cout<<"(003,"<<Code[j]<<")" <<endl;
 State0(j+1,j+1);
}
void State4(int j)//狀態4,表示字元為除法運算子
{
 cout<<"(004,"<<Code[j]<<")" <<endl;
 State0(j+1,j+1);
}
void State5(int j)//狀態5,字元為界符
{
 cout<<"(005,"<<Code[j]<<")" <<endl;
 State0(j+1,j+1);
}

void State6(int i,int j)//狀態6,準識別符號
{
  //Code[i]為準識別符號的第一個字元,是個字母 ,而Code[j-1]是字母或數字
  if(isdigit(Code[j])||isalpha(Code[j]))
  //如果當前字元仍然為字母或數字則再次進入狀態6
  {
     State6(i,j+1);
  return; 
  }
  else//如果當前字元為非數字及字母字元,則表明Code[i]~Code[j-1]這一段是識別符號
  {
   
    /*cout<<"(008,";
 for(int k=i;k<j;k++)
 {
   cout<<Code[k];  
 }
 cout<<")" <<endl;
 State0(j,j);*/
 State8(i,j);//進入狀態8
  }
}

void State7(int i,int j)//狀態7,準實數
{
 //Code[i]為準實數的第一個字元,是個字母 ,而Code[j-1]是數字或小數點
 if(isdigit(Code[j])!=0)//如果當前字元仍然是數字,則再次進入狀態7
 {
  State7(i,j+1);
  return;
 }
 if(Code[j]=='.')//如果當前字元是小數點,進入狀態9
 {
   State9(i,j+1);
   return;
 }
 if((Code[j]!='.')&&(isdigit(Code[j])==0))
 //如果當前字元既不為小數點也不是數字 ,則表明Code[i]~Code[j-1]這一段是個實數
 {
   /* cout<<"(010,";
 for(int k=i;k<j;k++)
 {
   cout<<Code[k];
 }
 cout<<")"<<endl;
 State0(j,j);*/
 State10(i,j);//進入狀態10
 }
}
void State8(int i,int j)//狀態8,識別符號
{
    cout<<"(008,";
 for(int k=i;k<j;k++)
 {
   cout<<Code[k];  
 }
 cout<<")" <<endl;
 State0(j,j);
}

void State9(int i,int j)//狀態9,整數後接個小數點的中間態
{
    //Code[i]~Code[j-1]之中含有小數點
    if(Code[j]=='.')
 /*若當前字元仍為小數點,則判斷Code[i]~Code[j]這一段屬於無效欄位的一部分,
 包括Code[j]後面直接連線的數字、小數點字元構成整個無效欄位 */
    {
      cout<<"(error,";
   int q=i;//從Code[i]開始算起
   while((isdigit(Code[q])!=0)||(Code[q])=='.')
   //直接相連的數字或小數點都屬於這個無效欄位的一部分
   {
     cout<<Code[q];
  q++;  
   }
   cout<<")" <<endl;
   //Code[q]此時為無效欄位的下一個字元
   State0(q,q);
   return;
   /*for(int k=i;k<=j;k++)
   {
    cout<<Code[k];
   }
   cout<<")" <<endl;
   State0(j+1,j+1);*/
    }
 if(isdigit(Code[j])!=0)//如果當前字元是數字,則再次進入狀態9
 {
   State9(i,j+1);
   return;
 }
 if(isdigit(Code[j])==0)
 //如果當前字元是非數字字元,說明Code[i]~Code[j-1]這一段是浮點數
 {
    State12(i,j);//進入終態12
 }
     
}

void State10(int i,int j)//狀態10,整數
{
    cout<<"(010,";
 for(int k=i;k<j;k++)
 {
   cout<<Code[k];
 }
 cout<<")"<<endl;
 State0(j,j);
}
void State12(int i,int j)//狀態12,浮點數
{
    cout<<"(012,";
 for(int k=i;k<j;k++)
 {
   cout<<Code[k];  
 }
 cout<<")" <<endl;
 State0(j,j);
}


int main()
{
  char code_char;
  int n=0,m=0;
  cout<<"請輸入“原始碼”(即字串),(以#為結束符)"<<endl;
  do{
    code_char=getchar();
    if(code_char=='#'&&n==0)
    {
    cout<<"原始碼為空,無法進行詞法分析!"<<endl;
    getchar();
    return 0;
     }
    if(code_char=='#')
    {
          cout<<" 詞法分析開始!";
     cout<<" .................."<<endl;      
     }
     Code[n]= code_char;
     n++;           
  }while(code_char!='#');    
  cout<<"詞法分析結束,結果如下:" <<endl;
  State0(0,0); 
  system("pause");
  return 0;
}

執行測試: