编译原理实验-词法分析器
⼀、实验⽬的
设计、编制、调试⼀个词法分析程序,对单词进⾏识别和编码,加深对词法分析原理的理解。
⼆、实验内容
1.选定语⾔,编辑任意的源程序保存在⽂件中;
2.对⽂件中的代码预处理,删除制表符、回车符、换⾏符、注释、多余的空格并将预处理后的代码保存在⽂件中;
3.扫描处理后的源程序,分离各个单词符号,显⽰分离的单词类型。
三、实验思路
对于实验内容1,选择编写c语⾔的源程序存放在中,设计⼀个c语⾔的词法分析器,主要包含三部分,⼀部分是预处理函数,第⼆部分是扫描判断单词类型的函数,第三部分是主函数,调⽤其它函数;
对于实验内容2,主要实现在预处理函数processor()中,使⽤⽂档操作函数打开源程序⽂件(),去
除两种类型(“//”,“/*…*/”)的注释、多余的空格合并为⼀个、换⾏符、回车符等,然后将处理后的保存在另⼀个新的⽂件()中,最后关闭⽂档。
对于实验内容3,打开处理后的⽂件,然后调⽤扫描函数,从⽂件⾥读取⼀个单词调⽤判断单词类型的函数与之前建⽴的符号表进⾏对⽐判断,最后格式化输出。
四、编码设计
代码参考了两篇博主的,做了部分改动,添加了预处理函数等
1 #include<iostream>
2 #include<fstream>
3 #include<cstdio>
4 #include<cstring>
5 #include<string>
6 #include<cstdlib>
7
8using namespace std;
9
10int aa;// fseek的时候⽤来接着的
11string  word="";
12string  reserved_word[20];//保留
13char buffer;//每次读进来的⼀个字符
14int num=0;//每个单词中当前字符的位置
15int line=1; //⾏数
16int row=1; //列数,就是每⾏的第⼏个
17bool flag; //⽂件是否结束了
18int flag2;//单词的类型
19
20
21//预处理函数
22int processor(){//预处理函数
23 FILE *p;
24int  falg = 0,len,i=0,j=0;
25char str[1000],str1[1000],c;
26if((p=fopen("","rt"))==NULL){
27  printf("⽆法打开要编译的源程序");
28return0;
29  }
30else{
31//fgets(str,1000,p);
32while((c=getc(p))!=EOF){
33    str[i++] = c;
34  }
35  fclose(p);
36  str[i] = '\0';
37for(i=0;i<strlen(str);i++){
38if(str[i]=='/'&&str[i+1]=='/'){
39while(str[i++]!='\n'){}
40    }//单⾏注释
41else if(str[i]=='/'&&str[i+1]=='*'){
42while(!(str[i]=='*'&&str[i+1]=='/')){i++;}
43    i+=2;
44    }//多⾏注释
45else if(str[i]==''&&str[i+1]==''){
46while(str[i]==''){i++;}
47    i--;
48if(str1[j-1]!='')
49        str1[j++]='';
50    }//多个空格,去除空格
51else if(str[i]=='\n') {
52if(str1[j-1]!='')
53        str1[j++]='';
54    }//换⾏处理,
55else if(str[i]==9){
56while(str[i]==9){
57      i++;
58    }
59if(str1[j-1]!='')
60      str1[j++]='';
61    i--;
62    }//tab键处理
63else str1[j++] = str[i];//其他字符处理
64  }
65  str1[j] = '\0';
66if((p = fopen("","w"))==NULL){ 67    printf("can not find it!");
68return0;
69  }
70else{
71if(fputs(str1,p)!=0){
72    printf("预处理失败!");
73    }
74else printf("预处理成功!");
75  }
76  fclose(p);
77  }
78return0;
79  }
80
81//设置保留字
82void set_reserve()
83 {
84    reserved_word[1]="return";
85    reserved_word[2]="def";
86    reserved_word[3]="if";
87    reserved_word[4]="else";
88    reserved_word[5]="while";
89    reserved_word[6]="return";
90    reserved_word[7]="char";
91    reserved_word[8]="for";
92    reserved_word[9]="and";
93    reserved_word[10]="or";
94    reserved_word[11]="int";
95    reserved_word[12]="bool";
96 }
97
98//看这个字是不是字母
99bool judge_word(char x)
100 {
101if(x>='a' && x<='z' || x>='A' && x<='Z' ){ 102return true;
103    }
104else return false;
105 }
106
107//看这个字是不是数字
108bool judge_number(char x)
109 {
110if(x>='0' && x<='9'){
111return true;
112    }
113else return false;
114 }
115
116//看这个字符是不是界符
117bool judge_jiefu(char x)
118 {
119if(x=='('||x==')'||x==','||x==';'||x=='{'||x=='}'){ 120return true;
121    }
122else return false;
123 }
124
125
126//加减乘
127bool judge_yunsuanfu1(char x)
128 {
129if(x=='+'||x=='-'||x=='*')
130    {
131return true;
132    }
133else return false;
134 }
135
136//等于赋值,⼤于⼩于⼤于等于,⼩于等于,⼤于⼩于
137bool judge_yunsuannfu2(char x)
138 {
139if(x=='='|| x=='>'||x=='<'||x=='&'||x=='||'){
140return true;
141    }
142else return false;
143 }
144
145
146//这个最⼤的函数的总体作⽤是从⽂件⾥读⼀个单词
147int scan(FILE *fp)
148 {
149    buffer=fgetc(fp);//读取⼀个字符
150if(feof(fp)){//检测结束符
151        flag=0;return0;
152    }
153else if(buffer=='')
154    {
155        row++;
156return0;
157    }
158else if(buffer=='\n')
159    {
160        row=1;
161return0;
162    }
163//如果是字母开头或'_' 看关键字还是普通单词
164else if(judge_word(buffer) || buffer=='_')
165    {
166        word+=buffer;
167        row++;
168while((buffer=fgetc(fp)) && (judge_word(buffer) || judge_number(buffer) || buffer=='_'))
169        {
170            word+=buffer;
171            row++;
172        }
173if(feof(fp)){
174                flag=0;
175return1;
176        }
177for(int i=1;i<=12;i++){
178if(word==reserved_word[i]){
179                aa=fseek(fp,-1,SEEK_CUR);//如果执⾏成功,stream将指向以fromwhere为基准,偏移offset(指针偏移量)个字节的位置,函数返回0。180return3;
181            }
182        }
183        aa=fseek(fp,-1,SEEK_CUR);
184return1;
185    }
186
187//开始是加减乘⼀定是类型4
188else if(judge_yunsuanfu1(buffer))
189    {
190        word+=buffer;
191        row++;
192return4;
193    }
194
195//开始是数字就⼀定是数字
196else if(judge_number(buffer))
197    {
198        word+=buffer;
199        row++;
200while((buffer=fgetc(fp)) && judge_number(buffer))
201        {
202            word+=buffer;
203            row++;
204        }
205if(feof(fp)){
206            flag=0;
207return2;
208        }
209        aa=fseek(fp,-1,SEEK_CUR);
210return2;
211    }
212
213//检验界符
214else if(judge_jiefu(buffer))
216        word+=buffer;
217        row++;
218return6;
219    }
220
221//检验 <=、  >=、  <>、  == =、 <、>
222else if(judge_yunsuannfu2(buffer))
223    {
224        row++;
225        word+=buffer;
226if(buffer=='<')  //为了检验题⽬中的<> <=
227        {
228            buffer=fgetc(fp);
229if(buffer=='>' || buffer=='=')
230            {
231                word+=buffer;
232                row++;
233return5;
234            }
235        }
236//检验  >= ==
237else{
238            buffer=fgetc(fp);
239if(buffer=='=')
240            {
241                word+=buffer;
242                row++;
243return5;
244            }
245        }
246if(feof(fp)){
247                flag=0;
248        }
249        aa=fseek(fp,-1,SEEK_CUR);
250return4;
251    }
252
253//⾸字符是/ 有可能是除号也有可能是注释
254else if(buffer=='/')
255    {
256        row++;
257        word+=buffer;
258        buffer=fgetc(fp);
259        aa=fseek(fp,-1,SEEK_CUR);
260return4;
261    }
262
263else {
264        word+=buffer;
265        row++;
266return -1;
267    }
268 }
269
270int main()
271 {
272    set_reserve();//设置保留字
273    processor();
274    cout<<"open "<<""<<endl;
275    flag=1;
276    FILE *fp;
277if(!(fp=fopen("","r")))
278    {
279        cout<<"not found the file or other error "<<endl;
280        flag=0;
281    }
282
283while(flag==1)
284    {
285//flag2 返回的类型
286        flag2=scan(fp);//反复调⽤函数提取单词
287
288if(flag2==1)
printf怎么加endl
289        {
290            cout<<"type:1 identifier      "<<word<<endl;
291if(word.length()>20)
292            cout<<"ERROR Identifier length cannot exceed 20 characters"<<endl; 293            ase(word.begin(),d());
294        }
295else if(flag2==3)
296        {
297            cout<<"type:3 reserved word  "<<word<<endl;
298            ase(word.begin(),d());
300else if(flag2==4)
301        {
302            cout<<"type:4 unary_operator  "<<word<<endl;
303            ase(word.begin(),d());
304        }
305else if(flag2==2)
306        {
307            cout<<"type:2 positive number "<<word<<endl;
308//if(word[0]=='0')
309//cout<<"ERROR: The first digit cannot be 0!"<<endl;
310            ase(word.begin(),d());
311        }
312else if(flag2==6)
313        {
314            cout<<"type:6 Separator      "<<word<<endl;
315            ase(word.begin(),d());
316        }
317else if(flag2==5)
318        {
319            cout<<"type:5 double_operator "<<word<<endl;
320            ase(word.begin(),d());
321        }
322//⾮法字符
323else if(flag2==-1)
324        {
325            cout<<"Illegal character      "<<word<<endl;
326            ase(word.begin(),d());
327        }
328    }
329
330int a=fclose(fp);
331        cout<<"press e to close"<<endl;
332char end;
333while(cin>>end && end!='e'){
334            cout<<"只有e可以关闭"<<endl;
335        }
336return0;
337 }
五、实验结果
1.下⾯是编写的⼀段源程序,命名为
2.经过程序执⾏后,在项⽬⽬录下⽣成了⼀个新的名为⽂件
⽂件内容如下,经过预处理后去除了多于内容

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。