编写词法分析器

词法分析器功能

输入源程序、输出单词符号(其表示形式为:(单词种别,单词自身的值)

预处理:删除注释,删除续换行符,换行符,TAB和空格

词法分析器的设计

(1)给出程序设计语言的单词规范——单词表

单词符号

种别编码

标识符

0

main

1

int

2

If

3

else

4

while

5

do

6

7

8

!=

9

>=

10

<=

11

==

12

,

13

;

14

(

15

)

16

{

17

}

18

+

19

-

20

*

21

/

22

=

23

常数(数)

24

2)对照单词表设计识别该单词所有单词的状态转换图

状态转换图实质上是程序流程图,每个状态结对应一小段程序。

程序思路:

(1)预处理:去掉程序中的空格和注释

(2)取出字符进行单词符号的识别并进行相应的处理

(3)输出词法分析结果

3)根据状态转换图编写词法分析器

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 using namespace std;
  5 
  6 int keyNum[6]= {1,2,3,4,5,6};//存储关键字的种别编码
  7 string key[6]= {"main","int","if","else","while","do"}; //存储关键字数组 
  8 int symbolNum[17]= {7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};//存储运算符和界符的种别码 
  9 string symbol[17]= {"<",">","!=",">=","<=","==",",",";","(",")","{","}","+","-","*","/","="};//存储运算符和界符数组 
 10 string letter[1000];//存储从文件中取出的字符
 11 string words[1000];//将字符转换为单词
 12 int length; //程序中字符的数目
 13 int num;//当前遍历到的字符下标 
 14 
 15 int isSymbol(string s)  //判断运算符和界符
 16 {
 17     int i;
 18     for(i=0; i<17; i++)
 19     {
 20         if(s==symbol[i])
 21             return symbolNum[i];
 22     }
 23     return 0;
 24 }
 25 
 26 bool isNum(string s)//判断是否为数字
 27 {
 28     if(s>="0" && s<="9")
 29         return true;
 30     return false;
 31 }
 32 
 33 bool isLetter(string s)//判断是否为字母
 34 {
 35     if(s>="a" && s<="z")
 36         return true;
 37     return false;
 38 }
 39 
 40 int isKeyWord(string s)//判断是否为关键字,是返回种别码
 41 {
 42     int i;
 43     for(i=0; i<6; i++)
 44     {
 45         if(s==key[i])
 46             return keyNum[i];
 47     }
 48     return 0;
 49 }
 50 
 51 int typeword(string str)//返回单个字符的类型
 52 {
 53     if(str>="a" && str<="z") // 字母
 54         return 1;
 55 
 56     if(str>="0" && str<="9") //数字
 57         return 2;
 58 
 59     if(str==">"||str=="="||str=="<"||str=="!"||str==","||str==";"||str=="("||str==")"||str=="{"||str=="}"||str=="+"||str=="-"||str=="*"||str=="/") //判断运算符和界符
 60         return 3;
 61 }
 62 
 63 string identifier(string s,int n) //连接标识符
 64 {
 65     int j=n+1;
 66     int flag=1;
 67 
 68     while(flag)
 69     {
 70         if(isNum(letter[j]) || isLetter(letter[j]))
 71         {
 72             s=(s+letter[j]).c_str();
 73             if(isKeyWord(s))
 74             {
 75                 j++;
 76                 num=j;
 77                 return s;
 78             }
 79             j++;
 80         }
 81         else//运算符等操作符
 82         {
 83             flag=0;
 84         }
 85     }
 86 
 87     num=j;
 88     return s;
 89 }
 90 
 91 string symbolStr(string s,int n) //连接符号与界符
 92 {
 93     int j=n+1;
 94     string str=letter[j];
 95     if(str==">"||str=="="||str=="<"||str=="!")
 96     {
 97         s=(s+letter[j]).c_str();
 98         j++;
 99     }
100     num=j;
101     return s;
102 }
103 
104 string Number(string s,int n)//连接数字 
105 {
106     int j=n+1;
107     int flag=1;
108 
109     while(flag)
110     {
111         if(isNum(letter[j]))
112         {
113             s=(s+letter[j]).c_str();
114             j++;
115         }
116         else
117         {
118             flag=0;
119         }
120     }
121 
122     num=j;
123     return s;
124 }
125 
126 void print(string s,int n)
127 {
128     cout<<"("<<s<<","<<n<<")"<<endl;
129 }
130 
131 void TakeWord()  //对letter数组中的字符进行分析 
132 {
133     int k;
134 
135     for(num=0; num<length;)
136     {
137         string str1,str;
138         str=letter[num];
139         k=typeword(str);//分析字符的类型 
140         switch(k)
141         {
142         case 1: //表明该字符为字母 
143         {
144             str1=identifier(str,num);
145             if(isKeyWord(str1))//输出关键字 
146                 print(str1,isKeyWord(str1));
147             else //输出标识符 
148                 print(str1,0);
149             break;
150         }
151         case 2://表明该字符为数字
152         {
153             str1=Number(str,num);
154             print(str1,24);//输出常数 
155             break;
156         }
157 
158         case 3://表明该字符为运算符和界符
159         {
160             str1=symbolStr(str,num);
161             print(str1,isSymbol(str1));//输出运算符和界符 
162             break;
163         }
164         }
165     }
166 }
167 
168 int main()
169 {
170     freopen("E:\\input.txt","r",stdin);
171     freopen("E:\\output.txt","w",stdout); 
172     int i,j,flag=0;
173     char w,front,aa=' ';//aa存前一个的'/' 
174     length=0;
175     while(cin>>w)//预处理:去掉程序中的空格和注释 
176     {
177         if((w=='/')&&(front=='/')){ //注释//开始判断条件
178             flag=1;
179         }
180         else if((w=='*')&&(front=='/')){ //注释/*开始判断条件
181             flag=2;
182         }
183         else if((flag==1)&&(w=='\n')){ //注释//结束判断条件 
184         //cout<<"------------"<<endl;
185             flag=0;
186         }
187         else if((flag==2)&&(w=='/')){ //注释/*结束判断条件
188         //cout<<"------------"<<endl;
189             flag=0;
190         }
191         else if((w!=' ')&&(flag==0))
192         {
193             int outflag=0;
194             if(aa=='/'){ //表示'/'并不是注释的组成部分,则输出存的前一个'/' 
195                 letter[length]=w;
196                 length++;
197                 aa=' ';
198                 outflag=1;
199             }
200             if(w=='/') aa=w;
201             else{
202                 if(outflag==0)//前面没输出 
203                 {
204                     letter[length]=w;
205                     length++;
206                 }
207             }
208         } 
209         front=w;
210     }
211     //
212     TakeWord();//从letter数组中取出字符进行分析
213 
214     fclose(stdin);//关闭文件
215     fclose(stdout);
216     return 0;
217 }

(4)结果

输入程序:

/*compare a and b then output the poccess result*/
int main()
{
    int a,b;
    a=5;
    b=4;
    if(a>=b)
    {
        a=a-b;
    }
    else
    {
        a=a+b;
    }
}

 输出的词法分析结果:

 

猜你喜欢

转载自www.cnblogs.com/Aiahtwo/p/12804065.html