-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.c
3123 lines (2900 loc) · 101 KB
/
main.c
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
/*
* SW compiler program implemented in C
*
* The program has been tested on CodeBlocks 16.01 rev 10702
*
* Student: Tao Wei 陶玮
*
* 使用方法:
* 运行后输入SW源程序文件名
* 回答是否输出虚拟机代码
* 回答是否输出符号表
* fcode.txt输出虚拟机代码
* foutput.txt输出源文件、出错示意(如有错)、各行对应的生成代码首地址(如无错)
* fresult.txt输出运行结果
* ftable.txt输出符号表
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define bool int /* 因为C语言没有bool类型 */
#define true 1 /* 所以做这3行处理 */
#define false 0
#define norw 29 /* 保留字个数 10+19 */
#define txmax 100 /* 符号表容量 */
#define nmax 14 /* 数字的最大位数 */
#define al 10 /* 标识符的最大长度 10?*/
#define maxerr 30 /* 允许的最多错误数 */
#define amax 2048 /* 地址上界*/
#define cxmax 200 /* 最多的虚拟机代码数 */
#define stacksize 500 /* 运行时数据栈元素最多为500个 */
#define levmax 1 /* 最大允许过程嵌套声明层数*/
/* 符号 */
enum symbol {
nul, /* 未定义 */
ident, /* 标识符 */
number, /* 数字 */
plus, minus, /* + - */
times, slash, /* * / */
eql, /* == */
neq, /* != */
lss, leq, /* < <= */
gtr, geq, /* > >= */
lparen, rparen, /* ( ) */
lbrace, rbrace, /* { } */
semicolon, /* ; */
threepoints, /* ... */
becomes, /* = */
plusone, minusone, /* ++, -- */
mod, /* % */
colon, /* : */
comma, /* , */
lbrack, rbrack, /* [ ] */
ifsym, elsesym, whilesym, forsym, insym,
readsym, printsym, callsym, varsym, funcsym,
boolsym, constsym, floatsym, oddsym, switchsym,
casesym, breaksym, repeatsym, notsym, defaultsym,
andsym, orsym, exitsym, tointsym, tofloatsym,
truesym, falsesym, returnsym, eofsym, continuesym,
};
#define symnum 57 // 27+29+1
/* 符号表中的类型 */
enum object {
variable, /* 变量 */
function, /* 函数 */
boolean, /* 布尔 */
constant, /* 常数 */
floatnum, /* 实数 */
};
/* 虚拟机代码指令 */
enum fct {
lit, /* lit 0, a 将数a置入栈顶 */
opr, /* opr 0, a 一组算术关系运算符 返回调用程序 */
lod, /* lod 1, a 将1,a形成的栈地址变量值置入栈顶 */
sto, /* sto 1, a 将栈顶值存到由1,a形成的栈地址变量 */
cal, /* cal 1, a 调用子程序 */
ini, /* int 0, a 预留a个存储位置 (int写作ini避免与C语言中的INT混淆) */
jmp, /* jmp 0, a 无条件转移 */
jpc, /* jpc 0, a 条件转移 (当s(t)==0时) */
};
#define fctnum 8
/* 虚拟机代码结构 */
struct instruction
{
enum fct f; /* 虚拟机代码指令 */
int l; /* 引用层与声明层的层次差 */
float a; /* 根据f的不同而不同 */
};
struct parameter
{
char name[al];
enum object type;
};
struct parameter p[10]; /* 函数内可传递最多10个参数 */
/* 全局变量 (中间过程使用) */
bool listswitch ; /* 显示虚拟机代码与否 */
bool tableswitch ; /* 显示符号表与否 */
struct instruction code[cxmax]; /* 存放虚拟机代码的数组 */
char mnemonic[fctnum][5]; /* 虚拟机代码指令名称 */
bool declbegsys[symnum]; /* 表示声明开始的符号集合 */
bool statbegsys[symnum]; /* 表示语句开始的符号集合 */
bool facbegsys[symnum]; /* 表示因子开始的符号集合 */
char ch; /* 存放当前读取的字符,getch 使用 */
enum symbol sym; /* 当前的符号 */
char id[al+1]; /* 当前ident,多出的一个字节用于存放0 */
float num; /* 当前number */
int cc, ll; /* getch使用的计数器,cc表示当前字符(ch)的位置 */
int cx; /* 虚拟机代码指针, 取值范围[0, cxmax-1]*/
char line[81]; /* 读取行缓冲区 */
char a[al+1]; /* 临时字符串,多出的一个字节用于存放0 */
char word[norw][al]; /* 保留字 */
enum symbol wsym[norw]; /* 保留字对应的符号值 */
enum symbol ssym[256]; /* 单字符的符号值 */
bool isend = false; /* 文件是否读完 */
bool isjmp[10]; /* statement_list语句中可否有continue和break语句 */
bool isfor = false; /* 当前执行语句是否在for-in语句中(循环体内除外)内 */
bool isfloat = false; /* 标识符所存数据类型是否是小数 */
int circlenum = 0; /* 当前位于几个循环体内 */
int continue_cx[10][100]; /* continue语句位置 */
int continue_n[10]; /* continue语句个数 */
int break_cx[10][100]; /* break语句位置 */
int break_n[10]; /* break语句个数 */
int exit_cx[100]; /* exit语句位置(最多100处) */
int exit_n = 0; /* exit语句个数 */
int parameter_n = 0; /* 函数()内参数个数 */
bool is_return = false; /* 函数是否有返回值 */
char current[10]; /* 当前所在函数名 */
int varmax = 0; /* 全局变量的最大位置 */
/* 符号表结构 */
struct tablestruct
{
char name[al]; /* 名字 */
enum object kind; /* 类型 */
int val; /* 数值,仅const使用 */
int level; /* 所处层, 仅const不使用 */
int adr; /* (开始)地址, 仅const不使用 */
int size; /* 需要分配的数据区空间, 仅function, array使用 */
int para_n; /* 函数参数个数, 仅function使用 */
bool isreturn; /* 是否有返回值, 仅function使用 */
};
struct tablestruct table[txmax]; /* 符号表 */
/* 全局变量 (输入输出相关) */
FILE* fin; /* 输入源文件 */
FILE* foutput; /* 输出文件及出错示意(如有错)、各行对应的生成代码首地址(如无错) */
FILE* ftable; /* 输出符号表 */
FILE* fcode; /* 输出虚拟机代码 */
FILE* fresult; /* 输出执行结果 */
char fname[al]; /* 输入字符串 (文件名, 是否选择) */
int err; /* 错误计数器 */
/* 函数申明 */
void error(int n);
void getsym();
void getch();
void init();
void program(int tx, bool* fsys, int lev);
void var_declaration_list(int* ptx, int* pdx, int lev);
void statement_list(int* ptx, bool* fsys, int lev);
void expression(int* ptx, bool* fsys, int lev);
void condition(int* ptx, bool* fsys, int lev);
void term(int* ptx, bool* fsys, int lev);
void factor(int* ptx, bool* fsys, int lev);
int position(char* idt, int tx);
void enter(enum object k, int* ptx, int* pdx, int lev);
void gen(enum fct x, int y, float z);
void test(bool* s1, bool* s2, int n);
int inset(int e, bool* s);
int addset(bool* sr, bool* s1, bool* s2, int n);
int subset(bool* sr, bool* s1, bool* s2, int n);
int mulset(bool* sr, bool* s1, bool* s2, int n);
void interpret();
void listcode(int cx0);
void listall();
int base(int l, float* s, int b);
/* 主程序 */
int main()
{
bool nxtlev[symnum]; /* 后继符号集合 */
printf("Input SW file? ");
scanf("%s", fname); /* 输入文件名 */
if ((fin = fopen(fname, "r")) == NULL) /* 文件打开失败 */
{
printf("Can't open the input file:(\n");
exit(1);
}
ch = fgetc(fin);
if (ch == EOF) /* 文件为空 */
{
printf("The input file is empty:(\n");
fclose(fin);
exit(1);
}
rewind(fin); /* 将文件内部的位置指针重新指向一个流(数据流/文件)的开头 */
if ((foutput = fopen("foutput.txt", "w")) == NULL)
{
printf("Can't open the output file:(\n");
exit(1);
}
if ((ftable = fopen("ftable.txt", "w")) == NULL)
{
printf("Can't open ftable.txt file!:(\n");
exit(1);
}
printf("List object codes?(Y/N)"); /* 是否输出虚拟机代码 */
scanf("%s", fname);
listswitch = (fname[0]=='y' || fname[0]=='Y');
printf("List symbol table?(Y/N)"); /* 是否输出符号表 */
scanf("%s", fname);
tableswitch = (fname[0]=='y' || fname[0]=='Y');
init(); /* 初始化 */
addset(nxtlev, declbegsys, statbegsys, symnum);
program(0, nxtlev, 0); /* 处理分程序 */
if (sym != eofsym)
{
printf("We cannot read the file over:(\n");
exit(1);
}
if (err == 0)
{
printf("\n===Parsing success!===\n");
fprintf(foutput,"\n===Parsing success!===\n");
if ((fcode = fopen("fcode.txt", "w")) == NULL)
{
printf("Can't open fcode.txt file!\n");
exit(1);
}
if ((fresult = fopen("fresult.txt", "w")) == NULL)
{
printf("Can't open fresult.txt file!\n");
exit(1);
}
listall(); /* 输出所有代码 */
fclose(fcode);
interpret(); /* 调用解释执行程序 */
fclose(fresult);
}
else
{
printf("\n%d errors in SW program!\n",err);
fprintf(foutput,"\n%d errors in SW program!\n",err);
}
fclose(ftable);
fclose(foutput);
fclose(fin);
return 0;
}
/* 初始化 */
void init()
{
int i;
/* 设置单字符符号 */
for (i = 0; i < 256; i++)
{
ssym[i] = nul;
}
ssym['+'] = plus;
ssym['-'] = minus;
ssym['*'] = times;
ssym['/'] = slash;
ssym['('] = lparen;
ssym[')'] = rparen;
ssym['{'] = lbrace;
ssym['}'] = rbrace;
ssym['='] = becomes;
ssym[';'] = semicolon;
ssym['%'] = mod;
ssym[':'] = colon;
ssym[','] = comma;
ssym['['] = lbrack;
ssym[']'] = rbrack;
/* 设置保留字名字,按照字母顺序,便于二分查找 */
strcpy(&(word[0][0]), "and");
strcpy(&(word[1][0]), "bool");
strcpy(&(word[2][0]), "break");
strcpy(&(word[3][0]), "call");
strcpy(&(word[4][0]), "case");
strcpy(&(word[5][0]), "const");
strcpy(&(word[6][0]), "continue");
strcpy(&(word[7][0]), "default");
strcpy(&(word[8][0]), "else");
strcpy(&(word[9][0]), "exit");
strcpy(&(word[10][0]), "false");
strcpy(&(word[11][0]), "float");
strcpy(&(word[12][0]), "for");
strcpy(&(word[13][0]), "func");
strcpy(&(word[14][0]), "if");
strcpy(&(word[15][0]), "in");
strcpy(&(word[16][0]), "not");
strcpy(&(word[17][0]), "odd");
strcpy(&(word[18][0]), "or");
strcpy(&(word[19][0]), "print");
strcpy(&(word[20][0]), "read");
strcpy(&(word[21][0]), "repeat");
strcpy(&(word[22][0]), "return");
strcpy(&(word[23][0]), "switch");
strcpy(&(word[24][0]), "tofloat");
strcpy(&(word[25][0]), "toint");
strcpy(&(word[26][0]), "true");
strcpy(&(word[27][0]), "var");
strcpy(&(word[28][0]), "while");
/* 设置保留字符号 */
wsym[0] = andsym;
wsym[1] = boolsym;
wsym[2] = breaksym;
wsym[3] = callsym;
wsym[4] = casesym;
wsym[5] = constsym;
wsym[6] = continuesym;
wsym[7] = defaultsym;
wsym[8] = elsesym;
wsym[9] = exitsym;
wsym[10] = falsesym;
wsym[11] = floatsym;
wsym[12] = forsym;
wsym[13] = funcsym;
wsym[14] = ifsym;
wsym[15] = insym;
wsym[16] = notsym;
wsym[17] = oddsym;
wsym[18] = orsym;
wsym[19] = printsym;
wsym[20] = readsym;
wsym[21] = repeatsym;
wsym[22] = returnsym;
wsym[23] = switchsym;
wsym[24] = tofloatsym;
wsym[25] = tointsym;
wsym[26] = truesym;
wsym[27] = varsym;
wsym[28] = whilesym;
/* 设置指令名称 */
strcpy(&(mnemonic[lit][0]), "lit");
strcpy(&(mnemonic[opr][0]), "opr");
strcpy(&(mnemonic[lod][0]), "lod");
strcpy(&(mnemonic[sto][0]), "sto");
strcpy(&(mnemonic[cal][0]), "cal");
strcpy(&(mnemonic[ini][0]), "int");
strcpy(&(mnemonic[jmp][0]), "jmp");
strcpy(&(mnemonic[jpc][0]), "jpc");
/* 设置符号集 */
for (i = 0; i < symnum; i++)
{
declbegsys[i] = false;
statbegsys[i] = false;
facbegsys[i] = false;
}
/* 设置声明开始符号集 */
declbegsys[varsym] = true;
declbegsys[funcsym] = true;
declbegsys[boolsym] = true;
declbegsys[constsym] = true;
declbegsys[floatsym] = true;
/* 设置语句开始符号集 */
statbegsys[ifsym] = true;
statbegsys[whilesym] = true;
statbegsys[readsym] = true;
statbegsys[printsym] = true;
statbegsys[ident] = true;
statbegsys[tointsym] = true;
statbegsys[tofloatsym] = true;
statbegsys[forsym] = true;
statbegsys[callsym] = true;
statbegsys[switchsym] = true;
statbegsys[repeatsym] = true;
statbegsys[exitsym] = true;
/* 设置因子开始符号集 */
facbegsys[ident] = true;
facbegsys[number] = true;
facbegsys[lparen] = true;
facbegsys[tointsym] = true;
facbegsys[tofloatsym] = true;
facbegsys[truesym] = true;
facbegsys[falsesym] = true;
/* 初始化break, continue记录个数为零,
* 初始化标记为不在循环体中 */
for(i = 0; i < 10; i++)
{
break_n[i] = 0;
isjmp[i] = false;
continue_n[i] = 0;
}
err = 0;
cc = ll = cx = 0;
ch = ' ';
}
/* 用数组实现集合的集合运算 */
/* 是否在集合中的真假运算 */
int inset(int e, bool* s)
{
return s[e];
}
/* 并运算 s1Us2 */
int addset(bool* sr, bool* s1, bool* s2, int n)
{
int i;
for (i = 0; i < n; i++)
{
sr[i] = s1[i] || s2[i];
}
return 0;
}
/* 差运算 s1-s2 */
int subset(bool* sr, bool* s1, bool* s2, int n)
{
int i;
for (i=0; i<n; i++)
{
sr[i] = s1[i] && (!s2[i]);
}
return 0;
}
/* 交运算 s1ns2*/
int mulset(bool* sr, bool* s1, bool* s2, int n)
{
int i;
for (i=0; i<n; i++)
{
sr[i] = s1[i] && s2[i];
}
return 0;
}
/* 出错处理,打印出错位置和错误编码 */
void error(int n)
{
char space[81];
memset(space,32,81); /* 32为asii码表的空格 初始化字符串为全空格*/
space[cc-1]=0; /* 出错时当前符号已经读完,所以cc-1 */
printf("**%s^%d\n", space, n);
fprintf(foutput,"**%s^%d\n", space, n);
err = err + 1;
if (err > maxerr)
{
printf("There are too many errors to handle!:(\n");
exit(1);
}
}
/*
* 过滤空格和两种表示方法的注释,读取一个字符
* 每次读一行,存入line缓冲区,line被getsym取空后再读一行
* 被函数getsym调用
*/
void getch()
{
if (cc == ll) /* 判断缓冲区中是否有字符,若无字符,则读入下一行字符到缓冲区中 */
{ /* 无缓存情况 */
if (feof(fin)) /* feof(fin)非零则文件结束 */
{
isend = true;
}
printf("%d ", cx); /* 输出虚拟机代码指针 */
fprintf(foutput,"%d ", cx);
ll = 0; /* 文件没有结束 */
cc = 0;
ch = ' ';
while (ch != 10) /* 10为asii码表的换行键 */
{
char pre = ch;
if (EOF == fscanf(fin,"%c", &ch) || (pre == '/' && ch == '/' )) /* 如果读取到文件结束/行注释 */
{
if(ll != 0) /* 该行头两个字符不是"//" */
{
line[ll] = 0; /* 字符串结束\0, 即该行缓存结束 */
}
if(pre == '/' && ch == '/')
{
while(EOF != fscanf(fin, "%c", &ch) && ch != 10) /* 忽略掉"//"后面的内容直至读到'\n' */
{
;
}
if(ch !=10)
isend = true;
if(ll == 0) /* 该行头两个字符就是"//" */
{
ch = ' ';
continue;
}
printf("\n");
fprintf(foutput,"\n");
}
else
{
isend = true;
}
break;
}
if(pre == '/' && ch == '*')
{
line[ll] = 0;
bool isenter = false; /* 块注释内是否有换行符, 有则输出一个换行 */
fscanf(fin, "%c", &pre);
fscanf(fin, "%c", &ch);
if(pre == '\n')
isenter = true;
while(pre != '*' || ch != '/')
{
pre = ch;
if(pre == '\n')
isenter = true;
if (EOF == fscanf(fin,"%c", &ch))
{
error(29); // 缺少"*/"
}
}
if(ll == 0) // 该行头两个字符就是"/*"
{
ch = ' ';
continue;
}
if(isenter == true)
{
printf("\n");
fprintf(foutput,"\n");
}
break;
}
if(pre == '/')
{
printf("%c", pre); /* 通过上面判断未跳出循环则'/'非注释所用可以输出 */
fprintf(foutput, "%c", pre);
line[ll] = pre;
ll++;
}
if(ch != '/')
{
printf("%c", ch); /* 当前字符为'/', 是否用于注释有待进一步判断 */
fprintf(foutput, "%c", ch);
line[ll] = ch;
ll++;
}
}
}
if(isend == true && ll == 0)
ch = 0;
else
{
ch = line[cc]; /* 有缓存情况 */
cc++;
}
}
/* 词法分析,获取一个符号 */
void getsym()
{
int i, j, k;
if(ch == 0)
sym = eofsym;
else
{
while (ch == ' ' || ch == 10 || ch == 9) /* 过滤空格、换行和制表符 */
{
getch();
}
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) /* 当前单词是标识符或是保留字 */
{
/* 单词保存进字符串a中 */
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];
if(sym == wsym[10])
{
sym = number;
num = 0; // false
}
else if(sym == wsym[26])
{
sym = number;
num = 1; // true
}
}
else /* 当前单词为标识符 */
{
sym = ident;
}
}
else if (ch >= '0' && ch <= '9') /* 当前的单词是数字 */
{
sym = number;
/* 获取数字的值 */
num = 0;
k = 0;
do {
num = 10 * num + ch - '0';
k++;
getch();
} while (ch >= '0' && ch <= '9');
float weight = 0.1;
if(isfor == false && ch == '.')
{
getch();
do{
num += weight * (ch - '0');
weight *= 0.1;
k++;
getch();
} while(ch >= '0' && ch <= '9');
}
k--;
if (k > nmax) /* 数字位数太多 */
{
error(30);
}
}
else if(ch == '!')
{
getch();
if(ch == '=')
{
sym = neq;
getch();
}
else
{
sym = nul; /* 不能识别的符号 */
}
}
else if(ch == '.')
{
getch();
if(ch == '.')
{
getch();
if(ch == '.')
{
sym = threepoints;
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 = plusone;
getch();
}
else
{
sym = plus;
}
}
else if (ch == '-')
{
getch();
if (ch == '-')
{
sym = minusone;
getch();
}
else
{
sym = minus;
}
}
else if (ch == 0)
{
sym = eofsym;
}
else
{
sym = ssym[ch]; /* 当符号不满足上述条件时,全部按照单字符符号处理 */
getch();
}
}
}
/*
* 生成虚拟机代码
*
* x: instruction.f;
* y: instruction.l;
* z: instruction.a;
*/
void gen(enum fct x, int y, float z)
{
if (cx >= cxmax)
{
printf("Program is too long!X(\n"); /* 生成的虚拟机代码程序过长 */
exit(1);
}
if ( z >= amax)
{
printf("Displacement address is too big!8(\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();
}
}
}
/*
* 编译程序主体
*
* tx: 符号表当前尾指针
* fsys: 当前模块后继符号集合
* lev: 当前分程序所在层
*/
void program(int tx, bool* fsys, int lev)
{
int i;
int dx; /* 记录数据分配的相对地址 */
int tx0; /* 保留初始tx */
int cx0; /* 保留初始cx */
bool nxtlev[symnum]; /* 在下级函数的参数中,符号集合均为值参,但由于使用数组实现,
传递进来的是指针,为防止下级函数改变上级函数的集合,开辟
新的空间传递给下级函数*/
dx = 3; /* 三个空间用于存放静态链SL、动态链DL和返回地址RA */
tx0 = tx; /* 记录本层标识符的初始位置 */
table[tx0].adr = cx; /* 记录当前层代码的开始位置 */
gen(jmp, 0, 0); /* 产生跳转指令,跳转位置未知暂时填0 */
if (lev > levmax) /* 嵌套层数过多 */
{
error(32);
}
getsym();
var_declaration_list(&tx, &dx, lev);
varmax = tx;
while (sym == funcsym) /* 遇到过程声明符号,开始处理过程声明 */
{
getsym();
strcpy(current, id);
printf("id:%s\n", id);
if (sym == ident)
{
enter(function, &tx, &dx, lev); /* 填写符号表 */
getsym();
}
else
{
error(41); /* function后应为标识符 */
}
if (sym == lparen)
{
getsym();
}
else
{
error(17); /* 函数名后少了"(" */
}
parameter_n = 0;
if (sym == varsym || sym == boolsym || sym == floatsym)
{
enum object type;
if(sym == varsym)
{
type = variable;
}
else if(sym == boolsym)
{
type = boolean;
}
else
{
type = floatnum;
}
getsym();
if (sym == ident)
{
strcpy(p[parameter_n].name, id);
p[parameter_n++].type = type;
getsym();
}
else
{
error(43);
}
while(sym == comma)
{
getsym();
if (sym == varsym || sym == boolsym || sym == floatsym)
{
enum object type;
if(sym == varsym)
{
type = variable;
}
else if(sym == boolsym)
{
type = boolean;
}
else
{
type = floatnum;
}
getsym();
if (sym == ident)
{
strcpy(p[parameter_n].name, id);
p[parameter_n++].type = type;
getsym();
}
else
{
error(43);
}
}
else
{
error(44);
break;
}
}
}
if (sym == rparen)
{
getsym();
}
else
{
error(18); /* 函数名后少了")" */
}
if (sym == lbrace)