1 /* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=0 fo+=t tw=80:
3 * Taller de Programación (75.42).
6 * Programa calculadora.
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/).
12 * Creado: dom sep 14 13:03:49 ART 2003
18 #include "parseerror.h"
19 #include "parser_common.h"
21 #include "variable_list.h"
28 #include "memdebug_debugger.h"
30 bool parser_expression(const char* exp, size_t len, float* result, DLList*
31 var_list, ParseError* error) {
39 /* Si es vacío, devuelve cero. */
44 /* Si es una expresión numérica, la devolvemos directamente. */
45 if ((exp[0] == '(') && (exp[len-1] == ')')) {
46 /* Si está entre paréntesis, se los sacamos. */
47 exp_cuted = strutil_copy_fragment(exp, 1, len - 2);
49 exp_cuted = strutil_copy_fragment(exp, 0, len);
51 /* No se pudo alocar la memoria. */
53 ParseError_set_message(error, "No se pudo alocar memoria");
56 /* Trato de convertirlo a float. */
57 *result = strtod(exp_cuted, &err);
58 if (*err == '\0') { /* OK */
62 /* No es un valor numérico, me fijo si está en la lista de variables. */
63 if (DLList_variable_find(var_list, exp_cuted)) {
64 *result = ((Variable*)DLList_current(var_list))->value;
69 /* No es una expresión numérica ni una variable, busco operadores de alta
71 for (i = 0; i < len; i++) {
73 /* Manejo los niveles de paréntesis. */
76 } else if (c == ')') {
78 /* Está en el nivel básico y hay un operador. */
79 } else if (((c == '+') || (c == '-')) && !level) {
80 /* No hay segundo operando. */
82 ParseError_set_message(error, "Falta segundo operando");
85 /* Calcula la expresión del primer operando. */
86 if (!parser_expression(exp, i, &result1, var_list, error)) {
87 /* Si hay error, devuelve FALSE (y "arrastra" el error. */
90 /* Calcula la expresión del segundo operando. */
91 if (!parser_expression(exp + i + 1, len - i - 1, &result2,
93 /* Si hay error, devuelve FALSE (y "arrastra" el error. */
96 *result = (c == '+') ? (result1 + result2) : (result1 - result2);
100 /* No hay tampoco operadores de alta precendencia, busco operadores de baja
102 for (i = 0; i < len; i++) {
104 /* Manejo los niveles de paréntesis. */
107 } else if (c == ')') {
109 /* Está en el nivel básico y hay un operador. */
110 } else if (((c == '*') || (c == '/')) && !level) {
111 /* No hay segundo operando. */
113 ParseError_set_message(error, "Falta segundo operando");
116 /* Calcula la expresión del primer operando. */
117 if (!parser_expression(exp, i, &result1, var_list, error)) {
118 /* Si hay error, devuelve FALSE (y "arrastra" el error. */
121 /* Calcula la expresión del segundo operando. */
122 if (!parser_expression(exp + i + 1, len - i - 1, &result2,
124 /* Si hay error, devuelve FALSE (y "arrastra" el error. */
127 /* Si estamos dividiendo, chequeamos que el divisor no sea cero. */
129 /* Segundo operando es cero. */
130 if (result2 == 0.0) {
131 ParseError_set_message(error, "División por cero");
134 *result = result1 / result2;
135 /* Si estamos multiplicando, no hay chequeos extra. */
137 *result = result1 * result2;
142 /* Si no tiene operadores ni valores numéricos ni es una variable, pero está
143 * entre paréntesis, pruebo de evaluar lo que está dentro de los paréntesis.
145 if ((exp[0] == '(') && (exp[len-1] == ')')) {
146 if (!parser_expression(exp + 1, len - 2, result, var_list, error)) {
147 /* Si hay error, devuelve FALSE (y "arrastra" el error. */
153 /* Si no tiene operadores ni valores numéricos ni es una variable, es un
155 ParseError_set_message(error, "La expresión es incorrecta");