編譯原理:詞法分析程序的設計與實現

  • 2019 年 10 月 11 日
  • 筆記

詞法分析程序(Lexical Analyzer)要求:


 

  • 從左至右掃描構成源程序的字符流
  • 識別出有詞法意義的單詞(Lexemes
  • 返回單詞記錄(單詞類別,單詞本身)
  • 濾掉空格
  • 跳過注釋
  • 發現詞法錯誤

程序結構:

輸入:字符流(什麼輸入方式,什麼數據結構保存)

處理

  • 遍歷(什麼遍歷方式)
  • 詞法規則

輸出:單詞流(什麼輸出形式)

  • 二元組

單詞類別:

  1. 標識符(10)
  2. 無符號數(11)
  3. 保留字(一詞一碼)
  4. 運算符(一詞一碼)
  5. 界符(一詞一碼)

 

單詞符號

種別碼

單詞符號

種別碼

begin

1

:

17

if

2

:=

18

then

3

<

20

while

4

<=

21

do

5

<>

22

end

6

>

23

l(l|d)*

10

>=

24

dd*

11

=

25

+

13

;

26

14

(

27

*

15

)

28

/

16

#

0


程序詞法分析代碼:

#include <iostream>  #include<stdio.h>  #include<string.h>  #include<stdlib.h>  using namespace std;    //關鍵字   string key[6]={"main","int","if","else","while","do"};  //關鍵字的種別碼  int keyNum[6]={1,2,3,4,5,6};  //運算符和界符   string symbol[17]={"<",">","!=",">=","<=","==",",",";","(",")","{","}","+","-","*","/","="};  //char symbol[12]={'<','>','!=','>=','<=','==',',',';','(',')','{','}'};  //運算符和界符的種別碼   int symbolNum[17]={7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};  //存放文件取出的字符   string letter[1000];  //將字符轉換為單詞  string words[1000];  int length; //保存程序中字符的數目   int num;    //判斷運算符和界符  int isSymbol(string s){      int i;      for(i=0;i<17;i++){          if(s==symbol[i])          return symbolNum[i];      }      return 0;  }  //判斷是否為數字   bool isNum(string s){      if(s>="0" && s<="9")      return true;  }  //判斷是否為字母   bool isLetter(string s){      if(s>="a" && s<="z")      return true;  }  //判斷是否為關鍵字,是返回種別碼   int isKeyWord(string s){      int i;      for(i=0;i<6;i++){          if(s==key[i])          return keyNum[i];      }      return 0;  }    //返回單個字符的類型   int typeword(string str){      if(str>="a" && str<="z") // 字母       return 1;        if(str>="0" && str<="9") //數字       return 2;        if(str==">"||str=="="||str=="<"||str=="!"||str==","||str==";"||str=="("||str==")"||str=="{"||str=="}"      ||str=="+"||str=="-"||str=="*"||str=="/") //判斷運算符和界符       return 3;  }    string identifier(string s,int n){      int j=n+1;      int flag=1;      while(flag){          if(isNum(letter[j]) || isLetter(letter[j])){              s=(s+letter[j]).c_str();              if(isKeyWord(s)){                  j++;                  num=j;                  return s;              }          j++;          }          else{              flag=0;          }      }      num=j;      return s;  }    string symbolStr(string s,int n){      int j=n+1;      string str=letter[j];      if(str==">"||str=="="||str=="<"||str=="!") {          s=(s+letter[j]).c_str();          j++;      }      num=j;      return s;  }    string Number(string s,int n){      int j=n+1;      int flag=1;      while(flag){          if(isNum(letter[j])){              s=(s+letter[j]).c_str();              j++;          }          else{              flag=0;          }      }      num=j;      return s;  }    void print(string s,int n){      cout<<"("<<s<<","<<n<<")"<<endl;  }    //取單詞   void TakeWord(){      int k;      for(num=0;num<length;){          string str1,str;          str=letter[num];          k=typeword(str);          switch(k){              case 1:                  str1=identifier(str,num);                  if(isKeyWord(str1))                      print(str1,isKeyWord(str1));                  else                      print(str1,0);                  break;              case 2:                  str1=Number(str,num);                  print(str1,24);                  break;              case 3:                  str1=symbolStr(str,num);                  print(str1,isSymbol(str1));                  break;          }      }  }    int main(){      char w;      int i,j;      freopen("test.txt","r",stdin);//讀取本地文件       freopen("result.txt","w",stdout); //從控制台輸出,而不是文本輸出      length=0;      while(cin>>w){          if(w!=' '){              letter[length]=w;              length++;          } //去掉程序中的空格      }      TakeWord();      fclose(stdin);//關閉文件       fclose(stdout);//關閉文件       return 0;  }

 


運行程序前準備一個分析文本test.txt內容如下:

int main()  {      int m,n;      int num=0;      n=10;      if(n<0){         m=-n;      }      else{         m=n;      }      while(m!=0){               num=m*n;      }  }


執行程序會輸出如下結果:

(int,2)  (main,1)  ((,15)  (),16)  ({,17)  (int,2)  (m,0)  (,,13)  (n,0)  (;,14)  (int,2)  (num,0)  (=,23)  (0,24)  (;,14)  (n,0)  (=,23)  (10,24)  (;,14)  (if,3)  ((,15)  (n,0)  (<,7)  (0,24)  (),16)  ({,17)  (m,0)  (=,23)  (-,20)  (n,0)  (;,14)  (},18)  (else,4)  ({,17)  (m,0)  (=,23)  (n,0)  (;,14)  (},18)  (while,5)  ((,15)  (m,0)  (!=,9)  (0,24)  (),16)  ({,17)  (num,0)  (=,23)  (m,0)  (*,21)  (n,0)  (;,14)  (},18)  (},18)