编译原理实验-词法分析器
⼀、实验⽬的
设计、编制、调试⼀个词法分析程序,对单词进⾏识别和编码,加深对词法分析原理的理解。
⼆、实验内容
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怎么加endl289 {
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小时内删除。
发表评论