]> git.llucax.com Git - z.facultad/75.42/calculadora.git/blob - parser_expression.c
Primera version (muy prematura) del parser de expresiones.
[z.facultad/75.42/calculadora.git] / parser_expression.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: parser_equation.c 50 2003-09-15 06:44:27Z luca $
15  */
16
17 #include "bool.h"
18 #include "parseerror.h"
19 #include "dllist.h"
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23
24 bool is_space(char c) {
25     return (c == ' ') || (c == '\t');
26 }
27
28 bool is_number(char c) {
29     return ('0' <= c) && (c <= '9');
30 }
31
32 bool is_alpha(char c) {
33     return (c == '_') || (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'));
34 }
35
36 bool is_alpha_num(c) {
37     return is_number(c) || is_alpha(c);
38 }
39
40 size_t DLList_equation_print(DLList* l, FILE* fp) {
41     size_t cant = 0;
42     Equation* eq;
43     for (eq = DLList_begin(l); DLList_have_more(l); eq = DLList_next(l)) {
44         cant += Equation_print(eq, fp);
45     }
46     return cant;
47 }
48
49 void DLList_equation_delete(DLList* l) {
50     if (l) {
51         while (!DLList_empty(l)) {
52             Equation_delete((Equation*)DLList_pop(l));
53         }
54     }
55     DLList_delete(l);
56 }
57
58 #define PARSE_ERROR(str) ParseError_set_pos_message(error, str, i + 1, c)
59
60 bool parser_expression(const char* exp, size_t len, float* result,
61         ParseError* error) {
62     enum {SEARCH_VAR, VAR, SEARCH_EQUAL, EXP} state = SEARCH_VAR;
63     size_t var_start = 0;
64     size_t var_len = 0;
65     size_t i;
66     char c;
67     /* Si es una expresión numérica, la devolvemos directamente. */
68     *result = strntod(exp, len, &err);
69     if (*err == '\0') { /* OK */
70         return TRUE; /* La expresión es numérica (FIXME: puede ser numérica
71                         entre paréntesis y esto falla). */
72     }
73     /* No es una expresión numérica, busco operadores de alta precedencia. */
74     for (i = 0; i < len; i++) {
75         c = exp[i];
76         if ((c == '(')) {
77             level++;
78         } else if (c == ')') {
79             level--;
80         } else if (((c == '+') || (c == '-')) && !level) {
81             /* FIXME: Es una operador => segundo operando. */
82             if (!parser_expression(exp, i - 1, result1, error)) {
83                 return FALSE;
84             }
85             /* FIXME: verificar que no este vacío el segundo operando. */
86             if (!parser_expression(exp + i + 1, len - i - 1, result2, error)) {
87                 return FALSE;
88             }
89         } else if (((c == '+') || (c == '-')) && !level) {
90         } else { /* es otra cosa => error */
91             PARSE_ERROR("un espacio o una letra");
92             return FALSE;
93         }
94     }
95     /* Error, no se llego a parsear todo bien. */
96     error->pos = len;
97     switch (state) {
98         case SEARCH_VAR:
99             ParseError_set_message(error,
100                     "No se encontró la definición de una variable");
101             break;
102         case VAR:
103         case SEARCH_EQUAL:
104             ParseError_set_message(error, "No se encontró un igual");
105             break;
106         case EXP:
107             ParseError_set_message(error, "No se encontró una expresión");
108             break;
109     }
110     return FALSE;
111 }
112
113 #undef PARSE_ERROR /* Sólo queremos usarlo en este fragmento */
114