]> git.llucax.com Git - z.facultad/75.42/calculadora.git/blob - parser_variable.c
Se completa el TP. Aparentemente anda todo. Falta documentación.
[z.facultad/75.42/calculadora.git] / parser_variable.c
1 /* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=0 fo+=t tw=80:
2  *
3  * Taller de Programación (75.42).
4  *
5  * Ejercicio Número 2:
6  * Programa calculadora.
7  *
8  * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
9  * Puede copiar, modificar y distribuir este programa bajo los términos de
10  * la licencia GPL (http://www.gnu.org/).
11  *
12  * Creado: dom sep 14 13:03:49 ART 2003
13  *
14  * $Id$
15  */
16
17 #include "parser_variable.h"
18 #include "bool.h"
19 #include "variable.h"
20 #include "variable_list.h"
21 #include "parser_common.h"
22 #include "parseerror.h"
23 #include "dllist.h"
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "memdebug_debugger.h"
29
30 #define PARSE_ERROR(str) ParseError_set_pos_message(error, str, i + 1, c)
31
32 bool parser_variable(const char* line, size_t len, DLList* variable_list,
33         ParseError* error) {
34     enum {SEARCH_VAR, VAR, SEARCH_VAL, VAL, SEARCH_MIN, MIN, SEARCH_MAX, MAX}
35         state = SEARCH_VAR;
36     size_t var_start = 0;
37     size_t var_len   = 0;
38     size_t val_start = 0;
39     size_t val_len   = 0;
40     size_t min_start = 0;
41     size_t min_len   = 0;
42     size_t max_start = 0;
43     size_t max_len   = 0;
44     size_t i;
45     char c;
46     Variable* var;
47     for (i = 0; i < len; i++) {
48         c = line[i];
49         switch (state) {
50             case SEARCH_VAR: /* Busca el comienzo de una variable. */
51                 if (!is_space(c)) {
52                     if (is_alpha(c)) {
53                         /* Es una letra => es el comienzo de la variable. */
54                         state = VAR;
55                         var_start = i;
56                     } else { /* es otra cosa => error */
57                         PARSE_ERROR("un espacio o una letra");
58                         return FALSE;
59                     }
60                 }
61                 /* Si es espacio, no hace nada, deja que siga. */
62                 break;
63             case VAR: /* Se fija cual es el nombre de la variable. */
64                 if (!is_alpha_num(c)) {
65                     if (is_space(c)) {
66                         /* Es un espacio, entonces hay que buscar un igual. */
67                         state = SEARCH_VAL;
68                         /* Calculo la longitud de la variable. */
69                         var_len = i - var_start;
70                     } else { /* es otra cosa */
71                         PARSE_ERROR(
72                                 "un espacio, una letra, un número o un igual");
73                         return FALSE;
74                     }
75                 }
76                 /* Si es alfanumérico, no hace nada, deja que siga. */
77                 break;
78             case SEARCH_VAL: /* Busca el valor. */
79                 if (!is_space(c)) {
80                     /* Pasamos a interpretar el valor. */
81                     state = VAL;
82                     /* Pone el inicio del valor. */
83                     val_start = i;
84                     /* Calcula la longitud como si fuera hasta el final. */
85                     val_len = len - i;
86                 }
87                 /* Si es espacio, no hace nada, deja que siga. */
88                 break;
89             case VAL: /* Se fija hasta donde va el valor actual. */
90                 if (is_space(c)) { /* Si es un espacio, terminó el valor. */
91                     /* Buscamos otro valor. */
92                     state = SEARCH_MIN;
93                     /* Pone la longitud de este valor. */
94                     val_len = i - val_start;
95                 }
96                 /* Si es alfanumérico, no hace nada, deja que siga. */
97                 break;
98             case SEARCH_MIN: /* Busca el mímino. */
99                 if (!is_space(c)) {
100                     /* Pasamos a interpretar el mínimo. */
101                     state = MIN;
102                     /* Pone el inicio del mínimo. */
103                     min_start = i;
104                     /* Calcula la longitud como si fuera hasta el final. */
105                     min_len = len - i;
106                 }
107                 /* Si es espacio, no hace nada, deja que siga. */
108                 break;
109             case MIN: /* Se fija hasta donde va el mínimo. */
110                 if (is_space(c)) { /* Si es un espacio, terminó el mínimo. */
111                     /* Buscamos el máximo. */
112                     state = SEARCH_MAX;
113                     /* Pone la longitud del mínimo. */
114                     min_len = i - min_start;
115                 }
116                 /* Si es alfanumérico, no hace nada, deja que siga. */
117                 break;
118             case SEARCH_MAX: /* Busca el máximo. */
119                 if (!is_space(c)) {
120                     /* Pasamos al estado de máximo encontrado. */
121                     state = MAX;
122                     /* Pone el inicio del máximo. */
123                     max_start = i;
124                     /* Pone la longitud del máximo hasta el final (ya no hay más
125                      * valores a buscar). */
126                     max_len = len - i;
127                 }
128                 /* Si es espacio, no hace nada, deja que siga. */
129                 break;
130         }
131         /* Si status es max, no se busca mas nada, terminamo el loop for. */
132         if (state == MAX) {
133             break;
134         }
135     }
136     /* Veo como terminó la interpretación. */
137     error->pos = len;
138     /* No se pudo interpretar una variable. */
139     if (state < VAL) {
140         switch (state) {
141             case SEARCH_VAR:
142                 /* No tiene variable. */
143                 ParseError_set_message(error,
144                         "No se encontró la definición de una variable");
145                 return FALSE;
146             case VAR:
147             case SEARCH_VAL:
148                 /* No tiene valor de la variable. */
149                 ParseError_set_message(error,
150                         "No se encontró el valor de la variable");
151                 return FALSE;
152         }
153     }
154     /* Al menos la variable con su valor ya la tenemos. */
155     var = Variable_new(line, var_start, var_len);
156     if (!var) {
157         ParseError_set_message(error, "No se pudo alocar memoria de variable");
158         return FALSE;
159     }
160     switch (state) {
161         case MAX:
162             /* Tiene máximo. */
163             if (!Variable_set_max(var, line, max_start, max_len)) {
164                 /* No se pudo setear el máximo. */
165                 Variable_delete(var);
166                 ParseError_set_message(error,
167                         "No se pudo establecer el máximo");
168                 return FALSE;
169             }
170             /* Continúo, tiene mínimo y valor también. */
171         case MIN:
172         case SEARCH_MAX:
173             /* Tiene míninimo. */
174             if (!Variable_set_min(var, line, min_start, min_len)) {
175                 /* No se pudo setear el mínimo. */
176                 Variable_delete(var);
177                 ParseError_set_message(error,
178                         "No se pudo establecer el mínimo");
179                 return FALSE;
180             }
181             /* Continúo, tiene valor también. */
182         case VAL:
183         case SEARCH_MIN:
184             /* Tiene solo valor. */
185             if (!Variable_set_value(var, line, val_start, val_len)) {
186                 /* No se pudo setear el valor. */
187                 Variable_delete(var);
188                 ParseError_set_message(error,
189                         "No se pudo establecer el valor");
190                 return FALSE;
191             }
192     }
193     /* Está todo ok, tengo la variable cargada, verifico max y min. */
194     if (!Variable_check_min_max(var)) {
195         Variable_delete(var);
196         ParseError_set_message(error,
197                 "El mínimo es mayor que el máximo");
198         return FALSE;
199     }
200     /* Ahora sí, la puedo agregar a la lista de variables. */
201     if (DLList_variable_find(variable_list, var->variable)) {
202         /* Si ya había uno, lo borro. */
203         DLList_remove_current(variable_list);
204     }
205     if (!DLList_push(variable_list, var)) {
206         ParseError_set_message(error,
207                 "No se pudo agregar variable a la lista");
208         return FALSE;
209     }
210     return TRUE;
211 }
212
213 #undef PARSE_ERROR /* Sólo queremos usarlo en este fragmento */
214