]> git.llucax.com Git - z.facultad/75.42/calculadora.git/commitdiff
Se agrega la primera versión del parser de ecuaciones. Sólo compila, pero no se
authorLeandro Lucarella <llucax@gmail.com>
Mon, 15 Sep 2003 05:00:57 +0000 (05:00 +0000)
committerLeandro Lucarella <llucax@gmail.com>
Mon, 15 Sep 2003 05:00:57 +0000 (05:00 +0000)
probó si anda.

equation.c [new file with mode: 0644]
equation.h [new file with mode: 0644]
parseerror.c [new file with mode: 0644]
parseerror.h [new file with mode: 0644]
parser_equation.c [new file with mode: 0644]
parser_equation.h [new file with mode: 0644]

diff --git a/equation.c b/equation.c
new file mode 100644 (file)
index 0000000..3b0e36e
--- /dev/null
@@ -0,0 +1,67 @@
+/* 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);
+}
+
diff --git a/equation.h b/equation.h
new file mode 100644 (file)
index 0000000..8b5f8f5
--- /dev/null
@@ -0,0 +1,33 @@
+/* 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 */
diff --git a/parseerror.c b/parseerror.c
new file mode 100644 (file)
index 0000000..398143a
--- /dev/null
@@ -0,0 +1,76 @@
+/* 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;
+}
+
diff --git a/parseerror.h b/parseerror.h
new file mode 100644 (file)
index 0000000..9678584
--- /dev/null
@@ -0,0 +1,44 @@
+/* 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 */
diff --git a/parser_equation.c b/parser_equation.c
new file mode 100644 (file)
index 0000000..479c9e7
--- /dev/null
@@ -0,0 +1,139 @@
+/* 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 */
+
diff --git a/parser_equation.h b/parser_equation.h
new file mode 100644 (file)
index 0000000..a260893
--- /dev/null
@@ -0,0 +1,43 @@
+/* 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 */