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