编译原理:词法分析程序的设计与实现

  • 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)