-
Notifications
You must be signed in to change notification settings - Fork 5
/
parser.c
1476 lines (1195 loc) · 44.3 KB
/
parser.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
863
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 <memory.h>
#include <string.h>
#include "parser.h"
#include "executor.h"
#include "lex.h"
#include "relocation.h"
#include "dependency.h"
static void expression(int level)
{
int *id;
int tmp;
{
if (!token) {
printf("%d: unexpected token EOF of expression\n", line);
exit(-1);
}
// 处理数值
if (token == Num) {
match(Num);
//TODO 进一步判断是否是浮点类型
if (num_type == INT){
load_integral_number_constant(integral_token_val);
expr_type = INT;
}else{
//TODO 加载浮点常量,浮点常量double类型存储
load_real_number_constant(real_token_val);
expr_type = FLOAT;
}
}
// 处理字符串常量
else if (token == '"') {
* text = IMM;
* text = integral_token_val;
match('"');
while (token == '"') {
match('"');
}
// 字符串常量不需要重定位
// data段初始化的时候都为0,所以不需要显示的在末尾添加'\0',下面是
// 为了使得data段在4字节边界上对齐,例如如果字符串的长度为11个字节
// 的话,那么对齐后实际分配的data空间是12个字节
data = (char *)(((int)data sizeof(int)) & (-sizeof(int)));
expr_type = PTR;
}
// 处理标识符
else if (token == Id) {
match(Id);
id = current_id;
//函数调用
if (token == '(') {
match('(');
int num_args = 0; //实参的个数
while (token != ')') {
// 将参数压人栈中
// TODO 如果参数是浮点类型的话就读不到数据了
expression(Assign);
* text = PUSH;
num_args ;
if (token == ',') {
match(',');
}
}
match(')');
// 系统函数, id[Value]保存的是函数的OP代码
if (id[Class] == Sys) {
* text = id[Value];
}
// 自定义的函数
else if (id[Class] == Fun) {
* text = CALL;
* text = id[Value];
}
else {
printf("%d: bad function call\n", line);
exit(-1);
}
// 如果函数调用有传递参数,那么函数返回后需要清理这些参数对应的
// 栈空间
if (num_args > 0) {
* text = ADJ;
* text = num_args;
}
//变量的类型
expr_type = id[Type];
}
else if (id[Class] == Num) {
// 枚举类型
* text = IMM;
* text = id[Value];
expr_type = INT;
}
else {
// 普通变量
if (id[Class] == Ext) {
* text = IMM;
* text = id[Value]; //id[Value]都是保存其地址
}
else if (id[Class] == Glo) {
* text = IMM;
* text = id[Value]; //id[Value]都是保存其地址
int offset = (id[Value] - (int)data_start);
add_relocation_item(text, offset, Data_Rel);
}
else {
printf("%d: undefined variable\n", line);
exit(-1);
}
expr_type = id[Type];
//根据变量的类型选择相应的加载指令
* text = emit_load_directive(expr_type);
}
}
// 强制类型转换以及不同的括号分组
else if (token == '(') {
match('(');
// 强制类型转换
if (token == Int || token == Char || token == Float || Double) {
int cast_type = type_of_token(token);
match(token);
while (token == Mul) {
match(Mul);
cast_type = cast_type PTR;
}
match(')');
//转型的优先级和Inc( )一样
expression(Inc);
check_assignment_types(cast_type, expr_type);
// 强制类型转换整体的表达式的类型应该和转型的类型是一样的例如
// (int **)var, 那么不管var之前是什么类型的变量,转型后的类型
// 就是(int **)
expr_type = cast_type;
} else {
// 普通的括号分组
expression(Assign);
match(')');
}
}
else if (token == Mul) {
match(Mul);
//解引用的优先级和Inc( )一样
expression(Inc);
printf("expr_type %d\n", expr_type);
if (expr_type >= PTR) {
expr_type = expr_type - PTR;
} else {
printf("%d: bad dereference\n", line);
exit(-1);
}
//float** f; 1.0 **f
//那么通过Load操作逐步解引用addr (LI) (LF)
//
* text = emit_load_directive(expr_type);
}
else if (token == And) {
match(And);
//取地址的优先级和Inc( )一样
expression(Inc);
//如果是&var的话,直接通过load操作前面的IMM操作就可以加载其地址了
//"&"后面的只能是变量而不能是常量,但是这里存在一个bug: 如果&const
//而这个const的数值恰好是LC LI LF和LD其中一个,所以为了保险起见加上
//对这种情况的判断;其次&的优先级比较高所以像&(1 2)之类的都是不合法的
if (!does_operate_on_constant() &&
(*text == LC || *text == LI || *text == LF || *text == LD)){
text--;
}else {
printf("%d: bad address of\n", line);
exit(-1);
}
expr_type = expr_type PTR;
}
else if (token == '!') {
match('!');
//逻辑非的优先级和Inc( )一样
expression(Inc);
// 使用expr == 0 进行判断
// 如果是"!"后面的表达式类型是浮点类型,则将bx寄存器中的数转型成整
// 型并放置在ax中指令BTOA就是这个作用
if (expr_type == FLOAT || expr_type == DOUBLE){
* text = BTOA;
}
* text = PUSH;
* text = IMM;
* text = 0;
* text = EQ;
//最后整个表达式(!<expr>)的类型是INT
expr_type = INT;
}
else if (token == '~') {
// bitwise not
match('~');
//按位非的优先级和Inc( )一样
expression(Inc);
//位操作的话表达式的类型一定要正确,因此需要检查一些类型
if (expr_type == FLOAT || expr_type == DOUBLE){
printf("%d: wrong type argument to bit-complement\n", line);
exit(-1);
}
//使用<expr> XOR -1来时实现按位非,具体细节如下
//(1111 1111) -1
//(0110 0011) XOR
//______________
//
//(1001 1100)
* text = PUSH;
* text = IMM;
* text = -1;
* text = XOR;
//最后整个表达式(~<expr>)的类型是INT
expr_type = INT;
}
else if (token == Add) {
// var, 不做实际的操作
match(Add);
//正号优先级和Inc( )一样
expression(Inc);
//最后整个表达式( <expr>)的类型和<expr>相同
expr_type = expr_type;
}
else if (token == Sub) {
// -var
match(Sub);
if (token == Num) {
if (num_type == INT || num_type == CHAR){
load_integral_number_constant(-integral_token_val);
}else{
load_real_number_constant(-real_token_val);
}
match(Num);
} else {
//TODO
* text = IMM;
* text = -1;
* text = PUSH;
expression(Inc);
* text = MUL;
}
}
else if (token == Inc || token == Dec) {
int save_token = token;
match(token);
expression(Inc);
if (does_operate_on_constant()){
printf("%d:Inc or Dec cannot apply on constant\n", line);
exit(-1);
}
// 暂时不支持浮点类型的变量(包括指针类型) 或--操作
if (get_base_type(expr_type) > INT){
printf("%d: sorry, Inc or Dec is not supported for floating\n",
line);
exit(-1);
}
if (*text == LC) {
*text = PUSH;
* text = LC;
} else if (*text == LI) {
*text = PUSH;
* text = LI;
} else {
printf("%d: bad lvalue of pre-increment\n", line);
exit(-1);
}
* text = PUSH;
* text = IMM;
* text = (expr_type > PTR) ? sizeof(int) : sizeof(char);
* text = (save_token == Inc) ? ADD : SUB;
* text = (expr_type == CHAR) ? SC : SI;
}
else {
printf("%d: bad expression\n", line);
exit(-1);
}
}
//处理二元操作符以及后缀操作符
{
// 根据当前的操作符优先级进行操作
while (token >= level) {
int left_type = expr_type;
if (token == Assign) {
// var = expr;
match(Assign);
// 变量如果是充当左值话就修改指令,使用PUSH指令保存其地址
// 如果是用作右值的话,就使用Load指令加载
// 左值不是变量,报错
if (*text == LC || *text == LI || *text == LF || *text == LD) {
*text = PUSH;
} else {
printf("%d: bad lvalue in assignment\n", line);
exit(-1);
}
// 然后计算右边表达式的值,并将结果保存到ax或者bx
expression(Assign);
//类型兼容的函数
printf("assign left %d , right %d\n", left_type, expr_type);
check_assignment_types(left_type, expr_type);
//如果两个是类型兼容的话,那么整个表达式的类型就是左操作数的类型
expr_type = left_type;
* text = emit_store_directive(expr_type);
}
else if (token == Cond) {
// expr ? a : b;
match(Cond);
int *addr;
// 如果结果是float类型的,那么将bx中的数转型移到ax中
// 转型的精度损失不会影响条件的真假性
if (expr_type == FLOAT || expr_type == DOUBLE){
* text = BTOA;
}
* text = JZ;
addr = text;
expression(Assign);
if (token == ':') {
match(':');
} else {
printf("%d: missing colon in conditional\n", line);
exit(-1);
}
int offset = (text 3 - text_start)*sizeof(int);
add_relocation_item(addr, offset, Text_Rel);
*addr = (int)(text 3);
* text = JMP;
addr = text;
expression(Cond);
offset = (text 1 - text_start)*sizeof(int);
add_relocation_item(addr, offset, Text_Rel);
*addr = (int)(text 1);
}
else if (token == Lor) {
// logic or
match(Lor);
int *addr;
// 如果结果是float类型的,那么将bx中的数转型移到ax中
// 转型的精度损失不会影响条件的真假性
if (expr_type == FLOAT || expr_type == DOUBLE){
* text = BTOA;
}
* text = JNZ;
addr = text;
expression(Lan);
int offset = (text 1 - text_start)*sizeof(int);
add_relocation_item(addr, offset, Text_Rel);
*addr = (int)(text 1);
expr_type = INT;
}
else if (token == Lan) {
// logic and
match(Lan);
int *addr;
// 如果结果是float类型的,那么将bx中的数转型移到ax中
// 转型的精度损失不会影响条件的真假性
if (expr_type == FLOAT || expr_type == DOUBLE){
* text = BTOA;
}
* text = JZ;
addr = text;
expression(Or);
int offset = (text 1 - text_start)*sizeof(int);
add_relocation_item(addr, offset, Text_Rel);
*addr = (int)(text 1);
expr_type = INT;
}
else if (token == Or) {
// bitwise or
match(Or);
* text = PUSH;
expression(Xor);
//位操作的话表达式的类型一定要正确,因此需要检查一些类型
if (expr_type == FLOAT || expr_type == DOUBLE){
printf("%d: wrong type argument to bitwise or\n", line);
exit(-1);
}
* text = OR;
expr_type = INT;
}
else if (token == Xor) {
// bitwise xor
match(Xor);
* text = PUSH;
expression(And);
//位操作的话表达式的类型一定要正确,因此需要检查一些类型
if (expr_type == FLOAT || expr_type == DOUBLE){
printf("%d: wrong type argument to bitwise xor\n", line);
exit(-1);
}
* text = XOR;
expr_type = INT;
}
else if (token == And) {
// bitwise and
match(And);
* text = PUSH;
expression(Eq);
//位操作的话表达式的类型一定要正确,因此需要检查一些类型
if (expr_type == FLOAT || expr_type == DOUBLE){
printf("%d: wrong type argument to bitwise xor\n", line);
exit(-1);
}
* text = AND;
expr_type = INT;
}
else if (token == Eq) {
// equal ==
match(Eq);
int *reserve1 = NULL, *reserve2 = NULL;
emit_code_for_binary_left(&reserve1, &reserve2);
//* text = PUSH;
expression(Ne);
//* text = EQ;
emit_code_for_binary_right(EQF, EQ, &reserve1, &reserve2);
expr_type = INT;
}
else if (token == Ne) {
// not equal !=
match(Ne);
int *reserve1 = NULL, *reserve2 = NULL;
emit_code_for_binary_left(&reserve1, &reserve2);
//* text = PUSH;
expression(Lt);
//* text = NE;
emit_code_for_binary_right(NEF, NE, &reserve1, &reserve2);
expr_type = INT;
}
else if (token == Lt) {
// less than
match(Lt);
int *reserve1 = NULL, *reserve2 = NULL;
emit_code_for_binary_left(&reserve1, &reserve2);
//* text = PUSH;
expression(Shl);
//* text = LT;
emit_code_for_binary_right(LTF, LT, &reserve1, &reserve2);
expr_type = INT;
}
else if (token == Gt) {
// greater than
match(Gt);
int *reserve1 = NULL, *reserve2 = NULL;
emit_code_for_binary_left(&reserve1, &reserve2);
//* text = PUSH;
expression(Shl);
//* text = GT;
emit_code_for_binary_right(GTF, GT, &reserve1, &reserve2);
expr_type = INT;
}
else if (token == Le) {
// less than or equal to
match(Le);
int *reserve1 = NULL, *reserve2 = NULL;
emit_code_for_binary_left(&reserve1, &reserve2);
//* text = PUSH;
expression(Shl);
//* text = LE;
emit_code_for_binary_right(LEF, LE, &reserve1, &reserve2);
expr_type = INT;
}
else if (token == Ge) {
// greater than or equal to
match(Ge);
int *reserve1 = NULL, *reserve2 = NULL;
emit_code_for_binary_left(&reserve1, &reserve2);
//* text = PUSH;
expression(Shl);
//* text = GE;
emit_code_for_binary_right(GEF, GE, &reserve1, &reserve2);
expr_type = INT;
}
else if (token == Shl) {
// shift left
match(Shl);
int save_type = expr_type;
* text = PUSH;
expression(Add);
// 两侧的操作数只能是char以及int型的
if ((save_type == FLOAT || save_type == DOUBLE) ||
(expr_type == FLOAT || save_type == DOUBLE)){
printf("%d: wrong type argument to shift left\n", line);
exit(-1);
}
* text = SHL;
expr_type = INT;
}
else if (token == Shr) {
// shift right
match(Shr);
int save_type = expr_type;
* text = PUSH;
expression(Add);
// 两侧的操作数只能是char以及int型的
if ((save_type == FLOAT || save_type == DOUBLE) ||
(expr_type == FLOAT || save_type == DOUBLE)){
printf("%d: wrong type argument to shitf right\n", line);
exit(-1);
}
* text = SHR;
expr_type = INT;
}
//TODO 先尝试让浮点的加法操作正常工作
else if (token == Add) {
// add
match(Add);
int *reserve1 = NULL, *reserve2 = NULL;
emit_code_for_binary_left(&reserve1, &reserve2);
//计算表达式右边的值
expression(Mul);
printf(" right type %d\n", expr_type);
//TODO expr_type = tmp;
//如果操作数是指针类型的话
if (expr_type > PTR) {
* text = PUSH;
* text = IMM;
* text = sizeof(int);
* text = MUL;
}
emit_code_for_binary_right(ADDF, ADD, &reserve1, &reserve2);
}
else if (token == Sub) {
// sub
match(Sub);
* text = PUSH;
expression(Mul);
if (tmp > PTR && tmp == expr_type) {
// pointer subtraction
* text = SUB;
* text = PUSH;
* text = IMM;
* text = sizeof(int);
* text = DIV;
expr_type = INT;
} else if (tmp > PTR) {
// pointer movement
* text = PUSH;
* text = IMM;
* text = sizeof(int);
* text = MUL;
* text = SUB;
expr_type = tmp;
} else {
// numeral subtraction
* text = SUB;
expr_type = tmp;
}
}
else if (token == Mul) { // multiply
match(Mul);
int *reserve1 = NULL, *reserve2 = NULL;
emit_code_for_binary_left(&reserve1, &reserve2);
//* text = PUSH;
expression(Inc);
emit_code_for_binary_right(MULF, MUL, &reserve1, &reserve2);
//* text = MUL;
//TODO
//expr_type = tmp;
}
else if (token == Div) {
// divide
match(Div);
int *reserve1 = NULL, *reserve2 = NULL;
emit_code_for_binary_left(&reserve1, &reserve2);
//* text = PUSH;
expression(Inc);
emit_code_for_binary_right(DIVF, DIV, &reserve1, &reserve2);
//* text = DIV;
//expr_type = tmp;
}
else if (token == Mod) {
// Modulo
match(Mod);
int save_type = expr_type;
* text = PUSH;
expression(Inc);
// 只有两个数是整型数(CHAR或INT)才可以
if (!((save_type == INT || save_type == CHAR) &&
(expr_type == INT || expr_type == CHAR))){
printf("%d:invalid operands to binary\n", line);
exit(-1);
}
* text = MOD;
expr_type = INT;
//expr_type = tmp;
}
else if (token == Inc || token == Dec) {
// postfix inc( ) and dec(--)
// 注意: 浮点数是不支持 或--操作的
if (*text == LI) {
*text = PUSH;
* text = LI;
}
else if (*text == LC) {
*text = PUSH;
* text = LC;
}
else {
printf("%d: bad value in increment\n", line);
exit(-1);
}
* text = PUSH;
* text = IMM;
* text = (expr_type > PTR) ? sizeof(int) : sizeof(char);
* text = (token == Inc) ? ADD : SUB;
//SC store char; SI store int
* text = (expr_type == CHAR) ? SC : SI;
match(token);
}
//数组的访问,但是好像没有数组的声明
else if (token == Brak) {
// array access var[xx]
match(Brak);
int array_type = expr_type;
* text = PUSH; //将var的值作为地址放在栈中
expression(Assign);
match(']');
//什么时候需要将type保存到tmp
if (array_type > PTR) {
// pointer, `not char *`
* text = PUSH; //xx的结果放在栈中(计算偏移量)
* text = IMM;
* text = sizeof(int);
* text = MUL;
}
else if (array_type < PTR) {
printf("%d: pointer type expected\n", line);
exit(-1);
}
expr_type = array_type - PTR;
* text = ADD; //计算地址:首地址 偏移量
//a[10] 等价于 *(a 10)
//LC load char; LI load int
* text = (expr_type == CHAR) ? LC : LI;
}
else {
printf("%d: compiler error, token = %d\n", line, token);
exit(-1);
}
}
}
}
static void statement() {
int *a, *b;
if (token == If) {
// 为if语句产生的汇编代码,不像gcc等正规编译器会进行一系列的优化操作
// if (...) <statement> [else <statement>]
// //按照顺序来
// if (...) <cond>
// JZ a
// <statement> <statement>
// else: JMP b //跳过else部分
// a:
// <statement> <statement>
// b: b:
//
match(If);
match('(');
//解析条件
expression(Assign);
match(')');
// 如果结果是float类型的,那么将bx中的数转型移到ax中
// 转型的精度损失不会影响条件的真假性
if (expr_type == FLOAT || expr_type == DOUBLE){
* text = BTOA;
}
* text = JZ;
b = text; //先为标号b分配一个地址空间
//解析if中的语句
statement(); //跳过这些细节
int offset;
//解析else部分
if (token == Else) {
//match包含了next操作, 如果有else if那么statement()后就会匹配if
match(Else);
// emit code for JMP B
// TODO 这里需要重定位location: b, offset: text 3 - text_start
offset = (text 3 - text_start)*sizeof(int);
add_relocation_item(b, offset, Text_Rel);
*b = (int)(text 3);
* text = JMP;
b = text;
statement(); //跳过这些细节
}
// TODO 这里需要重定位location: b, offset: text 1 - text_start
offset = (text 1 - text_start)*sizeof(int);
add_relocation_item(b, offset, Text_Rel);
*b = (int)(text 1); //编译完后再填充标号b的内容
}
//TODO 实现break, continue
else if (token == While) {
//
// a: a:
// while (<cond>) <cond>
// JZ b
// <statement> <statement>
// JMP a
// b: b:
match(While);
a = text 1; //a开始将存放<cond>
match('(');
expression(Assign);
match(')');
// 如果结果是float类型的,那么将bx中的数转型移到ax中
// 转型的精度损失不会影响条件的真假性
if (expr_type == FLOAT || expr_type == DOUBLE){
* text = BTOA;
}
* text = JZ;
b = text; //先为标号b分配一个地址空间
//TODO 将两个标号打包压入堆栈中(主要是为了while循环)
//如果堆栈为空的时候,即此时的环境不是在while循环中,那么报错
//start_label1: , end_label2:
//start_label2: , end_label2:
statement();
int offset;
//相当于continue
* text = JMP;
//TODO 这里需要一个重定位location:text, offset=a - text_start
* text = (int)a;
offset = (a - text_start)*sizeof(int);
add_relocation_item(text, offset, Text_Rel);
//相当于break
//编译完后在填充标号b的内容, b开始存放其它命令
//TODO 这里也需要一个重定位location:b, offset=text 1-text_start
offset = (text 1 - text_start)*sizeof(int);
add_relocation_item(b, offset, Text_Rel);
*b = (int)(text 1); //b开始存放其它命令
}
//匹配if/while中的语句
else if (token == '{') {
// { <statement> ... }
match('{');
while (token != '}') {
statement();
}
match('}');
}
else if (token == Return) {
// return [expression];
match(Return);
if (token != ';') {
expression(Assign);
}
match(';');
// emit code for return
* text = LEV;
}
else if (token == ';') {
// empty statement
match(';');
}
else {
// a = b; or function_call();
//printf("assignement\n");
expression(Assign);
match(';');
}
}
static void global_declaration()
{
// 解析变量声明的类型
if (token == Int) {
match(Int);
basetype = INT;
printf("Int token\n");
}
else if (token == Char) {
match(Char);
basetype = CHAR;
printf("Char token\n");
}
else if (token == Float){
match(Float);
basetype = FLOAT;
printf("Float token\n");
}else if (token == Double){
match(Double);
basetype = DOUBLE;
printf("Double token\n");
}
// 解析可由逗号分割的变量声明
while (token != ';' && token != '}') {
int final_type = basetype;
// 解析指针类型,因为会存在如 "int ****var;" 的多级指针声明需要用一个循
// 环来解析,注意因为在词法分析阶段解析标识符的时候遇到非标识符的字符
// 就会停止下来,因此 "int**** var;" 这种形式也是可以的
while (token == Mul) {
match(Mul);
final_type = final_type PTR;
}
if (token != Id) {
// 如果记号不是标识符的话则为非法声明
printf("%d: bad global declaration\n", line);
exit(-1);
}
if (current_id[Class]) {
// 标识符已经存在
printf("%d: duplicate global declaration\n", line);
exit(-1);
}
match(Id);
//设置了Type和Value,等程序后面引用的时候就能正确加载
current_id[Type] = final_type;
if(token == Brak){
//TODO 新增支持数组声明, 数组下标要是整数
static int* addr_keeper;
next();
if (token != Num){
printf("%d: bad index\n", line);
}
int num = integral_token_val;
current_id[Class] = Glo;
//为什么current_id[Value] = (int)data就不行,可能数组的访问就是用指针
//实现的 data是char*类型的
//数组变量是指针变量,数组的起始地址保存在该指针变量中
//这里不能使用(int)&data因为data是全局变量,其数值后面是会变化的