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