probó si anda.
--- /dev/null
+/* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=0 fo+=t tw=80:
+ *
+ * Taller de Programación (75.42).
+ *
+ * Ejercicio Número 2:
+ * Programa calculadora.
+ *
+ * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
+ * Puede copiar, modificar y distribuir este programa bajo los términos de
+ * la licencia GPL (http://www.gnu.org/).
+ *
+ * Creado: lun sep 15 01:10:28 ART 2003
+ *
+ * $Id$
+ */
+
+#include "equation.h"
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Copia un fragmento de una cadena devolviendo el puntero a la copia.
+ */
+char* Equation_copy_fragment(const char* str, size_t start, size_t len) {
+ /* Reservo el espacio (incluyendo el caracter nulo). */
+ char* new = malloc(sizeof(char) * (len + 1));
+ if (new) {
+ /* Copio el fragmento. */
+ strncpy(new, str + start, len);
+ /* Termino la cadena. */
+ new[len] = '\0';
+ /* Si no pude reservar la memoria, devuelvo NULL. */
+ }
+ return new;
+}
+
+Equation* Equation_new(const char* line, size_t var_start, size_t var_len,
+ size_t exp_start, size_t exp_len) {
+ Equation* eq = malloc(sizeof(Equation));
+ if (eq) {
+ /* Copio el fragmento de la variable. */
+ eq->variable = Equation_copy_fragment(line, var_start, var_len);
+ /* Si no hay más memoria, libero el resto y devuelvo NULL. */
+ if (!eq->variable) {
+ free(eq);
+ return NULL;
+ }
+ /* Copio el fragmento de la ecuación. */
+ eq->expression = Equation_copy_fragment(line, exp_start, exp_len);
+ /* Si no hay más memoria, libero el resto y devuelvo NULL. */
+ if (!eq->expression) {
+ free(eq->variable);
+ free(eq);
+ return NULL;
+ }
+ }
+ return eq;
+}
+
+void Equation_delete(Equation* eq) {
+ if (eq) {
+ free(eq->variable);
+ free(eq->expression);
+ }
+ free(eq);
+}
+
--- /dev/null
+/* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t tw=80:
+ *
+ * Taller de Programación (75.42).
+ *
+ * Ejercicio Número 2:
+ * Programa calculadora.
+ *
+ * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
+ * Puede copiar, modificar y distribuir este programa bajo los términos de
+ * la licencia GPL (http://www.gnu.org/).
+ *
+ * Creado: lun sep 15 01:15:27 ART 2003
+ *
+ * $Id$
+ */
+
+#ifndef EQUATION_H
+#define EQUATION_H
+
+/*#include "bool.h"*/
+#include <stdlib.h>
+
+typedef struct {
+ char* variable;
+ char* expression;
+} Equation;
+
+Equation* Equation_new(const char* line, size_t var_start, size_t var_len,
+ size_t exp_start, size_t exp_len);
+
+void Equation_delete(Equation* eq);
+
+#endif /* EQUATION_H */
--- /dev/null
+/* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=0 fo+=t tw=80:
+ *
+ * Taller de Programación (75.42).
+ *
+ * Ejercicio Número 2:
+ * Programa calculadora.
+ *
+ * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
+ * Puede copiar, modificar y distribuir este programa bajo los términos de
+ * la licencia GPL (http://www.gnu.org/).
+ *
+ * Creado: lun sep 15 00:02:35 ART 2003
+ *
+ * $Id$
+ */
+
+#include "parseerror.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+ParseError* ParseError_new(void) {
+ ParseError* pe = malloc(sizeof(ParseError));
+ if (pe) {
+ pe->line = 0;
+ pe->pos = 0;
+ pe->message = NULL;
+ }
+ return pe;
+}
+
+void ParseError_delete(ParseError* pe) {
+ if (pe) {
+ free(pe->message);
+ }
+ free(pe);
+}
+
+bool ParseError_set_message(ParseError* pe, const char* msg) {
+ /* Si había otro mensaje, liberamos la memoria */
+ if (pe->message) {
+ free(pe->message);
+ }
+ /* Aloco nueva memoria. */
+ pe->message = malloc(sizeof(char) * (strlen(msg) + 1));
+ if (pe->message) {
+ strcpy(pe->message, msg);
+ }
+ return pe->message ? TRUE : FALSE;
+}
+
+bool ParseError_set_pos_message(ParseError* pe, const char* msg, size_t pos,
+ char wrong_char) {
+ /* Si había otro mensaje, liberamos la memoria */
+ if (pe->message) {
+ free(pe->message);
+ }
+ /* Aloco nueva memoria. */
+ pe->message = malloc(
+ sizeof("Se buscaba ")
+ + sizeof(char) * strlen(msg) /* Tamaño del mensaje */
+ + sizeof(", pero se encontró '")
+ + sizeof(char) /* un char para imprimir el caracter encontrado */
+ + sizeof("' (0x")
+ + sizeof(char) * 2 /* dos char para poner el numero */
+ + sizeof(")")
+ + sizeof(char) /* un char para el caracter nulo (fin de string) */
+ );
+ if (pe->message) {
+ /* Copio el nuevo mensaje. */
+ sprintf(pe->message, "Se buscaba %s pero se encontró '%c' (0x%02X)",
+ msg, wrong_char, pos);
+ }
+ return pe->message ? TRUE : FALSE;
+}
+
--- /dev/null
+/* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t tw=80:
+ *
+ * Taller de Programación (75.42).
+ *
+ * Ejercicio Número 2:
+ * Programa calculadora.
+ *
+ * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
+ * Puede copiar, modificar y distribuir este programa bajo los términos de
+ * la licencia GPL (http://www.gnu.org/).
+ *
+ * Creado: sáb ago 30 19:59:12 ART 2003
+ *
+ * $Id$
+ */
+
+#ifndef PARSEERROR_H
+#define PARSEERROR_H
+
+#include "bool.h"
+#include <stdlib.h>
+
+typedef struct {
+ size_t line;
+ size_t pos;
+ char* message;
+} ParseError;
+
+ParseError* ParseError_new(void);
+
+void ParseError_delete(ParseError* pe);
+
+/**
+ * \return TRUE si se pudo alocar la memoria necesaria, FALSE si no.
+ */
+bool ParseError_set_message(ParseError* pe, const char* msg);
+
+/**
+ * \return TRUE si se pudo alocar la memoria necesaria, FALSE si no.
+ */
+bool ParseError_set_pos_message(ParseError* pe, const char* msg, size_t pos,
+ char wrong_char);
+
+#endif /* PARSEERROR_H */
--- /dev/null
+/* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=0 fo+=t tw=80:
+ *
+ * Taller de Programación (75.42).
+ *
+ * Ejercicio Número 2:
+ * Programa calculadora.
+ *
+ * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
+ * Puede copiar, modificar y distribuir este programa bajo los términos de
+ * la licencia GPL (http://www.gnu.org/).
+ *
+ * Creado: dom sep 14 13:03:49 ART 2003
+ *
+ * $Id$
+ */
+
+#include "bool.h"
+#include "equation.h"
+#include "parseerror.h"
+#include "dllist.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+bool is_space(char c) {
+ return (c == ' ') || (c == '\t');
+}
+
+bool is_number(char c) {
+ return ('0' < c) && (c < '9');
+}
+
+bool is_alpha(char c) {
+ return (c == '_') || (('a' < c) && (c < 'z')) || (('A' < c) && (c < 'Z'));
+}
+
+bool is_alpha_num(c) {
+ return is_number(c) || is_alpha(c);
+}
+
+#define PARSE_ERROR(str) ParseError_set_pos_message(error, str, i, c)
+
+bool parser_equation(const char* line, size_t len, DLList* equation_list,
+ ParseError* error) {
+ enum {SEARCH_VAR, VAR, SEARCH_EQUAL, EXP} state = SEARCH_VAR;
+ size_t var_start = 0;
+ size_t var_len = 0;
+ size_t i;
+ char c;
+ Equation* eq;
+ for (i = 0; i < len; i++) {
+ switch (state) {
+ case SEARCH_VAR: /* Busca el comienzo de una variable. */
+ if (!is_space(c)) {
+ if (is_alpha(c)) {
+ /* Es una letra => es el comienzo de la variable. */
+ state = VAR;
+ var_start = i;
+ } else { /* es otra cosa => error */
+ PARSE_ERROR("un espacio o una letra");
+ return FALSE;
+ }
+ }
+ /* Si es espacio, no hace nada, deja que siga. */
+ break;
+ case VAR: /* Se fija cual es el nombre de la variable. */
+ if (!is_alpha_num(c)) {
+ if (is_space(c)) {
+ /* Es un espacio, entonces hay que buscar un igual. */
+ state = SEARCH_EQUAL;
+ /* Calculo la longitud de la variable. */
+ var_len = i - var_start;
+ } else if (c == '=') {
+ /* Es igual, empieza la expresión. */
+ state = EXP;
+ } else { /* es otra cosa */
+ PARSE_ERROR(
+ "un espacio, una letra, un número o un igual");
+ return FALSE;
+ }
+ }
+ /* Si es alfanumérico, no hace nada, deja que siga. */
+ break;
+ case SEARCH_EQUAL: /* Busca un signo de igual. */
+ if (!is_space(c)) {
+ if (c == '=') {
+ /* Es igual, empieza la expresión. */
+ state = EXP;
+ } else { /* es otra cosa */
+ PARSE_ERROR("un espacio o un igual");
+ return FALSE;
+ }
+ }
+ /* Si es espacio, no hace nada, deja que siga. */
+ break;
+ case EXP: /* Encontró la expresión, la agrego a la lista. */
+ eq = Equation_new(line, var_start, var_len,
+ i, /* Comienzo de la ecuación */
+ len - i); /* Longitud de la ecuación (sin el "\n") */
+ /* No se pudo alocar la memoria. */
+ if (!eq) {
+ error->pos = 0;
+ ParseError_set_message(error,
+ "No se pudo alocar la memoria para la ecuación");
+ return FALSE;
+ }
+ /* Lo agrego a la lista y si no se agregó bien da error. */
+ if (!DLList_push(equation_list, eq)) {
+ error->pos = 0;
+ ParseError_set_message(error,
+ "No se poner la ecuación en la lista");
+ /* Elimino la ecuación recién creada. */
+ Equation_delete(eq);
+ return FALSE;
+ }
+ /* Se terminó todo bien. */
+ return TRUE;
+ }
+ }
+ /* Error, no se llego a parsear todo bien. */
+ error->pos = len;
+ switch (state) {
+ case SEARCH_VAR:
+ ParseError_set_message(error,
+ "No se encontró la definición de una variable");
+ break;
+ case VAR:
+ case SEARCH_EQUAL:
+ ParseError_set_message(error, "No se encontró un igual");
+ break;
+ case EXP:
+ ParseError_set_message(error, "No se encontró una expresión");
+ break;
+ }
+ return FALSE;
+}
+
+#undef PARSE_ERROR /* Sólo queremos usarlo en este fragmento */
+
--- /dev/null
+/* vim: set et sts=4 sw=4 fdm=indent fdl=1 fdn=1 fo+=t tw=80:
+ *
+ * Taller de Programación (75.42).
+ *
+ * Ejercicio Número 2:
+ * Programa calculadora.
+ *
+ * Copyleft 2003 - Leandro Lucarella <llucare@fi.uba.ar>
+ * Puede copiar, modificar y distribuir este programa bajo los términos de
+ * la licencia GPL (http://www.gnu.org/).
+ *
+ * Creado: lun sep 15 01:26:35 ART 2003
+ *
+ * $Id$
+ */
+
+#ifndef PARSER_EQUATION_H
+#define PARSER_EQUATION_H
+
+#include "bool.h"
+#include "parseerror.h"
+#include "dllist.h"
+#include <stdlib.h>
+
+/* TODO:
+ *
+ * opcion1:
+ * que devuelva la posición en donde empieza la exresión o cero si hubo
+ * error. En otro lugar debe dejar la variable que se parseo.
+ *
+ * opcion2: <---------------------------- Creo que es la mejor.
+ * Que devuelva una estructura con
+ * - variable.
+ * - expresion.
+ *
+ * opcion3:
+ * Que devuelva una estructura de nodo de variable o de ecuacion segun como
+ * se la llame.
+ */
+bool parser_equation(const char* line, size_t len, DLList* equation_list,
+ ParseError* error);
+
+#endif /* PARSER_EQUATION_H */