-
Notifications
You must be signed in to change notification settings - Fork 0
/
godweiyang.cpp
1279 lines (1191 loc) · 40.6 KB
/
godweiyang.cpp
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
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "compile.h"
/*
* 初始化
*/
#define norw 13 /* 保留字个数 */
#define txmax 100 /* 符号表容量 */
#define nmax 14 /* 数字的最大位数 */
#define al 10 /* 标识符的最大长度 */
#define maxerr 30 /* 允许的最多错误数 */
#define addrmax 2048 /* 地址上界*/
#define levmax 3 /* 最大允许过程嵌套声明层数*/
#define cxmax 200 /* 最多的虚拟机代码数 */
#define stacksize 500 /* 运行时数据栈元素最多为500个 */
#define symnum 37
#define fctnum 9
/* 虚拟机代码结构 */
struct instruction {
enum fct f; /* 虚拟机代码指令 */
int l; /* 引用层与声明层的层次差 */
int a; /* 根据f的不同而不同 */
};
char ch; /* 存放当前读取的字符,getch 使用 */
enum symbol sym; /* 当前的符号 */
char id[al+1]; /* 当前ident,多出的一个字节用于存放0 */
int num; /* 当前number */
int cc, ll; /* getch使用的计数器,cc表示当前字符(ch)的位置 */
int linenum;
int cx; /* 虚拟机代码指针, 取值范围[0, cxmax-1]*/
char line[81]; /* 读取行缓冲区 */
char a[al+1]; /* 临时符号,多出的一个字节用于存放0 */
struct instruction code[cxmax]; /* 存放虚拟机代码的数组 */
char word[norw][al]; /* 保留字 */
enum symbol wsym[norw]; /* 保留字对应的符号值 */
enum symbol ssym[256]; /* 单字符的符号值 */
char mnemonic[fctnum][5]; /* 虚拟机代码指令名称 */
bool declbegsys[symnum]; /* 表示声明开始的符号集合 */
bool statbegsys[symnum]; /* 表示语句开始的符号集合 */
bool facbegsys[symnum]; /* 表示因子开始的符号集合 */
char errorinfo[100][100];
bool debug;
/* 符号表结构 */
struct tablestruct {
char name[al]; /* 名字 */
enum object kind; /* 类型:const,var或procedure */
int val; /* 数值,仅const使用 */
int level; /* 所处层,仅const不使用 */
int adr; /* 地址,仅const不使用 */
int size; /* 需要分配的数据区空间, 仅procedure使用 */
};
struct tablestruct table[txmax]; /* 符号表 */
FILE* fin; /* 输入源文件 */
FILE* ftable; /* 输出符号表 */
FILE* fcode; /* 输出虚拟机代码 */
FILE* foutput; /* 输出文件及出错示意(如有错)、各行对应的生成代码首地址(如无错) */
FILE* fresult; /* 输出执行结果 */
FILE* ferrors; /* 输出错误 */
FILE* fdebug; /* 输出调试信息 */
char fname[al];
int err; /* 错误计数器 */
void init() {
/* 设置单字符符号 */
memset(ssym, 0, sizeof ssym);
ssym['%'] = mod;
ssym['+'] = plus;
ssym['-'] = minus;
ssym['*'] = times;
ssym['/'] = slash;
ssym['('] = lparen;
ssym[')'] = rparen;
ssym['{'] = lbrace;
ssym['}'] = rbrace;
ssym['='] = becomes;
ssym['$'] = period;
ssym[';'] = semicolon;
/* 设置保留字名字,按照字母顺序,便于二分查找 */
strcpy(word[0], "call");
strcpy(word[1], "const");
strcpy(word[2], "else");
strcpy(word[3], "for");
strcpy(word[4], "func");
strcpy(word[5], "if");
strcpy(word[6], "in");
strcpy(word[7], "odd");
strcpy(word[8], "print");
strcpy(word[9], "read");
strcpy(word[10], "repeat");
strcpy(word[11], "var");
strcpy(word[12], "while");
/* 设置保留字符号 */
wsym[0] = callsym;
wsym[1] = constsym;
wsym[2] = elsesym;
wsym[3] = forsym;
wsym[4] = funcsym;
wsym[5] = ifsym;
wsym[6] = insym;
wsym[7] = oddsym;
wsym[8] = printsym;
wsym[9] = readsym;
wsym[10] = repeatsym;
wsym[11] = varsym;
wsym[12] = whilesym;
/* 设置指令名称 */
strcpy(mnemonic[lit], "lit");
strcpy(mnemonic[opr], "opr");
strcpy(mnemonic[lod], "lod");
strcpy(mnemonic[sto], "sto");
strcpy(mnemonic[cal], "cal");
strcpy(mnemonic[ini], "int");
strcpy(mnemonic[jmp], "jmp");
strcpy(mnemonic[jpc], "jpc");
strcpy(mnemonic[jeq], "jeq");
/* 设置符号集 */
memset(declbegsys, false, sizeof declbegsys);
memset(statbegsys, false, sizeof statbegsys);
memset(facbegsys, false, sizeof facbegsys);
/* 设置声明开始符号集 */
declbegsys[constsym] = true;
declbegsys[varsym] = true;
declbegsys[funcsym] = true;
/* 设置语句开始符号集 */
statbegsys[callsym] = true;
statbegsys[ifsym] = true;
statbegsys[whilesym] = true;
statbegsys[readsym] = true;
statbegsys[printsym] = true;
statbegsys[ident] = true;
statbegsys[forsym] = true;
statbegsys[repeatsym] = true;
/* 设置因子开始符号集 */
facbegsys[ident] = true;
facbegsys[number] = true;
facbegsys[lparen] = true;
strcpy(errorinfo[0], "声明符号后面缺少标识符");
strcpy(errorinfo[1], "缺少';'");
strcpy(errorinfo[2], "语句或者函数声明开始符号错误");
strcpy(errorinfo[3], "缺少语句开始符号");
strcpy(errorinfo[4], "缺少语句结束符号");
strcpy(errorinfo[5], "编译未完成");
strcpy(errorinfo[6], "标识符未声明");
strcpy(errorinfo[7], "赋值语句等号左侧不是变量");
strcpy(errorinfo[8], "缺少赋值符号");
strcpy(errorinfo[9], "缺少分号");
strcpy(errorinfo[10], "语句结束符号错误");
strcpy(errorinfo[11], "缺少关系运算符");
strcpy(errorinfo[12], "标识符不能是函数");
strcpy(errorinfo[13], "因子开始符号错误");
strcpy(errorinfo[14], "数字位数超出范围");
strcpy(errorinfo[15], "数字大小超出范围");
strcpy(errorinfo[16], "缺少')'");
strcpy(errorinfo[17], "缺少'('");
strcpy(errorinfo[18], "变量未声明");
strcpy(errorinfo[19], "function后面缺少'()'");
strcpy(errorinfo[20], "缺少'{'");
strcpy(errorinfo[21], "缺少'}'");
strcpy(errorinfo[22], "缺少'in'");
strcpy(errorinfo[23], "for循环缺少左边界");
strcpy(errorinfo[24], "for循环缺少右边界");
strcpy(errorinfo[25], "for循环缺少'...'");
strcpy(errorinfo[30], "函数嵌套层数过多");
strcpy(errorinfo[31], "call声明后面缺少过程名");
strcpy(errorinfo[32], "常量声明中的=后应是数字");
strcpy(errorinfo[33], "repeat后缺少while");
err = 0;
cc = ll = cx = 0;
ch = ' ';
linenum = 0;
foutput = fopen("foutput.txt", "w");
ftable = fopen("ftable.txt", "w");
ferrors = fopen("ferror.txt", "w");
fcode = fopen("fcode.txt", "w");
fresult = fopen("fresult.txt", "w");
fdebug = fopen("fdebug.txt", "w");
}
void compile() {
fin = fopen("C:\\Users\\10152130143\\Desktop\\sw_compiler-master\\sw_lcm.txt", "r");
//fin = stdin;
bool nxtlev[symnum];
init(); /* 初始化 */
getsym();
addset(nxtlev, declbegsys, statbegsys, symnum);
nxtlev[period] = true;
block(0, 0, nxtlev); /* 处理分程序 */
if (sym != period) {
error(5);
}
if (err == 0) {
fprintf(foutput,"\n===编译成功!===\n");
} else {
fprintf(ferrors,"\n本代码共有 %d 个错误!\n",err);
}
debug = true;
listall(); /* 输出所有代码 */
interpret(); /* 调用解释执行程序 */
fclose(fcode);
fclose(ftable);
fclose(foutput);
fclose(fin);
fclose(fresult);
}
/*
* 用数组实现集合的集合运算
*/
int inset(int e, bool* s) {
return s[e];
}
void addset(bool* sr, bool* s1, bool* s2, int n) {
for (int i = 0; i < n; i++) {
sr[i] = s1[i] || s2[i];
}
}
void subset(bool* sr, bool* s1, bool* s2, int n) {
for (int i = 0; i < n; i++) {
sr[i] = s1[i] && (!s2[i]);
}
}
void mulset(bool* sr, bool* s1, bool* s2, int n) {
for (int i = 0; i < n; i++) {
sr[i] = s1[i] && s2[i];
}
}
/*
* 出错处理,打印出错位置和错误编码
*/
void error(int n) {
fprintf(ferrors, "第 %d 行 错误: %s\n", linenum, errorinfo[n]);
err = err + 1;
if (err > maxerr) {
exit(1);
}
}
/*
* 过滤空格,读取一个字符
* 每次读一行,存入line缓冲区,line被getsym取空后再读一行
* 被函数getsym调用
*/
void getch() {
if (cc == ll) { /* 判断缓冲区中是否有字符,若无字符,则读入下一行字符到缓冲区中 */
if (feof(fin)) {
ch = '$';
return;
}
ll = 0;
cc = 0;
linenum++;
fprintf(foutput, "%d ", cx);
ch = ' ';
while (ch != 10) {
if (EOF == fscanf(fin,"%c", &ch)) {
line[ll] = 0;
break;
}
fprintf(foutput, "%c", ch);
line[ll] = ch;
ll++;
}
}
ch = line[cc];
cc++;
}
/*
* 词法分析,获取一个符号
*/
void getsym() {
int i,j,k;
while (ch == ' ' || ch == 10 || ch == 9) { /* 过滤空格、换行和制表符 */
getch();
}
if (ch == '$') sym = period;
else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { /* 当前的单词是标识符或是保留字 */
k = 0;
do {
if(k < al) {
a[k] = ch;
k++;
}
getch();
} while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'));
a[k] = 0;
strcpy(id, a);
i = 0;
j = norw - 1;
do { /* 搜索当前单词是否为保留字,使用二分法查找 */
k = (i + j) / 2;
if (strcmp(id,word[k]) <= 0) {
j = k - 1;
}
if (strcmp(id,word[k]) >= 0) {
i = k + 1;
}
} while (i <= j);
if (i-1 > j) { /* 当前的单词是保留字 */
sym = wsym[k];
} else { /* 当前的单词是标识符 */
sym = ident;
}
} else {
if (ch >= '0' && ch <= '9') { /* 当前的单词是数字 */
k = 0;
num = 0;
sym = number;
do {
num = 10 * num + ch - '0';
k++;
getch();;
} while (ch >= '0' && ch <= '9'); /* 获取数字的值 */
k--;
if (k > nmax) { /* 数字位数太多 */
error(14);
}
} else {
if (ch == '.') { /* 检测...符号 */
getch();
if (ch == '.') {
getch();
if (ch == '.') {
sym = range;
getch();
} else {
sym = nul;
}
} else {
sym = nul; /* 不能识别的符号 */
}
} else if (ch == '<') {
getch();
if (ch == '=') {
sym = leq;
getch();
} else {
sym = lss;
}
} else if (ch == '>') {
getch();
if (ch == '=') {
sym = geq;
getch();
} else {
sym = gtr;
}
} else if (ch == '=') {
getch();
if (ch == '=') {
sym = eql;
getch();
} else
sym = becomes;
} else if (ch == '!') {
getch();
if (ch == '=') {
sym = neq;
getch();
} else
sym = nul;
} else if (ch == '/') {
getch();
if (ch == '/') { //行注释
cc = ll;
getch();
getsym();
} else if (ch == '*') { //块注释
int flag = 0;
while (ch != '$') {
getch();
if (ch == '*') flag = 1;
else if (ch == '/' && flag == 1) {
getch();
getsym();
break;
} else {
flag = 0;
}
}
if (ch == '$') sym = period;
} else { //除号
sym = slash;
getch();
}
} else if (ch == '+') {
getch();
if (ch == '+') {
sym = add;
getch();
} else {
sym = plus;
}
} else if (ch == '-') {
getch();
if (ch == '-') {
sym = sub;
getch();
} else {
sym = minus;
}
} else {
sym = ssym[ch];
if (sym != period)
getch();
}
}
}
}
/*
* 生成虚拟机代码
*
* x: instruction.f;
* y: instruction.l;
* z: instruction.a;
*/
void gen(enum fct x, int y, int z ) {
if (cx >= cxmax) {
printf("生成的虚拟机代码程序过长!\n"); /* 生成的虚拟机代码程序过长 */
exit(1);
}
if ( z >= addrmax) {
printf("地址偏移越界!\n"); /* 地址偏移越界 */
exit(1);
}
code[cx].f = x;
code[cx].l = y;
code[cx].a = z;
cx++;
}
/*
* 测试当前符号是否合法
*
* 在语法分析程序的入口和出口处调用测试函数test,
* 检查当前单词进入和退出该语法单位的合法性
*
* s1: 需要的单词集合
* s2: 如果不是需要的单词,在某一出错状态时,
* 可恢复语法分析继续正常工作的补充单词符号集合
* n: 错误号
*/
void test(bool* s1, bool* s2, int n) {
if (!inset(sym, s1)) {
error(n);
/* 当检测不通过时,不停获取符号,直到它属于需要的集合或补救的集合 */
while ((!inset(sym,s1)) && (!inset(sym,s2))) {
getsym();
}
}
}
/*
* 编译程序主体
*
* lev: 当前分程序所在层
* tx: 符号表当前尾指针
* fsys: 当前模块后继符号集合
*/
void block(int lev, int tx, bool* fsys) {
int i;
int dx; /* 记录数据分配的相对地址 */
int tx0; /* 保留初始tx */
int cx0; /* 保留初始cx */
bool nxtlev[symnum]; /* 在下级函数的参数中,符号集合均为值参,但由于使用数组实现,
传递进来的是指针,为防止下级函数改变上级函数的集合,开辟新的空间
传递给下级函数*/
dx = 3; /* 三个空间用于存放静态链SL、动态链DL和返回地址RA */
tx0 = tx; /* 记录本层标识符的初始位置 */
table[tx].adr = cx; /* 记录当前层代码的开始位置 */
gen(jmp, 0, 0); /* 产生跳转指令,跳转位置未知暂时填0 */
if (lev > 1) { /* 嵌套层数过多 */
error(30);
}
if (sym == nul) sym = period;
do {
while (sym == varsym || sym == constsym) { /* 遇到变量声明符号,开始处理变量声明 */
if (sym == varsym) {
getsym();
vardeclaration(&tx, lev, &dx);
if (sym == semicolon) {
getsym();
} else {
error(9); /* 漏掉了分号 */
}
} else {
getsym();
constdeclaration(&tx, lev, &dx); /* dx的值会被constdeclaration改变,使用指针 */
if (sym == semicolon) { /* 遇到分号结束定义常量 */
getsym();
} else {
error(9); /* 漏掉了分号 */
}
}
}
while (sym == funcsym) { /* 遇到过程声明符号,开始处理过程声明 */
getsym();
if (sym == ident) {
enter(function, &tx, lev, &dx); /* 填写符号表 */
getsym();
} else {
error(0); /* procedure后应为标识符 */
}
if (sym == lparen) getsym();
else error(19);
if (sym == rparen) getsym();
else error(19);
if (sym == lbrace) getsym();
else error(20);
memcpy(nxtlev, fsys, sizeof(bool) * symnum);
nxtlev[rbrace] = true;
block(lev + 1, tx, nxtlev); /* 递归调用 */
if(sym == rbrace) {
getsym();
memcpy(nxtlev, statbegsys, sizeof(bool) * symnum);
nxtlev[funcsym] = true;
test(nxtlev, fsys, 6);
} else {
error(38); /* 漏掉了'}' */
}
}
if (sym == period) break;
memcpy(nxtlev, statbegsys, sizeof(bool) * symnum);
nxtlev[ident] = true;
test(nxtlev, declbegsys, 7);
} while (inset(sym, declbegsys)); /* 直到没有声明符号 */
code[table[tx0].adr].a = cx; /* 把前面生成的跳转语句的跳转位置改成当前位置 */
table[tx0].adr = cx; /* 记录当前过程代码地址 */
table[tx0].size = dx; /* 声明部分中每增加一条声明都会给dx增加1,声明部分已经结束,dx就是当前过程数据的size */
cx0 = cx;
gen(ini, 0, dx); /* 生成指令,此指令执行时在数据栈中为被调用的过程开辟dx个单元的数据区 */
for (i = 1; i <= tx; i++) {
switch (table[i].kind) {
case constant:
fprintf(ftable, "%d const %s ", i, table[i].name);
fprintf(ftable, "val=%d\n", table[i].val);
break;
case variable:
fprintf(ftable, "%d var %s ", i, table[i].name);
fprintf(ftable, "lev=%d addr=%d\n", table[i].level, table[i].adr);
break;
case function:
fprintf(ftable,"%d func %s ", i, table[i].name);
fprintf(ftable,"lev=%d addr=%d size=%d\n", table[i].level, table[i].adr, table[i].size);
break;
}
}
fprintf(ftable,"\n");
/* 语句后继符号为分号或end */
memcpy(nxtlev, fsys, sizeof(bool) * symnum); /* 每个后继符号集合都包含上层后继符号集合,以便补救 */
nxtlev[semicolon] = true;
statement(nxtlev, &tx, lev);
gen(opr, 0, 0); /* 每个过程出口都要使用的释放数据段指令 */
memset(nxtlev, 0, sizeof(bool) * symnum); /* 分程序没有补救集合 */
test(fsys, nxtlev, 8); /* 检测后继符号正确性 */
}
/*
* 在符号表中加入一项
*
* k: 标识符的种类为const,var或procedure
* ptx: 符号表尾指针的指针,为了可以改变符号表尾指针的值
* lev: 标识符所在的层次
* pdx: dx为当前应分配的变量的相对地址,分配后要增加1
*
*/
void enter(enum object k, int* ptx, int lev, int* pdx) {
(*ptx)++;
strcpy(table[(*ptx)].name, id); /* 符号表的name域记录标识符的名字 */
table[(*ptx)].kind = k;
switch (k) {
case constant: /* 常量 */
if (num > addrmax) {
error(15); /* 常数越界 */
num = 0;
}
table[(*ptx)].val = num; /* 登记常数的值 */
break;
case variable: /* 变量 */
table[(*ptx)].level = lev;
table[(*ptx)].adr = (*pdx);
(*pdx)++;
break;
case function: /* 过程 */
table[(*ptx)].level = lev;
break;
}
}
/*
* 查找标识符在符号表中的位置,从tx开始倒序查找标识符
* 找到则返回在符号表中的位置,否则返回0
*
* id: 要查找的名字
* tx: 当前符号表尾指针
*/
int position(char* id, int tx) {
int i;
strcpy(table[0].name, id);
i = tx;
while (strcmp(table[i].name, id) != 0) {
i--;
}
return i;
}
/*
* 常量声明处理
*/
void constdeclaration(int* ptx, int lev, int* pdx) {
if (sym == ident) {
getsym();
if (sym == becomes) {
getsym();
if (sym == number) {
enter(constant, ptx, lev, pdx);
getsym();
} else {
error(32); /* 常量声明中的=后应是数字 */
}
} else {
error(8); /* 常量声明中的标识符后应是= */
}
} else {
error(0); /* const后应是标识符 */
}
}
/*
* 变量声明处理
*/
void vardeclaration(int* ptx,int lev,int* pdx) {
if (sym == ident) {
enter(variable, ptx, lev, pdx); // 填写符号表
getsym();
} else {
error(0); /* var后面应是标识符 */
}
}
/*
* 输出所有目标代码
*/
void listall() {
int i;
for (i = 0; i < cx; i++) {
fprintf(fcode,"%d %s %d %d\n", i, mnemonic[code[i].f], code[i].l, code[i].a);
}
}
/*
* 语句处理
*/
void statement(bool* fsys, int* ptx, int lev) {
int i, cx1, cx2;
bool nxtlev[symnum];
while (inset(sym, statbegsys)) {
if (sym == ident) { /* 准备按照赋值语句处理 */
i = position(id, *ptx);/* 查找标识符在符号表中的位置 */
if (i == 0) {
error(6); /* 标识符未声明 */
} else {
if(table[i].kind != variable) {
error(7); /* 赋值语句中,赋值号左部标识符应该是变量 */
i = 0;
} else {
getsym();
if (sym == add) {
gen(lod, lev-table[i].level, table[i].adr);
gen(lit, 0, 1);
gen(opr, 0, 2);
gen(sto, lev-table[i].level, table[i].adr);
getsym();
} else if (sym == sub) {
gen(lod, lev-table[i].level, table[i].adr);
gen(lit, 0, 1);
gen(opr, 0, 3);
gen(sto, lev-table[i].level, table[i].adr);
getsym();
} else {
if(sym == becomes) {
getsym();
} else {
error(8); /* 没有检测到赋值符号 */
}
memcpy(nxtlev, fsys, sizeof(bool) * symnum);
expression(nxtlev, ptx, lev); /* 处理赋值符号右侧表达式 */
if(i != 0) {
/* expression将执行一系列指令,但最终结果将会保存在栈顶,执行sto命令完成赋值 */
gen(sto, lev-table[i].level, table[i].adr);
}
}
}
}
} else {
if (sym == readsym) { /* 准备按照read语句处理 */
getsym();
if (sym != lparen) {
error(17); /* 格式错误,应是左括号 */
} else {
getsym();
if (sym == ident) {
i = position(id, *ptx); /* 查找要读的变量 */
} else {
i = 0;
}
if (i == 0) {
error(18); /* read语句括号中的标识符应该是声明过的变量 */
} else {
gen(opr, 0, 16); /* 生成输入指令,读取值到栈顶 */
gen(sto, lev-table[i].level, table[i].adr); /* 将栈顶内容送入变量单元中 */
}
getsym();
}
if(sym != rparen) {
error(16); /* 格式错误,应是右括号 */
while (!inset(sym, fsys)) { /* 出错补救,直到遇到上层函数的后继符号 */
getsym();
}
} else {
getsym();
}
} else {
if (sym == printsym) { /* 准备按照write语句处理 */
getsym();
if (sym == lparen) {
getsym();
if (sym == ident)
i = position(id, *ptx);
else i = 0;
if (i == 0) error(18);
else {
memcpy(nxtlev, fsys, sizeof nxtlev);
nxtlev[rparen] = true;
expression(nxtlev, ptx, lev);
gen(opr, 0, 14);
gen(opr, 0, 15);
}
if (sym != rparen) {
error(16); /* 格式错误,应是右括号 */
} else {
getsym();
}
}
} else {
if (sym == callsym) { /* 准备按照call语句处理 */
getsym();
if (sym != ident) {
error(0); /* call后应为标识符 */
} else {
i = position(id, *ptx);
if (i == 0) {
error(6); /* 过程名未找到 */
} else {
if (table[i].kind == function) {
gen(cal, lev-table[i].level, table[i].adr); /* 生成call指令 */
} else {
error(31); /* call后标识符类型应为过程 */
}
}
getsym();
if (sym == lparen) getsym();
else error(19);
if (sym == rparen) getsym();
else error(19);
}
} else {
if (sym == ifsym) { /* 准备按照if语句处理 */
getsym();
memcpy(nxtlev, fsys, sizeof(bool) * symnum);
nxtlev[lbrace] = true;
condition(nxtlev, ptx, lev); /* 调用条件处理 */
if (sym == lbrace) {
getsym();
} else {
error(20);
}
cx1 = cx; /* 保存当前指令地址 */
gen(jpc, 0, 0); /* 生成条件跳转指令,跳转地址未知,暂时写0 */
nxtlev[rbrace] = true;
nxtlev[elsesym] = true;
statement(fsys, ptx, lev); /* 处理then后的语句 */
cx2 = cx;
gen(jmp, 0, 0);
code[cx1].a = cx;
code[cx1].a = cx; /* 经statement处理后,cx为then后语句执行完的位置,它正是前面未定的跳转地址,此时进行回填 */
if (sym == rbrace) getsym();
else error(21);
if (sym == elsesym) {
getsym();
if (sym == lbrace) getsym();
else error(20);
memcpy(nxtlev, fsys, sizeof nxtlev);
nxtlev[rbrace] = true;
statement(nxtlev, ptx, lev);
if (sym == rbrace) getsym();
else error(21);
}
code[cx2].a = cx;
} else {
if (sym == whilesym) { /* 准备按照while语句处理 */
cx1 = cx; /* 保存判断条件操作的位置 */
getsym();
memcpy(nxtlev, fsys, sizeof(bool) * symnum);
nxtlev[lbrace] = true; /* 后继符号为do */
condition(nxtlev, ptx, lev); /* 调用条件处理 */
cx2 = cx; /* 保存循环体的结束的下一个位置 */
gen(jpc, 0, 0); /* 生成条件跳转,但跳出循环的地址未知,标记为0等待回填 */
if (sym == lbrace) {
getsym();
} else {
error(20); /* 缺少do */
}
memcpy(nxtlev, fsys, sizeof nxtlev);
nxtlev[rbrace] = true;
statement(fsys, ptx, lev); /* 循环体 */
if (sym == rbrace) getsym();
else error(21);
gen(jmp, 0, cx1); /* 生成条件跳转指令,跳转到前面判断条件操作的位置 */
code[cx2].a = cx; /* 回填跳出循环的地址 */
} else if (sym == forsym) {
getsym();
if (sym == ident) {
i = position(id, *ptx);
if (i == 0) error(6);
else {
if (table[i].kind != variable) {
error(7);
i = 0;
} else {
getsym();
if (sym != insym) error(22);
else getsym();
memcpy(nxtlev, fsys, sizeof nxtlev);
nxtlev[range] = true;
expression(nxtlev, ptx, lev);
gen(sto, lev-table[i].level, table[i].adr);
if (sym != range) error(25);
else getsym();
cx1 = cx;
gen(lod, lev-table[i].level, table[i].adr);
memcpy(nxtlev, fsys, sizeof nxtlev);
nxtlev[lbrace] = true;
expression(nxtlev, ptx, lev);
gen(opr, 0, 13);
cx2 = cx;
gen(jpc, 0, 0);
if (sym == lbrace)
getsym();
else error(20);
memcpy(nxtlev, fsys, sizeof nxtlev);
nxtlev[rbrace] = true;
statement(nxtlev, ptx, lev);
if (sym == rbrace)
getsym();
else error(21);
gen(lod, lev-table[i].level, table[i].adr);
gen(lit, 0, 1);
gen(opr, 0, 2);
gen(sto, lev-table[i].level, table[i].adr);
gen(jmp, 0, cx1);
code[cx2].a = cx;
}
}
}
} else if (sym == repeatsym) {
getsym();
if (sym == lbrace) getsym();
else error(20);
cx1 = cx;
memcpy(nxtlev, fsys, sizeof nxtlev);
nxtlev[rbrace] = true;
statement(nxtlev, ptx, lev);
printf("%d\n", sym);
if (sym == rbrace) getsym();
else error(21);
printf("%d\n", sym);
if (sym == whilesym) getsym();
else error(33);
if (sym == lparen) getsym();
else error(17);
memcpy(nxtlev, fsys, sizeof nxtlev);
nxtlev[rparen] = true;
condition(nxtlev, ptx, lev);
gen(jeq, 0, cx1);
if (sym == rparen) getsym();
else error(16);
}
}
}
}
}
}
if (sym == semicolon)
getsym();
else error(1);
}
}
/*
* 表达式处理
*/
void expression(bool* fsys, int* ptx, int lev) {
enum symbol addop; /* 用于保存正负号 */
bool nxtlev[symnum];
if(sym == plus || sym == minus) { /* 表达式开头有正负号,此时当前表达式被看作一个正的或负的项 */
addop = sym; /* 保存开头的正负号 */
getsym();
memcpy(nxtlev, fsys, sizeof(bool) * symnum);
nxtlev[plus] = true;
nxtlev[minus] = true;
term(nxtlev, ptx, lev); /* 处理项 */
if (addop == minus) {
gen(opr,0,1); /* 如果开头为负号生成取负指令 */
}
} else { /* 此时表达式被看作项的加减 */
memcpy(nxtlev, fsys, sizeof(bool) * symnum);
nxtlev[plus] = true;
nxtlev[minus] = true;
term(nxtlev, ptx, lev); /* 处理项 */
}
while (sym == plus || sym == minus) {
addop = sym;
getsym();
memcpy(nxtlev, fsys, sizeof(bool) * symnum);
nxtlev[plus] = true;
nxtlev[minus] = true;
term(nxtlev, ptx, lev); /* 处理项 */
if (addop == plus) {
gen(opr, 0, 2); /* 生成加法指令 */
} else {
gen(opr, 0, 3); /* 生成减法指令 */
}