-
Notifications
You must be signed in to change notification settings - Fork 0
/
MOC.egg
2149 lines (2060 loc) · 43.8 KB
/
MOC.egg
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
----------------------------------------------------------------------------------------------------------
-- Grammaires de MC et MOC --
-- La grammaire de MOC est obtenue en decommentant --
-- les parties indiquees. --
-----------------------------------------------------
--options
option auto = true;
option version = 0.0.1;
option k=2;
-- verification du retour
inh typeRet : DTYPE for BLOC, INSTS, INST, SIX;
syn isRet : BOOLEAN for BLOC, INSTS, INST, SIX;
-- decl type
inh tInt : DTYPE for PARFS, PARFSX, PARF, TYPE, STYPE, ENTITES, FONCTION, BLOC, INSTS, INST, SIX, AFFX, E, A, AX, R, RX, T, TX, F, ARGS, ARGSX;
inh tChar : DTYPE for PARFS, PARFSX, STYPE, PARF, TYPE, ENTITES, FONCTION, BLOC, INSTS, INST, SIX, AFFX, E, A, AX, R, RX, T, TX, F, ARGS, ARGSX;
inh tPointeurNull : DTYPE for PARFS, PARFSX, TYPE, PARF, STYPE, ENTITES, FONCTION, BLOC, INSTS, INST, SIX, AFFX, E, A, AX, R, RX, T, TX, F, ARGS, ARGSX;
inh tVoid : DTYPE for PARFS, PARFSX, STYPE, ENTITES, TYPE, PARF, FONCTION, BLOC, INSTS, INST, SIX, AFFX, E, A, AX, R, RX, T, TX, F, ARGS, ARGSX;
inh tString : DTYPE for PARFS, PARFSX, STYPE, PARF, TYPE, ENTITES, FONCTION, BLOC, INSTS, INST, SIX, AFFX, E, A, AX, R, RX, T, TX, F, ARGS, ARGSX;
inh regLB : Register for PARFS, PARFSX, TYPE, PARF, STYPE, ENTITES, FONCTION, BLOC, INSTS, INST, SIX, AFFX, E, A, AX, R, RX, T, TX, F, ARGS, ARGSX;
-- test initialisation
syn initialiser : BOOLEAN for F, A, R, T, RX, TX, AX, E; -- ***************************************
syn var : INFOVAR for F, A, R, T; -- ***************************************
--attributes
syn type : DTYPE for TYPE, REFS, STYPE, F, E, A, T, R, AFFX;
inh htype : DTYPE for REFS, AFFX;
-- affectation
syn affectable : BOOLEAN for F, A, R, T, E;
syn vide : BOOLEAN for TX, RX, AX, AFFX;
syn estAffectation : BOOLEAN for AFFX;
syn est_adresse : BOOLEAN for F, T, TX, A, E, RX, R, AX;--, T, F;
inh hest_adresse : BOOLEAN for AFFX, TX, RX, AX;
syn adresse : Emplacement for F, TX, T, A, E, RX, R, AX;
inh hadresse : Emplacement for AFFX, TX, RX, AX;
inh lire_resultat : BOOLEAN for E, AFFX; -- indique si AFFX doit generer le code pour lire le terme de gauche
-- initialisation
-- la table de symboles
inh tds : TDS for ENTITES, FONCTION, PARFS, PARF, PARFSX, TYPE, REFS,
STYPE, BLOC, INSTS, INST, SIX, AFFX, E, A, AX, R, RX, T, TX, F, ARGS, ARGSX;
syn stds : TDS for INST;
-- la table de symboles des fonctions
inh tds_fonction : TDS for ENTITES, FONCTION, BLOC, INSTS, INST, SIX, AFFX, E, A, AX, R, RX, T, TX, F, ARGS, ARGSX;
syn stds_fonction : TDS for FONCTION, ENTITES;
-- la liste de parametres
inh hparams : PARAMETRES for PARFS, PARF, PARFSX, ARGS, ARGSX;
syn params : PARAMETRES for PARFS, PARF, PARFSX, ARGS, ARGSX;
-- la liste des parametres à mettre dans la tds du bloc associé à la fonction
inh htdspar : TDS for PARFS, PARF, PARFSX;
syn tdspar : TDS for PARFS, PARF, PARFSX;
-- l'adresse des variables
inh hadr : INTEGER for ENTITES, FONCTION, PARFS, PARF, PARFSX, BLOC, INSTS, INST, SIX;
syn adr : INTEGER for PARF, INST, INSTS;
syn last_adr : INTEGER for PARFS, PARFSX; -- vaut l'adresse du dernier parametre
inh htailleparams : INTEGER for BLOC, INSTS, INST, SIX;
-- le fichier source
inh source : MOCSourceFile for PROGRAMME;
-- la machine cible pour la generation de code
inh machine : IMachine for
ENTITES, FONCTION, INST, BLOC, INSTS, SIX,
PARFS, PARF, PARFSX, ARGS,ARGSX,
E, AFFX, A, AX, R, RX, T, TX, F, OPMUL, OPUN, OPADD, OPREL
-- -- decommenter la ligne suivante pour MOC
-- ,IMPLEMENTATION, METHODES, METHODE, ATTRIBUTS, MPARF, MPARFS,MARG, MARGS
-- -- fin extension MOC
;
-- ces attributs permettent de recuperer les instructions du code ASM inline
syn code_asm : STRING for ASM;
-- la TDS courante
inh tds_asm : TDS for ASM;
-- code genere
syn code : STRING for ENTITES, FONCTION, BLOC, INSTS, INST, SIX, E, A, AFFX, AX, R, RX, T, TX, F, OPMUL, ARGS, ARGSX, OPUN, OPADD, OPREL;
-- operation
inh hcode : STRING for AX, RX, TX;
inh code_gauche: STRING for AFFX; -- code du terme a gauche de l'operateur
--terminaux
space separateur is "[\r\n\t ]+";
space comm is "\/\/[^\n]*\n";
sugar paro is "\(";
sugar parf is "\)";
sugar aco is "\{";
sugar acf is "\}";
sugar virg is ",";
sugar pv is "\;";
sugar affect is "=";
sugar si is "if";
sugar sinon is "else";
sugar void is "void";
sugar asm is "asm";
sugar int is "int";
sugar char is "char";
sugar retour is "return";
sugar null is "NULL";
sugar nil is "nil";
sugar inf is "\<";
sugar infeg is "\<=";
sugar sup is "\>";
sugar supeg is "\>=";
sugar eg is "==";
sugar neg is "\!=";
sugar plus is "\+";
sugar moins is "\-";
sugar ou is "\|\|";
sugar mult is "\*";
sugar div is "\/";
sugar mod is "\%" ;
sugar et is "\&\&";
sugar non is "\!";
term entier is "[0-9]+";
term caractere is "\'[^\']\'";
term chaine is "\"[^\"]*\"";
term ident is "[a-z][_0-9A-Za-z]*";
-- --decommenter pour MOC
--term identc is "[A-Z][_0-9A-Za-z]*"; -- nom de classe
--term chaineo is "@\"[^\"]*\""; -- chaine MOC
-- --fin extension MOC
-- pour les instructions en assembleur 'inline'
compil ASM;
--production rules
PROGRAMME -> #initType #init #tds #adresse ENTITES #main #gen;
global
machine : IMachine;
-- transmission de la machine cible (choisie par l'option -m au lancement)
#initType {
do
ENTITES^tInt := new DTYPE("int", 1);
ENTITES^tChar := new DTYPE("char", 1);
ENTITES^tString := new DTYPE("string", 1);
ENTITES^tPointeurNull := new POINTEURNULL();
ENTITES^tVoid := new DTYPE("void", 0);
ENTITES^regLB := new Register("LB", 0);
end
}
#init {
do
machine := PROGRAMME^source.getMachine();
if machine = null then
error(NO_MACH, PROGRAMME^source.getMachName());
else
ENTITES^machine := machine;
end
end
}
--tds associées à entites
#tds {
local
do
ENTITES^tds := nil;
ENTITES^tds_fonction := new TDS();
end
}
--adresse de l'entité d'origine
#adresse {
do
ENTITES^hadr := 0;
end
}
--verifie l'existence d'une fonction main
#main {
local
i : INFO;
do
i := ENTITES^stds_fonction.chercherLocalement("main");
if (i = null) then
error(NO_MAIN,"");
end
end
}
-- ecrit le code dans un fichier
#gen {
local
do
machine.writeCode(PROGRAMME^source.getFileName(), ENTITES^code);
end
}
ENTITES -> #tds_fonction #gen ;
#gen {
do
ENTITES^code := "";
end
}
#tds_fonction {
do
ENTITES^stds_fonction := ENTITES^tds_fonction;
end
}
ENTITES -> asm #tds ASM ENTITES #tds_fonction #gen;
#tds {
do
ENTITES1^tds := ENTITES^tds;
-- Remplacer 'null' par la table courante pour que
-- le code ASM puisse acceder aux variables de MC ou MOC
ASM^tds_asm := ENTITES^tds;
end
}
#tds_fonction {
do
ENTITES^stds_fonction := ENTITES1^stds_fonction;
end
}
#gen {
do
ENTITES^code := ENTITES^machine.genCodeInLine(ASM^code_asm) + ENTITES1^code;-- ASM^code_asm contient le code ASM inline;
end
}
ENTITES -> FONCTION #tds_fonction ENTITES #stds_fonction #gen ;
#tds_fonction {
do
ENTITES1^tds_fonction := FONCTION^stds_fonction;
end
}
#stds_fonction {
do
ENTITES^stds_fonction := ENTITES1^stds_fonction;
end
}
#gen {
do
ENTITES^code := FONCTION^code + ENTITES1^code;
end
}
--fonctions
FONCTION -> TYPE ident paro #params #adresse PARFS parf #tds #passeTypeRet #passeTailleparams BLOC #tds_fonction #verifReturn #aff #gen ;
global
tailleparams : INTEGER;
tRetour : DTYPE;
leCode : STRING;
#passeTailleparams{
do
tailleparams := - PARFS^last_adr -1;
BLOC^htailleparams := tailleparams;
end
}
#aff {
do
-- write "\n";
-- write "\n";
-- write "Table des fonctions visibles par " + ident^txt;
-- write "\n";
-- write FONCTION^tds_fonction.toString();
--write "\n";
end
}
#gen {
do
-- write "Taille des parametres de " + ident^txt + " : "+ tailleparams +"\n";
leCode := FONCTION^machine.genFonction(ident^txt, BLOC^code);
tRetour := TYPE^type;
if(tRetour.isVoid()) then
-- depiler les arguments
leCode := leCode + FONCTION^machine.genRetour(tailleparams, 0, "");
end
FONCTION^code := leCode;
end
}
#verifReturn {
do
if ~TYPE^type.isVoid() & ~BLOC^isRet then
error(B_22, "vous avez oublie le retour");
end
end
}
#params {
do
PARFS^hparams := new PARAMETRES(); -- creation du conteneur des parametres
PARFS^htdspar := new TDS(FONCTION^tds); -- creation de la tds de la fonction
end
}
#adresse {
do
PARFS^hadr := -1; -- initialisation des adresses parametre
BLOC^hadr := 3; -- initialisation des adresse de bloc
end
}
#tds {
do
BLOC^tds := PARFS^tdspar;
end
}
#passeTypeRet {
do
BLOC^typeRet := TYPE^type;
end
}
#tds_fonction {
local
i : INFOFONCTION;
t : TDS;
s : String;
do
i := new INFOFONCTION(TYPE^type, PARFS^params);
t := FONCTION^tds_fonction;
s := "Already_declared";
if (t.chercherLocalement(ident^txt) != null) then
error(B_01, "fonction deja existante"); -- write fonction existante
else
t.inserer(ident^txt, i);
end
FONCTION^stds_fonction := t;
end
}
-- parametres de fonctions
PARFS -> #params #last_adr;
#params {
do
PARFS^params := PARFS^hparams;
PARFS^tdspar := PARFS^htdspar;
end
}
#last_adr {
do
PARFS^last_adr := PARFS^hadr;
end
}
PARFS -> PARF #params1 #adresse PARFSX #params2 #last_adr;
#params1 {
do
PARFSX^hparams := PARF^params;
PARFSX^htdspar := PARF^tdspar;
end
}
#adresse {
do
PARFSX^hadr := PARF^adr;
end
}
#params2 {
do
PARFS^params := PARFSX^params;
PARFS^tdspar := PARFSX^tdspar;
end
}
#last_adr {
do
PARFS^last_adr := PARFSX^last_adr;
end
}
PARFSX -> #params #last_adr;
#params {
do
PARFSX^params := PARFSX^hparams;
PARFSX^tdspar := PARFSX^htdspar;
end
}
#last_adr {
do
PARFSX^last_adr := PARFSX^hadr;
end
}
PARFSX -> virg PARF #params1 #adresse PARFSX #params2 #last_adr;
#params1 {
do
PARFSX1^hparams := PARF^params;
PARFSX1^htdspar := PARF^tdspar;
end
}
#adresse {
do
PARFSX1^hadr := PARF^adr;
end
}
#params2 {
do
PARFSX^params := PARFSX1^params;
PARFSX^tdspar := PARFSX1^tdspar;
end
}
#last_adr {
do
PARFSX^last_adr := PARFSX1^last_adr;
end
}
PARF -> TYPE ident #params #adresse;
#params {
local
p : PARAMETRES;
i : INFOVAR;
t : TDS;
do
i := new INFOVAR(TYPE^type, new Emplacement(PARF^hadr, PARF^regLB));
-- je considere que les parametres sont initialise : la verification sera fait lors de l'execution
i.setInitialiser();
p := PARF^hparams;
p.inserer(TYPE^type);
PARF^params := p;
t := PARF^htdspar;
if (t.chercherLocalement(ident^txt) = null) then
t.inserer(ident^txt, i);
else
error(B_02, "nom de parametre deja existant "); -- write fonction existante
-- write nom de parametre deja utilise
end
PARF^tdspar := t;
end
}
#adresse {
local
taille : INTEGER;
do
taille := TYPE^type.getTaille();
PARF^adr := PARF^hadr - taille;
end
}
-- les types (de base et pointeurs)
TYPE -> STYPE #recapTypePointeur REFS #creatType ;
#creatType {
do
TYPE^type := REFS^type;
end
}
#recapTypePointeur {
do
REFS^htype := STYPE^type;
end
}
REFS -> #syntheseType ;
#syntheseType{
do
REFS^type := REFS^htype;
end
}
REFS -> mult #recapType REFS #creatType ;
#recapType{
do
REFS1^htype := REFS^htype;
end
}
#creatType{
do
REFS^type := new POINTEUR(REFS1^type);
end
}
-- types de base
STYPE-> void #creatType ;
#creatType {
do
STYPE^type := STYPE^tVoid;
end
}
STYPE-> int #creatType ;
#creatType {
do
STYPE^type := STYPE^tInt;
end
}
STYPE-> char #creatType ;
#creatType {
do
STYPE^type := STYPE^tChar;
end
}
-- corps de methode et bloc d'instructions
BLOC -> aco #tds #passeTypeRet INSTS acf #isReturn #gen ;
global
t : TDS;
#tds {
do
t := new TDS(BLOC^tds);
INSTS^tds := t;
end
}
#passeTypeRet {
do
INSTS^typeRet := BLOC^typeRet;
end
}
#isReturn {
do
BLOC^isRet := INSTS^isRet;
end
}
#gen {
local
tailleBloc : INTEGER;
do
tailleBloc := INSTS^adr - BLOC^hadr;
write "; tds:\n" + t;
write "; taille des locales = " + tailleBloc+ "\n";
-- Le code du bloc est celui de ses instructions
-- plus le code pour liberer la place occupee
-- par les variables locales (POP (0) taille)
BLOC^code := INSTS^code + BLOC^machine.genComment("fin d'un bloc : pop")+ BLOC^machine.genFree(tailleBloc) ;
end
}
-- instructions
INSTS -> #isReturn #adr #gen;
#adr {
do
INSTS^adr := INSTS^hadr;
end
}
#isReturn{
do
INSTS^isRet := false;
end
}
#gen {
do
-- no code
INSTS^code := "";
end
}
INSTS -> #passeType INST #tds #adresse INSTS #isReturn #adr #gen ;
#passeType {
do
INST^typeRet := INSTS^typeRet;
INSTS1^typeRet := INSTS^typeRet;
end
}
#tds {
do
INSTS1^tds := INST^stds;
end
}
#adresse {
do
INSTS1^hadr := INST^adr;
end
}
#isReturn {
do
INSTS^isRet := INST^isRet | INSTS1^isRet;
end
}
#adr {
do
INSTS^adr := INSTS1^adr;
end
}
#gen {
do
-- append codes
INSTS^code := INST^code + INSTS1^code;
end
}
-- declaration de variable locale avec ou sans init
INST -> TYPE ident #tds #adresse #lire_resultat #code_gauche AFFX pv #verifCompatibilite #isReturn #gen #setInit;
global
i : INFO;
adresse : INTEGER;
empl : Emplacement;
#tds {
do
i := INST^tds.chercherLocalement(ident^txt);
if (i != null) then
error(B_03, "nom de variable deja utilise "); -- write fonction existante
-- write nom de variable deja utilise
else
empl := new Emplacement(INST^hadr, INST^regLB);
i := new INFOVAR(TYPE^type, empl);
INST^tds.inserer(ident^txt, i);
end
INST^stds := INST^tds;
end
}
#lire_resultat {
do
AFFX^lire_resultat := false;
end
}
#adresse {
do
adresse := INST^hadr + TYPE^type.getTaille();
INST^adr := adresse;
end
}
#code_gauche {
do
AFFX^code_gauche := INST^machine.genDeclaration(ident^txt, TYPE^type.getTaille(), empl);
AFFX^hadresse := empl;
AFFX^hest_adresse := false;
AFFX^htype := TYPE^type;
end
}
#setInit{
do
if ~AFFX^vide then
match i with INFOVAR then
i.setInitialiser();
--write("init change ");
end
end
end
}
#verifCompatibilite {
local
compValue : BOOLEAN;
do
if AFFX^type != null then
compValue := TYPE^type.compareTo(AFFX^type);
if ~compValue then
error(B_04 , "affectation non compatible");
end
end
end
}
#isReturn{
do
INST^isRet := false;
end
}
#gen {
local
leCode : STRING;
do
INST^code := AFFX^code + INST^machine.genComment("fin de declaration de "+ident^txt);
-- instruction expression (affectation et appel de procedure)
INST -> #lire_resultat E pv #adresse #stds #isReturn #gen ;
#gen {
do
INST^code := E^code;
end
}
#lire_resultat {
do
E^lire_resultat := false;
end
}
#adresse {
do
INST^adr := INST^hadr;
end
}
#stds {
do
INST^stds := INST^tds;
end
}
#isReturn{
do
INST^isRet := false;
end
}
-- bloc d'instructions
INST -> #passeTypeRet #tds BLOC #adresse #stds #isReturn #gen ;
#passeTypeRet{
do
BLOC^typeRet := INST^typeRet;
end
}
#adresse {
do
INST^adr := INST^hadr;
end
}
#stds {
do
INST^stds := INST^tds;
end
}
#tds {
do
--BLOC^tds := new TDS(INST^tds);
end
}
#isReturn{
do
INST^isRet := false;
end
}
#gen {
do
INST^code := BLOC^code;
end
}
-- conditionnelle
INST -> si paro #lire_resultat E parf #tds #passeTypeRet BLOC SIX #adresse #stds #isReturn #gen;
#lire_resultat{
do
E^lire_resultat := true;
end
}
#passeTypeRet{
do
BLOC^typeRet := INST^typeRet;
SIX^typeRet := INST^typeRet;
end
}
#adresse {
do
INST^adr := INST^hadr;
end
}
#stds {
do
INST^stds := INST^tds;
end
}
#tds {
do
BLOC^tds := new TDS(INST^tds);
end
}
#isReturn {
do
INST^isRet := BLOC^isRet & SIX^isRet;
end
}
#gen {
do
--write "code de la condition : "+ E^code;
INST^code := INST^machine.genIf(E^code, BLOC^code, SIX^code);
end
}
SIX -> sinon #tds #passeTypeRet BLOC #isReturn #gen;
#tds {
do
BLOC^tds := new TDS(SIX^tds);
end
}
#passeTypeRet {
do
BLOC^typeRet := SIX^typeRet;
end
}
#isReturn {
do
SIX^isRet := BLOC^isRet;
end
}
#gen {
do
SIX^code := BLOC^code;
end
}
SIX -> #isReturn #gen ;
#isReturn {
do
SIX^isRet := false;
end
}
#gen {
do
SIX^code := "";
end
}
-- retour de fonction
INST -> retour #lire_resultat E pv #adresse #tds #verifReturn #isReturn #gen ;
#lire_resultat{
do
E^lire_resultat := true;
end
}
#adresse {
do
INST^adr := INST^hadr;
end
}
#tds {
do
INST^stds := INST^tds;
end
}
#verifReturn {
do
if ~INST^typeRet.compareTo(E^type) then
error(B_21, "faux retour");
end
end
}
#isReturn {
do
INST^isRet := true;
end
}
#gen {
do
-- sortir de la fonction courante en retournant la valeur de E
INST^code := INST^machine.genRetour(INST^htailleparams, E^type.getTaille(), E^code); -- + E^code;
end
}
-- inline asm
INST -> asm #tds ASM #adresse #stds #isReturn #gen;
#adresse {
do
INST^adr := INST^hadr;
end
}
#stds {
do
INST^stds := INST^tds;
end
}
#tds {
do
-- A remplacer par la table courante pour que
-- l'assembleur puisse acceder aux variables
ASM^tds_asm := INST^tds;
end
}
#isReturn {
do
INST^isRet := true; -- ATTENTION: on n'a pas les moyens de verifier
end
}
#gen {
do
-- ASM^code_asm contient le code assembleur inline
-- dans lequel les noms de variables ont ete remplaces
-- par leurs adresses.
INST^code := INST^machine.genCodeInLine(ASM^code_asm);
end
}
-- les expressions
-----------------------------------------------------------------------
-- E = expression (y compris l'affectation)
-- A = expression figurant dans une affectation
-- R = expression figurant dans une expresion relationnelle
-- T = expression figurant dans une expression additive (TERME)
-- F = expression figurant dans une expression multiplicative (FACTEUR)
-----------------------------------------------------------------------
-- ici je demande est ce que j ai besoin de verifier la compatibilite des types
-- Si AFFX^type est nul alors pas besoin de verifier
E -> A #getType #code_gauche AFFX #verifCompatible #estAffectable #gen #testInit ;
global
typeE : DTYPE;
#getType {
do
typeE := A^type;
E^type := typeE;
end
}
#code_gauche {
do
AFFX^hest_adresse := A^est_adresse;
AFFX^hadresse := A^adresse;
AFFX^code_gauche := A^code;
AFFX^htype := typeE;
end
}
-- **************************************************************
#testInit {
do
if AFFX^vide then
E^initialiser := A^initialiser;
else
if A^var /= null then
A^var.setInitialiser(); -- la rendre initiliser
E^initialiser := true;
else
error (B_100, " erreur affectation **");
E^initialiser := false;
end
end
end
}
-- ***********************************************
#verifCompatible {
local
compValue : BOOLEAN;
do
if ~AFFX^vide then
compValue := A^type.compareTo(AFFX^type);
if ~compValue then
error(B_6 , "affectation : type non compatible");
-- ecrire erreur de typage d affectation
end
end
end
}
-- j affecte a E le type du cote gauche de l affectation
#estAffectable{
do
E^affectable := false; -- car l'expr sera brut en sommet de pile : non affectable (pas d'@)
--if AFFX^vide then
-- E^affectable := A^affectable;
--else
-- E^affectable := false;
--end
end
}
#gen {
do
if AFFX^estAffectation then
if ~A^affectable then
error(NonAffectable , "Le cote gauche n est pas affectable");
end
end
-- prendre en compte l'eventuelle affectaion puis
-- NON (responsabilite delegue a AFFX) : mettre en sommet de pile la nouvelle valeur de A (code + transmettre adresse, est_adresse ...)
E^code := AFFX^code; -- + AFFX^code_adresse_expr + E^machine.genReadIndirectMem(typeE); -- indirect car AFFX ne connait pas le vrai type de E donc pas sa taille : si maintenant
E^est_adresse := A^est_adresse;
E^adresse := A^adresse;
end
}
-- affectation : laisse en somment de pile la valeur affectee
AFFX -> affect A #getType #estVide #gen #testInit ;
global
t : DTYPE;
#getType {
do
t := A^type;
AFFX^type := t;
end
}
#estVide{
do
AFFX^vide := false;
end
}
#gen {
local
leCode : STRING; -- code de l'affectation
adr_gauche : STRING;
empl_gauche : Emplacement;
empl_droit : Emplacement;
code_valeur_gauche : STRING; -- code pour laisser en sommet de pile la nouvelle valeur de la varible affectee
codedroit : STRING;
do
-- pour visualiser les codes errones
leCode := AFFX^machine.genComment("adresse d'affectation inexistante 4");
codedroit := AFFX^machine.genComment("adresse terme droit d'affectation inexistante 3");
AFFX^estAffectation := true;
-- lire la valeur de droite
empl_droit := A^adresse;
if empl_droit /= null then
-- empl_droit est l'emplacement du terme de droite
codedroit := A^code + AFFX^machine.genReadMem(empl_droit, t.getTaille());
else
if A^est_adresse then
-- lire indirect l'adresse
codedroit := A^code + AFFX^machine.genReadIndirectMem(t.getTaille());
else
-- le terme de droite est une constante ou a un appel de procedure
codedroit := A^code ;
end
end
-- recuperer l'adresse du terme de gauche
-- affecter
-- laisser en sommet de pile la nouvelle valeur de la variable affectee
code_valeur_gauche := AFFX^machine.genComment("code de la nouvelle de la variable affectee");
empl_gauche := AFFX^hadresse;
if empl_gauche /= null then
-- empl_gauche est l'adresse du terme gauche
code_valeur_gauche := code_valeur_gauche + AFFX^machine.genReadMem(empl_gauche, AFFX^htype.getTaille());
leCode := AFFX^code_gauche + AFFX^machine.genAffectation(codedroit, AFFX^hadresse, t.getTaille());
else
if AFFX^hest_adresse then
code_valeur_gauche := code_valeur_gauche + AFFX^code_gauche + AFFX^machine.genReadIndirectMem(AFFX^htype.getTaille());
-- ecrire indirect a l'adresse
leCode := AFFX^code_gauche + AFFX^machine.genWriteIndirectMem(codedroit, t.getTaille());
else
error(Interne_adresse, "adresse d'affectation inexistante 1");
end
end
if AFFX^lire_resultat then
AFFX^code := leCode + code_valeur_gauche;
else
AFFX^code := leCode;
end
end
}
-- ******************************************************************
#testInit {
do
if ~A^initialiser then
error(B_55, " cote droit non initialise");
end
end
}
-- ******************************************************************
AFFX -> #getType #estVide #gen ;
#getType {
do