]> git.llucax.com Git - z.facultad/75.42/calculadora.git/blob - parser_equation.c
Últimos retoques.
[z.facultad/75.42/calculadora.git] / parser_equation.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 "bool.h"
18 #include "equation.h"
19 #include "equation_list.h"
20 #include "parser_common.h"
21 #include "parseerror.h"
22 #include "dllist.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "memdebug_debugger.h"
28
29 #define PARSE_ERROR(str) ParseError_set_pos_message(error, str, i + 1, c)
30
31 bool parser_equation(const char* line, size_t len, DLList* equation_list,
32         ParseError* error) {
33     enum {SEARCH_VAR, VAR, SEARCH_EQUAL, EXP} state = SEARCH_VAR;
34     size_t var_start = 0;
35     size_t var_len = 0;
36     size_t i;
37     char c;
38     Equation* eq;
39     for (i = 0; i < len; i++) {
40         c = line[i];
41         switch (state) {
42             case SEARCH_VAR: /* Busca el comienzo de una variable. */
43                 if (!is_space(c)) {
44                     if (is_alpha(c)) {
45                         /* Es una letra => es el comienzo de la variable. */
46                         state = VAR;
47                         var_start = i;
48                     } else { /* es otra cosa => error */
49                         PARSE_ERROR("un espacio o una letra");
50                         return FALSE;
51                     }
52                 }
53                 /* Si es espacio, no hace nada, deja que siga. */
54                 break;
55             case VAR: /* Se fija cual es el nombre de la variable. */
56                 if (!is_alpha_num(c)) {
57                     if (is_space(c)) {
58                         /* Es un espacio, entonces hay que buscar un igual. */
59                         state = SEARCH_EQUAL;
60                         /* Calculo la longitud de la variable. */
61                         var_len = i - var_start;
62                     } else if (c == '=') {
63                         /* Es igual, empieza la expresión. */
64                         state = EXP;
65                         /* Calculo la longitud de la variable. */
66                         var_len = i - var_start;
67                     } else { /* es otra cosa */
68                         PARSE_ERROR(
69                                 "un espacio, una letra, un número o un igual");
70                         return FALSE;
71                     }
72                 }
73                 /* Si es alfanumérico, no hace nada, deja que siga. */
74                 break;
75             case SEARCH_EQUAL: /* Busca un signo de igual. */
76                 if (!is_space(c)) {
77                     if (c == '=') {
78                         /* Es igual, empieza la expresión. */
79                         state = EXP;
80                     } else { /* es otra cosa */
81                         PARSE_ERROR("un espacio o un igual");
82                         return FALSE;
83                     }
84                 }
85                 /* Si es espacio, no hace nada, deja que siga. */
86                 break;
87             case EXP: /* Encontró la expresión, la agrego a la lista. */
88                 eq = Equation_new(line, var_start, var_len,
89                         i, /* Comienzo de la ecuación */
90                         len - i); /* Longitud de la ecuación (sin el "\n") */
91                 /* No se pudo alocar la memoria. */
92                 if (!eq) {
93                     error->pos = 0;
94                     ParseError_set_message(error,
95                             "No se pudo alocar la memoria para la ecuación");
96                     return FALSE;
97                 }
98                 /* Lo agrego a la lista y si no se agregó bien da error. */
99                 if (!DLList_push(equation_list, eq)) {
100                     error->pos = 0;
101                     ParseError_set_message(error,
102                             "No se poner la ecuación en la lista");
103                     /* Elimino la ecuación recién creada. */
104                     Equation_delete(eq);
105                     return FALSE;
106                 }
107                 /* Se terminó todo bien. */
108                 return TRUE;
109         }
110     }
111     /* Error, no se llego a parsear todo bien. */
112     error->pos = len;
113     switch (state) {
114         case SEARCH_VAR:
115             ParseError_set_message(error,
116                     "No se encontró la definición de una variable");
117             break;
118         case VAR:
119         case SEARCH_EQUAL:
120             ParseError_set_message(error, "No se encontró un igual");
121             break;
122         case EXP:
123             ParseError_set_message(error, "No se encontró una expresión");
124             break;
125     }
126     return FALSE;
127 }
128
129 #undef PARSE_ERROR /* Sólo queremos usarlo en este fragmento */
130