编译原理

sssssss

语义分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
/*
一个简单的翻译模式
P→ DS.
D→B; D
D→ε
B→int L | real L
L→id | L,id
S→ V := E H
H→;S | ε
E→E+T | T
T→( E )
T→id
V→id


start-> DS.
D->B; D
D->ε
B->int L { L.type := int }|real L { L.type := real }
L->id { A.Type := L.type enter(v.entry,L.type)} A
A-> ,idA { A1.Type := A.type enter(v.entry,A.type)}
A->ε

S→ V := E { gen( ":=", E.place,0,V.place) } H
H→;S | ε
E->T { R.i:=T.place} R {E.place:=R.s}
R->+T { R1.i:= newtemp; gen( "*", R.i, T.place , R1.i) } R {R.s:= R1.s; }
R-> ε {Rs=R.i}
T->( E ) { T.place := E.place}
T->id {T.place:=found (id)}
V->id {V.place:=found(id)}

*/

#include "语义分析.h"

int main()
{
char filename[20];

printf("请输入分析的文件名:");
gets(filename);
if((fin=fopen(filename,"r"))==NULL)
{
printf("不能打开文件.\n");
exit(0);
}

init(); //初始化
getsym(); //读第一个单词,将单词类别放入sym中,单字词值放入id中
start(); //开始按start->DS. 分析

if (sym==eeof)
{
printf("语法正确\n\n将中间代码保存到文件请输入文件名,否则回车");
gets(filename);
if(strlen(filename)<=0) return 0;
if((fout=fopen(filename,"w"))==NULL)
{
printf("不能打开文件.\n");
exit(0);
}
for (int cx1=0;cx1<cx;cx1++)
fprintf(fout,"(%s,%s,%s,%s)\n",code[cx1].f,code[cx1].l,code[cx1].r,code[cx1].t);
return 0;
}
else {printf("语法错1: . 后不能再有句子"); exit(0);}
fclose(fin);
fclose(fout);
return 0;
}



//初始化函数
void init()
{
int i;

/* 设置单字符符号 */
for (i=0; i<=255; i++)
{
ssym[i] = nul; //不正确的单字符符号为nul,先预置初值nul
}
ssym['+'] = plus;
ssym['-'] = minus;
ssym['*'] = times;
ssym['/'] = divide;
ssym['('] = lparen;
ssym[')'] = rparen;
ssym['.'] = period;
ssym[','] = comma;
ssym[';'] = semicolon;

/* 设置保留字名字 */
strcpy(&(word[0][0]), "real");
strcpy(&(word[1][0]), "int");

/* 设置保留字符号 */
wsym[0] = realsym;
wsym[1] = intsym;

tv=100; //临时变量指针初值,让Tx和tv的取值没有交集,区别到底是临时变变量和声明的变量
tx=0; //表指针初值
cx=0; //指令计数器

}

bool reals=false,ints=false;
/*
* 词法分析,获取一个符号
*/
int getsym()
{
int i,k;
ch=fgetc(fin);

if (ch==EOF) {sym=eeof; return 0;} //文件结束

while (ch==' ' || ch==10 || ch==13 || ch==9) /* 忽略空格、换行、回车和TAB */
ch=fgetc(fin);

if (ch>='a' && ch<='z')
{ /* 名字或保留字以a..z开头 ,*/
k = 0;
do
{
if(k<al) /* 符号的最大长度为al ,超长就截尾处理*/
{
a[k] = ch;
k++;
}
ch=fgetc(fin);
} while (ch>='a' && ch<='z' || ch>='0' && ch<='9');

a[k] = 0;
strcpy(id, a);
fseek(fin,-1,1);

for (i=0;i<norw;i++) /* 搜索当前符号是否为保留字 */
if (strcmp(id,word[i]) == 0)
break;
if (i <norw)
{
sym = wsym[i];
}
else
{
sym = ident; /* 搜索失败则,类型是标识符 */
}
}
else if(ch == ':') /* 检测赋值符号 */
{
ch=fgetc(fin);
if (ch == '=')
{
sym = becomes;
}
else
{
sym = nul; /* 不能识别的符号 */
}
}
else sym = ssym[ch]; /* 当符号不满足上述条件时,全部按照单字符符号处理 */
return 0;
}


/*
* 在符号表中加入一项
*/

void enter(enum symbol type)
{
tx=tx+1;
if (tx > txmax)
{
printf(" 符号表越界 "); /* 符号表越界 */
return;
}
for(int i=0;i<tx;++i){
if(strcmp(table[i].name, id)==0&&table[i].type==type){printf("禁止重复同名标识符\n");exit(0);}}
strcpy(table[tx].name, id); /* 全局变量id中已存有当前名字的名字,Tx为插入当前符号之前表尾指针 */
table[tx].type = type;
//for(int i=0;i<10;++i) printf("%c",id[i]);
//printf("\n%d\n",sym);

}



/*
* 查找名字的位置.
* 找到则返回在名字表中的位置,否则返回0.
*
* idt: 要查找的名字
* tx: 当前名字表尾指针,全局变量
*/
int found(char* idt)
{
int i;
strcpy(table[0].name, idt);
i = tx;
while (strcmp(table[i].name, idt) != 0)
{
i--;
}
return i;
}


/* 中间代码*/
int gen(enum symbol op, int arg1, int arg2,int result )
{
char temp1[al+1],temp2[al+1],temp3[al+1];
if(arg1>=100) //模拟申请临时变量
{
wsprintf(temp1,"T%d",arg1);
}
else
{
strcpy(temp1, table[arg1].name);
}

if(arg2>=100)
{
wsprintf(temp2,"T%d",arg2);
}
else
{
strcpy(temp2, table[arg2].name);
}

if(result>=100)
{
wsprintf(temp3,"T%d",result);
}
else
{
strcpy(temp3,table[result].name);
}

if (op==becomes)
{

printf("(:=,%s,%s,%s)\n",temp1,temp2,temp3);
writecode(":=",temp1,temp2,temp3);
}
else if (op==plus) //+运算
{

writecode("+",temp1,temp2,temp3);
printf("(+,%s,%s,%s)\n",temp1,temp2,temp3);
}
else if (op==minus) //+运算
{

writecode("-",temp1,temp2,temp3);
printf("(-,%s,%s,%s)\n",temp1,temp2,temp3);
}
else if (op==times) //+运算
{

writecode("*",temp1,temp2,temp3);
printf("(*,%s,%s,%s)\n",temp1,temp2,temp3);
}
else if (op==divide) //+运算
{

writecode("/",temp1,temp2,temp3);
printf("(/,%s,%s,%s)\n",temp1,temp2,temp3);
}

return 0;
}

//处理代码段
void writecode(char op[al+1], char arg1[al+1], char arg2[al+1],char result[al+1] )
{
if (cx >= cxmax)
{
printf("Program too long"); /* 程序过长 */
return ;
}
strcpy(code[cx].f, op);
strcpy(code[cx].l,arg1);
strcpy(code[cx].r,arg2);
strcpy(code[cx].t,result);
cx++;
return ;
}


/*分析产生式 P->DS. */

void start()
{
if (sym==intsym ||sym==realsym)
{
D();
S();
if (sym==period)
{
getsym();
return;
}
else
{printf("语法错2: 缺少程序结束."); exit(0);}
}
else
{printf("语法错3: 程序只能用int,和real开始,而且区分大小写"); exit(0);}
}

/*递归下降分析
D-> B; D
D->ε

*/
void D()
{
if (sym==intsym ||sym==realsym)
{
B();
if (ch=';')
{
getsym();
D();
}
else
{printf("语法错i"); exit(0);}
}
else if(sym==ident || sym==period) return;

else {printf("语法错ii"); exit(0);}
}

/*
B-> int L { L.type := int }|real L { L.type := real }
*/
void B()
{
if (sym==intsym )
{
getsym();
L(intsym);
}
else if (sym==realsym)
{
getsym();
L(realsym);
}else
{printf("语法错iii"); exit(0);}
}


/*
L-> id { A.Type := L.type enter(v.entry,L.type)} A V.entry通过全局变量tx隐性传递
*/
void L(enum symbol type)
{
if (sym==ident)
{
enter(type);
getsym();
A(type);
}
else
{printf("语法错iv"); exit(0);}
}


/*
A-> ,id A { A1.Type := A.type enter(v.entry,A.type)}
A->ε
*/

void A(enum symbol type)
{
if (sym==comma) //当前单词为,
{
getsym();
if (sym==ident)
{
enter(type);
getsym();
A(type);
}
else
{printf("语法错v"); exit(0);}
}
else if (sym== semicolon) return ;//当前单词为;即A的follow集元素,相当于进行A->ε
else
{printf("语法错vi"); exit(0);}
}



/*
S→ V := E { gen( ":=", E.place,0,V.place) } H
*/
void S()
{
int vplace,Eplace;
if (sym==ident)
{
vplace=V();
//getsym();
if (sym==becomes) //当前单词为:=
{
getsym();
Eplace=E();
if(reals&&ints) {printf("语法错vvi"); exit(0);}
gen(becomes,Eplace,-1,vplace);
H();

}
else
{printf("语法错vii"); exit(0);}
}
else {printf("语法错viii"); exit(0);}
}

/*
H→;S | ε
*/
void H()
{
if (sym==semicolon) //当前单词为indent类型
{
reals=false,ints=false;
getsym();
S();
}
else if (sym==period) return ;
else
{printf("语法错ivv"); exit(0);}
}
/*
E->T { R.i:=T.place} R {E.place:=R.s}
*/

int E()
{
int ri,tplace,Rs;
if (sym==ident || sym== lparen)
{
tplace=T();
ri=tplace;
Rs=R(ri);
}
else
{printf("语法错vv"); exit(0);}
return Rs;
}

/*
R->+T { R1.i:= newtemp; gen( "*", R.i, T.place , R1.i) } R {R.s:= R1.s; }
R-> ε {R.s=R.i}
*/

int R(int Ri)
{
int Rs,tplace;
if (sym==plus)
{
getsym();
tplace=T();
if(reals&&ints) {printf("运算变量类型不一致"); exit(0);}
tv=tv+1; //生成临时变量
gen(plus,Ri,tplace,tv);
Rs=R(tv);
}
else if(sym==minus)
{
getsym();
tplace=T();
if(reals&&ints) {printf("运算变量类型不一致"); exit(0);}
tv=tv+1; //生成临时变量
gen(minus,Ri,tplace,tv);
Rs=R(tv);
}
else if (sym== semicolon || sym==rparen|| sym==period)
{
Rs=Ri;
}
else {printf("语法错vvi"); exit(0);}
return Rs;
}

/*

T->( E ) { T.place := E.place}
T->id {F.place:=found (id)}
*/
int T()
{
int ri,tplace,Rs;
if (sym==ident || sym== lparen)
{
tplace=F();
ri=tplace;
Rs=P(ri);
}
else
{printf("语法错vvii"); exit(0);}
return Rs;
}
int F()
{
int Fplace;
if (sym== lparen)
{
getsym();
Fplace=E();
if (sym== rparen)
getsym();
else
{
printf("语法错,缺)"); exit(0);
}
}
else if (sym==ident)
{
Fplace=found (id);
if (Fplace==0) {printf("变量没有声明"); exit(0);}
if(table[Fplace].type==realsym) reals=true;
else ints=true;
getsym();
}
else{printf("语法错,缺("); exit(0);}
return Fplace;
}

int P(int Ri)
{
int Rs,tplace;
if (sym==times)
{
getsym();
tplace=F();
if(reals&&ints) {printf("运算变量类型不一致"); exit(0);}
tv=tv+1; //生成临时变量
gen(times,Ri,tplace,tv);
Rs=P(tv);
}
else if(sym==divide)
{
getsym();
tplace=F();
if(reals&&ints) {printf("运算变量类型不一致"); exit(0);}
tv=tv+1; //生成临时变量
gen(divide,Ri,tplace,tv);
Rs=P(tv);
}
else if (sym== semicolon || sym==rparen|| sym==period||sym==plus||sym==minus)
{
Rs=Ri;
}
else {printf("%d语法错vviii",sym); exit(0);}
return Rs;
}

/*

V->id {V.place:=found(id)}
*/
int V()
{
int Vplace;
if (sym==ident)
{
Vplace=found (id);
if (Vplace==0) {printf("变量没有声明"); exit(0);}
if(table[Vplace].type==realsym) reals=true;
else ints=true;
getsym();
}
else{printf("语法错ivvv"); exit(0);}
return Vplace;
}

语义分析.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <stdio.h>
#include<dos.h>
#include<stdlib.h>
#include<string.h>
//#include <iostream.h>
#include<ctype.h>
#include <windows.h>

#define txmax 100 /* 锟斤拷锟脚憋拷锟斤拷锟斤拷锟斤拷锟� */
#define al 10 /* 锟斤拷锟脚碉拷锟斤拷蟪ざ锟� */
#define tvmax 500 /* 锟斤拷锟斤拷芄锟斤拷锟斤拷锟斤拷锟斤拷时锟斤拷锟斤拷取值锟斤拷围[100, tvmax] */
#define norw 2 /* 锟截硷拷锟街革拷锟斤拷 */
#define cxmax 500 /* 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟� */

int tx; //锟斤拷锟街憋拷指锟斤拷, 取值锟斤拷围[0, txmax-1]
int tv ; //锟斤拷时锟斤拷锟斤拷锟斤拷锟斤拷


/* 锟斤拷锟斤拷 */
enum symbol {
nul, eeof, ident, plus, minus , times, lparen,divide,
rparen, comma, semicolon, becomes, period, realsym, intsym,
};

enum symbol sym; /* 锟斤拷前锟侥凤拷锟斤拷 */
char ch; /* 锟斤拷取锟街凤拷锟侥伙拷锟斤拷锟斤拷锟斤拷getch 使锟斤拷 */
char id[al+1]; /* 锟斤拷前ident, 锟斤拷锟斤拷锟揭伙拷锟斤拷纸锟斤拷锟斤拷诖锟斤拷0 */
char a[al+1]; /* 锟斤拷时锟斤拷锟斤拷, 锟斤拷锟斤拷锟揭伙拷锟斤拷纸锟斤拷锟斤拷诖锟斤拷0 */

/* 锟斤拷锟脚憋拷锟结构 */
struct tablestruct
{
char name[al]; /* 锟斤拷锟斤拷 */
enum symbol type; // 锟斤拷锟斤拷
};

struct tablestruct table[txmax]; /* 锟斤拷锟脚憋拷 */

char word[norw][al]; /* 锟斤拷锟斤拷锟斤拷 */
enum symbol wsym[norw]; /* 锟斤拷锟斤拷锟街讹拷应锟侥凤拷锟斤拷值 */
enum symbol ssym[256]; /* 锟斤拷锟街凤拷锟侥凤拷锟斤拷值锟斤拷散锟叫憋拷 */

int cx; /* 锟斤拷元式锟斤拷锟斤拷指锟斤拷, 取值锟斤拷围[0, cxmax-1]*/
struct instruction
{
char f[al+1]; /* 锟斤拷锟斤拷锟斤拷 */
char l[al+1]; /* 锟斤拷锟斤拷锟斤拷锟� */
char r[al+1]; /* 锟揭诧拷锟斤拷锟斤拷*/
char t[al+1]; /* 锟斤拷锟� */
};
struct instruction code[cxmax]; /* 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟� */

FILE* fin;
FILE* fout;

int getsym();
void enter(enum symbol type);
void init();
int found(char* idt);
int gen(enum symbol op, int arg1, int arg2,int result ); //锟叫硷拷锟斤拷锟斤拷锟斤拷
void writecode(char *op, char *arg1, char *arg2,char *result ); //写锟斤拷锟斤拷
void start();
void D();
void B();
void L(enum symbol type);
void A(enum symbol type);
void S();
void H();
int E();
int R(int Ri);
int T();
int V();
int F();
int P(int Ri);