]> git.llucax.com Git - z.facultad/75.42/calculadora.git/blob - parser_equation.c
a84925ee90b7eacd53b9419a48439423e35c4803
[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 #define PARSE_ERROR(str) ParseError_set_pos_message(error, str, i + 1, c)
51
52 bool parser_equation(const char* line, size_t len, DLList* equation_list,
53         ParseError* error) {
54     enum {SEARCH_VAR, VAR, SEARCH_EQUAL, EXP} state = SEARCH_VAR;
55     size_t var_start = 0;
56     size_t var_len = 0;
57     size_t i;
58     char c;
59     Equation* eq;
60     for (i = 0; i < len; i++) {
61         c = line[i];
62         switch (state) {
63             case SEARCH_VAR: /* Busca el comienzo de una variable. */
64                 if (!is_space(c)) {
65                     if (is_alpha(c)) {
66                         /* Es una letra => es el comienzo de la variable. */
67                         state = VAR;
68                         var_start = i;
69                     } else { /* es otra cosa => error */
70                         PARSE_ERROR("un espacio o una letra");
71                         return FALSE;
72                     }
73                 }
74                 /* Si es espacio, no hace nada, deja que siga. */
75                 break;
76             case VAR: /* Se fija cual es el nombre de la variable. */
77                 if (!is_alpha_num(c)) {
78                     if (is_space(c)) {
79                         /* Es un espacio, entonces hay que buscar un igual. */
80                         state = SEARCH_EQUAL;
81                         /* Calculo la longitud de la variable. */
82                         var_len = i - var_start;
83                     } else if (c == '=') {
84                         /* Es igual, empieza la expresión. */
85                         state = EXP;
86                         /* Calculo la longitud de la variable. */
87                         var_len = i - var_start;
88                     } else { /* es otra cosa */
89                         PARSE_ERROR(
90                                 "un espacio, una letra, un número o un igual");
91                         return FALSE;
92                     }
93                 }
94                 /* Si es alfanumérico, no hace nada, deja que siga. */
95                 break;
96             case SEARCH_EQUAL: /* Busca un signo de igual. */
97                 if (!is_space(c)) {
98                     if (c == '=') {
99                         /* Es igual, empieza la expresión. */
100                         state = EXP;
101                     } else { /* es otra cosa */
102                         PARSE_ERROR("un espacio o un igual");
103                         return FALSE;
104                     }
105                 }
106                 /* Si es espacio, no hace nada, deja que siga. */
107                 break;
108             case EXP: /* Encontró la expresión, la agrego a la lista. */
109                 eq = Equation_new(line, var_start, var_len,
110                         i, /* Comienzo de la ecuación */
111                         len - i); /* Longitud de la ecuación (sin el "\n") */
112                 /* No se pudo alocar la memoria. */
113                 if (!eq) {
114                     error->pos = 0;
115                     ParseError_set_message(error,
116                             "No se pudo alocar la memoria para la ecuación");
117                     return FALSE;
118                 }
119                 /* Lo agrego a la lista y si no se agregó bien da error. */
120                 if (!DLList_push(equation_list, eq)) {
121                     error->pos = 0;
122                     ParseError_set_message(error,
123                             "No se poner la ecuación en la lista");
124                     /* Elimino la ecuación recién creada. */
125                     Equation_delete(eq);
126                     return FALSE;
127                 }
128                 /* Se terminó todo bien. */
129                 return TRUE;
130         }
131     }
132     /* Error, no se llego a parsear todo bien. */
133     error->pos = len;
134     switch (state) {
135         case SEARCH_VAR:
136             ParseError_set_message(error,
137                     "No se encontró la definición de una variable");
138             break;
139         case VAR:
140         case SEARCH_EQUAL:
141             ParseError_set_message(error, "No se encontró un igual");
142             break;
143         case EXP:
144             ParseError_set_message(error, "No se encontró una expresión");
145             break;
146     }
147     return FALSE;
148 }
149
150 #undef PARSE_ERROR /* Sólo queremos usarlo en este fragmento */
151