编写词法分析器
词法分析器功能
输入源程序、输出单词符号(其表示形式为:(单词种别,单词自身的值)
预处理:删除注释,删除续换行符,换行符,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; } }
输出的词法分析结果: