词法分析程序(Lexical Analyzer)要求:
- 从左至右扫描构成源程序的字符流
- 识别出有词法意义的单词(Lexemes)
- 返回单词记录(单词类别,单词本身)
- 滤掉空格
- 跳过注释
- 发现词法错误
程序结构:
输入:字符流(什么输入方式,什么数据结构保存)
处理:
–遍历(什么遍历方式)
–词法规则
输出:单词流(什么输出形式)
–二元组
单词类别:
1.标识符(10)
2.无符号数(11)
3.保留字(一词一码)
4.运算符(一词一码)
5.界符(一词一码)
单词符号 |
种别码 |
单词符号 |
种别码 |
main |
1 |
, |
13 |
int |
2 |
; |
14 |
if |
3 |
( |
15 |
else |
4 |
) |
16 |
while |
5 |
{ |
17 |
do |
6 |
} |
18 |
< |
7 |
+ |
19 |
> |
8 |
- |
20 |
!= |
9 |
* |
21 |
>= |
10 |
/ |
22 |
<= |
11 |
= |
23 |
== |
12 |
|
|
1 #include <iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<stdlib.h> 5 using namespace std; 6 7 //关键字 8 string key[6]={"main","int","if","else","while","do"}; 9 10 //关键字的种别码 11 int keyNum[6]={1,2,3,4,5,6}; 12 13 //运算符和界符 14 string symbol[17]={"<",">","!=",">=","<=","==",",",";","(",")","{","}","+","-","*","/","="}; 15 16 //运算符和界符的种别码 17 int symbolNum[17]={7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23}; 18 19 //存放文件取出的字符 20 string letter[1000]; 21 22 int length; //保存程序中字符的数目 23 int num; 24 25 //判断运算符和界符 26 int isSymbol(string s){ 27 int i; 28 for(i=0;i<17;i++){ 29 if(s==symbol[i]) 30 return symbolNum[i]; 31 } 32 return 0; 33 } 34 35 //判断是否为数字 36 bool isNum(string s){ 37 if(s>="0" && s<="9") 38 return true; 39 return false; 40 } 41 42 //判断是否为字母 43 bool isLetter(string s){ 44 if(s>="a" && s<="z") 45 return true; 46 return false; 47 } 48 49 //判断是否为关键字,是返回种别码 50 int isKeyWord(string s){ 51 int i; 52 for(i=0;i<6;i++){ 53 if(s==key[i]) 54 return keyNum[i]; 55 } 56 return 0; 57 } 58 59 //返回单个字符的类型 60 int typeword(string str){ 61 if(str>="a" && str<="z") // 字母 62 return 1; 63 64 if(str>="0" && str<="9") //数字 65 return 2; 66 67 if(str==">"||str=="="||str=="<"||str=="!"||str==","||str==";"||str=="("||str==")"||str=="{"||str=="}"||str=="+"||str=="-"||str=="*"||str=="/") //判断运算符和界符 68 return 3; 69 } 70 //标识符的连接 71 string identifier(string s,int n){ 72 int j=n+1; 73 int flag=1; 74 75 while(flag){ 76 if(isNum(letter[j]) || isLetter(letter[j])){ 77 s=(s+letter[j]); 78 if(isKeyWord(s)){ 79 j++; 80 num=j; 81 return s; 82 } 83 j++; 84 }else{ 85 flag=0; 86 } 87 } 88 89 num=j; 90 return s; 91 } 92 93 //符号和界符的连接 94 string symbolStr(string s,int n){ 95 int j=n+1; 96 string str=letter[j]; 97 if(str==">"||str=="="||str=="<"||str=="!") { 98 s=(s+letter[j]); 99 j++; 100 } 101 num=j; 102 return s; 103 } 104 105 //数字的连接 106 string Number(string s,int n){ 107 int j=n+1; 108 int flag=1; 109 110 while(flag){ 111 if(isNum(letter[j])){ 112 s=(s+letter[j]); 113 j++; 114 }else{ 115 flag=0; 116 } 117 } 118 119 num=j; 120 return s; 121 } 122 123 //输出 124 void print(string s,int n){ 125 cout<<"("<<s<<","<<n<<")"<<endl; 126 } 127 128 //取单词 129 void TakeWord(){ 130 int k; 131 132 for(num=0;num<length;){ 133 string str1,str; 134 str=letter[num]; 135 k=typeword(str); 136 switch(k){ 137 case 1:{ 138 str1=identifier(str,num); 139 if(isKeyWord(str1)) 140 print(str1,isKeyWord(str1)); 141 else 142 print(str1,0); 143 break; 144 } 145 146 case 2:{ 147 str1=Number(str,num); 148 print(str1,24); 149 break; 150 } 151 152 case 3:{ 153 str1=symbolStr(str,num); 154 print(str1,isSymbol(str1)); 155 break; 156 } 157 158 } 159 } 160 } 161 162 int main(){ 163 char w; 164 int i,j; 165 166 freopen("s.txt","r",stdin); 167 168 length=0; 169 while(cin>>w){ 170 if(w!=' '){ 171 letter[length]=w; 172 length++; 173 } //去掉程序中的空格 174 } 175 176 TakeWord(); 177 178 fclose(stdin);//关闭文件 179 return 0; 180 }
实验文本:
实验结果:
该实验的代码是参考网上代码修改的,逻辑大概能理清,但是没有实现跳过注释的功能。