1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.19
4: Copyright (C) 1989-2014 Dr. BERTRAND Joël
5:
6: This file is part of RPL/2.
7:
8: RPL/2 is free software; you can redistribute it and/or modify it
9: under the terms of the CeCILL V2 License as published by the french
10: CEA, CNRS and INRIA.
11:
12: RPL/2 is distributed in the hope that it will be useful, but WITHOUT
13: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14: FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License
15: for more details.
16:
17: You should have received a copy of the CeCILL License
18: along with RPL/2. If not, write to info@cecill.info.
19: ================================================================================
20: */
21:
22:
23: #include "rpl-conv.h"
24:
25:
26: /*
27: ================================================================================
28: Fonction de transcription d'un arbre en liste chaînée
29: ================================================================================
30: Entrées : pointeur sur une structure struct_processus
31: --------------------------------------------------------------------------------
32: Sorties :
33: --------------------------------------------------------------------------------
34: Effets de bord : néant
35: ================================================================================
36: */
37:
38: static struct_liste_chainee *
39: transcription_arbre(struct_processus *s_etat_processus, struct_arbre *s_arbre)
40: {
41: integer8 i;
42:
43: struct_liste_chainee *l_element_courant;
44: struct_liste_chainee *l_liste;
45: struct_liste_chainee *l_nouvelle_pile_locale;
46: struct_liste_chainee *l_pile_locale;
47:
48: l_pile_locale = NULL;
49:
50: for(i = 0; i < (*s_arbre).nombre_branches; i++)
51: {
52: if ((l_nouvelle_pile_locale = allocation_maillon(s_etat_processus))
53: == NULL)
54: {
55: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
56: return(NULL);
57: }
58:
59: (*l_nouvelle_pile_locale).suivant = l_pile_locale;
60: l_pile_locale = l_nouvelle_pile_locale;
61:
62: if (((*l_pile_locale).donnee = (void *) transcription_arbre(
63: s_etat_processus, (*s_arbre).branches[i])) == NULL)
64: {
65: return(NULL);
66: }
67: }
68:
69: if ((l_liste = allocation_maillon(s_etat_processus)) == NULL)
70: {
71: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
72: return(NULL);
73: }
74:
75: // Ajout de la fonction
76:
77: (*l_liste).suivant = NULL;
78: (*l_liste).donnee = (*s_arbre).feuille;
79:
80: free((*s_arbre).branches);
81: free(s_arbre);
82:
83: // Chaînage des arguments
84:
85: while(l_pile_locale != NULL)
86: {
87: l_element_courant = (void *) (*l_pile_locale).donnee;
88:
89: if (l_element_courant == NULL)
90: {
91: (*s_etat_processus).erreur_systeme = d_es_pile_vide;
92: return(NULL);
93: }
94:
95: while((*l_element_courant).suivant != NULL)
96: {
97: l_element_courant = (*l_element_courant).suivant;
98: }
99:
100: (*l_element_courant).suivant = l_liste;
101: l_liste = (void *) (*l_pile_locale).donnee;
102:
103: l_nouvelle_pile_locale = (*l_pile_locale).suivant;
104: liberation_maillon(s_etat_processus, l_pile_locale);
105: l_pile_locale = l_nouvelle_pile_locale;
106: }
107:
108: return(l_liste);
109: }
110:
111:
112: /*
113: ================================================================================
114: Fonction de simplification d'un arbre
115: ================================================================================
116: Entrées : pointeur sur une structure struct_processus
117: --------------------------------------------------------------------------------
118: Sorties :
119: --------------------------------------------------------------------------------
120: Effets de bord : néant
121: ================================================================================
122: */
123:
124: static void
125: inversion_fonctions_arbre(struct_arbre *s_arbre)
126: {
127: return;
128: }
129:
130:
131: static void
132: simplification_arbre(struct_processus *s_etat_processus,
133: struct_arbre **s_arbre)
134: {
135: return;
136: }
137:
138:
139: /*
140: ================================================================================
141: Fonction 'simplification' (ne libère pas les paramètres)
142: ================================================================================
143: Entrées : pointeur sur une structure struct_processus
144: --------------------------------------------------------------------------------
145: Sorties :
146: --------------------------------------------------------------------------------
147: Effets de bord : néant
148: ================================================================================
149: */
150:
151: struct_objet *
152: simplification(struct_processus *s_etat_processus, struct_objet *s_objet)
153: {
154: struct_objet *s_objet_simplifie;
155:
156: integer8 i;
157: integer8 nombre_arguments;
158:
159: struct_arbre *s_arbre;
160:
161: struct_liste_chainee *l_element_courant;
162:
163: // Attention : l_liste_locale et l_ancienne_liste_locale ne contiennent pas
164: // un pointeur sur une struct_objet, mais sur une struct_arbre.
165:
166: struct_liste_chainee *l_liste_locale;
167: struct_liste_chainee *l_ancienne_liste_locale;
168:
169: if ((*s_objet).type == ALG)
170: {
171: /*
172: * Transcription de l'expression algébrique en arbre q-aire
173: */
174:
175: l_liste_locale = NULL;
176: l_element_courant = (*s_objet).objet;
177:
178: while(l_element_courant != NULL)
179: {
180: switch((*(*l_element_courant).donnee).type)
181: {
182: // Toutes les fonctions (intrinsèques, extrinsèques et
183: // utilisateurs).
184:
185: case FCT:
186: {
187: // Il s'agit d'un objet de type ALG. Nous pouvons donc
188: // sauter les délimiteurs d'expression.
189:
190: if ((l_element_courant != (*s_objet).objet) &&
191: ((*l_element_courant).suivant != NULL))
192: {
193: nombre_arguments = (*((struct_fonction *)
194: (*(*l_element_courant).donnee).objet))
195: .nombre_arguments;
196:
197: // Si le nombre d'arguments vaut 0, la fonction
198: // apparaît en notation algébrique comme une fonction
199: // infixe.
200:
201: if (nombre_arguments == 0)
202: {
203: nombre_arguments = 2;
204: }
205:
206: if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
207: {
208: (*s_etat_processus).erreur_systeme =
209: d_es_allocation_memoire;
210: return(NULL);
211: }
212:
213: (*s_arbre).inversion = d_faux;
214: (*s_arbre).nombre_branches = nombre_arguments;
215: (*s_arbre).feuille = copie_objet(s_etat_processus,
216: (*l_element_courant).donnee, 'P');
217:
218: if (((*s_arbre).branches = malloc(((size_t) (*s_arbre)
219: .nombre_branches) * sizeof(struct_arbre *)))
220: == NULL)
221: {
222: (*s_etat_processus).erreur_systeme =
223: d_es_allocation_memoire;
224: return(NULL);
225: }
226:
227: for(i = nombre_arguments - 1; i >= 0; i--)
228: {
229: if (l_liste_locale == NULL)
230: {
231: (*s_etat_processus).erreur_execution =
232: d_ex_manque_argument;
233: return(NULL);
234: }
235:
236: (*s_arbre).branches[i] = (struct_arbre *)
237: (*l_liste_locale).donnee;
238:
239: l_ancienne_liste_locale = l_liste_locale;
240: l_liste_locale = (*l_liste_locale).suivant;
241:
242: liberation_maillon(s_etat_processus,
243: l_ancienne_liste_locale);
244: }
245:
246: // Introduction de l'arbre dans la pile locale
247:
248: l_ancienne_liste_locale = l_liste_locale;
249:
250: if ((l_liste_locale = allocation_maillon(
251: s_etat_processus)) == NULL)
252: {
253: (*s_etat_processus).erreur_systeme =
254: d_es_allocation_memoire;
255: return(NULL);
256: }
257:
258: (*l_liste_locale).suivant = l_ancienne_liste_locale;
259: (*l_liste_locale).donnee = (void *) s_arbre;
260: }
261:
262: break;
263: }
264:
265: default:
266: {
267: l_ancienne_liste_locale = l_liste_locale;
268:
269: if ((l_liste_locale = allocation_maillon(s_etat_processus))
270: == NULL)
271: {
272: (*s_etat_processus).erreur_systeme =
273: d_es_allocation_memoire;
274: return(NULL);
275: }
276:
277: (*l_liste_locale).suivant = l_ancienne_liste_locale;
278:
279: if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
280: {
281: (*s_etat_processus).erreur_systeme =
282: d_es_allocation_memoire;
283: return(NULL);
284: }
285:
286: (*s_arbre).feuille = copie_objet(s_etat_processus,
287: (*l_element_courant).donnee, 'P');
288: (*s_arbre).inversion = d_faux;
289: (*s_arbre).nombre_branches = 0;
290: (*s_arbre).branches = NULL;
291:
292: (*l_liste_locale).donnee = (void *) s_arbre;
293: break;
294: }
295: }
296:
297: l_element_courant = (*l_element_courant).suivant;
298: }
299:
300: // Toute l'expression a été balayée. On ne doit plus avoir qu'un
301: // seul niveau dans la pile locale, ce niveau contenant l'arbre
302: // à réduire.
303:
304: if (l_liste_locale == NULL)
305: {
306: (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
307: return(NULL);
308: }
309: else if ((*l_liste_locale).suivant != NULL)
310: {
311: (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
312: return(NULL);
313: }
314:
315: s_arbre = (void *) (*l_liste_locale).donnee;
316:
317: liberation_maillon(s_etat_processus, l_liste_locale);
318: l_liste_locale = NULL;
319:
320: /*
321: * Simplification de l'arbre
322: */
323:
324: # ifdef EXPERIMENTAL_CODE
325: simplification_arbre(s_etat_processus, &s_arbre);
326:
327: if ((*s_etat_processus).erreur_systeme != d_es)
328: {
329: return(NULL);
330: }
331: # endif
332:
333: /*
334: * Transcription de l'arbre q-aire simplifié en expression algébrique.
335: * Seule une fonction récursive permet de faire cette conversion
336: * simplement.
337: */
338:
339: l_liste_locale = transcription_arbre(s_etat_processus, s_arbre);
340:
341: if ((s_objet_simplifie = allocation(s_etat_processus, ALG))
342: == NULL)
343: {
344: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
345: return(NULL);
346: }
347:
348: // Ajout des délimiteurs '<<' et '>>' à la liste d'instructions
349:
350: if (((*s_objet_simplifie).objet = allocation_maillon(s_etat_processus))
351: == NULL)
352: {
353: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
354: return(NULL);
355: }
356:
357: l_element_courant = (*s_objet_simplifie).objet;
358:
359: if (((*l_element_courant).donnee = allocation(s_etat_processus,
360: FCT)) == NULL)
361: {
362: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
363: return(NULL);
364: }
365:
366: (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
367: .nombre_arguments = 0;
368: (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
369: .fonction = instruction_vers_niveau_superieur;
370:
371: if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
372: .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
373: {
374: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
375: return(NULL);
376: }
377:
378: strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
379: .nom_fonction, "<<");
380:
381: (*l_element_courant).suivant = l_liste_locale;
382:
383: while((*l_element_courant).suivant != NULL)
384: {
385: l_element_courant = (*l_element_courant).suivant;
386: }
387:
388: if (((*l_element_courant).suivant =
389: allocation_maillon(s_etat_processus)) == NULL)
390: {
391: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
392: return(NULL);
393: }
394:
395: l_element_courant = (*l_element_courant).suivant;
396: (*l_element_courant).suivant = NULL;
397:
398: if (((*l_element_courant).donnee = allocation(s_etat_processus,
399: FCT)) == NULL)
400: {
401: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
402: return(NULL);
403: }
404:
405: (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
406: .nombre_arguments = 0;
407: (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
408: .fonction = instruction_vers_niveau_inferieur;
409:
410: if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
411: .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
412: {
413: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
414: return(NULL);
415: }
416:
417: strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
418: .nom_fonction, ">>");
419: }
420: else
421: {
422: s_objet_simplifie = copie_objet(s_etat_processus, s_objet, 'P');
423: }
424:
425: return(s_objet_simplifie);
426: }
427:
428: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>