X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=parser.c;h=1e9b9861731ac2ccbc81f844afbd9c80f91859d6;hb=a3f2e6cf008678cfa2b1a868e38fefbe81009971;hp=326dad384b916b135d27ca3b80c786ce8495f5ee;hpb=226557a3339d4f3f98547eef6deeb4ec512366d1;p=calc.git diff --git a/parser.c b/parser.c index 326dad3..1e9b986 100644 --- a/parser.c +++ b/parser.c @@ -1,10 +1,16 @@ -#include #include #include #include #include +#include "alloc.h" +#include "argument.h" #include "debug.h" +#include "element.h" +#include "format.h" +#include "program.h" +#include "stack.h" +#include "storage.h" #include "parser.h" @@ -12,23 +18,6 @@ double answer = 0; -#define DEFAULT_STORAGE_SIZE 10 -int storage_size = -1; -double *storage = NULL; - -int argument_size = 0; -double *argument = NULL; - -int stack_size = 0; -double *stack = NULL; - -#define DEFAULT_FORMAT "=> %.6g\n" -char *format = NULL; -char *minform = NULL; - -workspace_t *programs = NULL; -int nb_programs = 0; - /* compare codes */ int codecmp (char *ref, char *str) @@ -51,70 +40,6 @@ int codecmp (char *ref, char *str) return 0; } -/* calloc or die function */ - -void *callocordie (size_t count, size_t size) -{ - if (count * size == 0) { - return NULL; - } - void *new = calloc (count, size); - if (new == NULL) { - VERBOSE (ERROR, fprintf (stderr, "can't allocate memory\n")); - exit (1); - } - return new; -} - -/* allocate new element */ - -element_t *newelement (func_t function, int nbops, int prio) -{ - element_t *new = (element_t *) callocordie (1, sizeof (element_t)); - if (nbops) { - new->ops = (element_t **) callocordie (nbops, sizeof (element_t *)); - } - new->func = function; - new->nbops = nbops; - new->prio = prio; - - return new; -} - -/* desallocate element */ - -void delelement (element_t *root) -{ - if ((root != NULL) && (root != ERROR_OP)) { - int i; - for (i = 0; i < root->nbops; i++) { - delelement (root->ops[i]); - } - if (root->nbops) { - free (root->ops); - } - free (root); - } -} - -/* duplicate element */ - -element_t *dupelement (element_t *root) -{ - element_t *tmp = NULL; - int i; - - if ((root == NULL) || (root == ERROR_OP)) { - return root; - } - tmp = newelement (root->func, root->nbops, root->prio); - tmp->value = root->value; - for (i = 0; i < root->nbops; i++) { - tmp->ops[i] = dupelement (root->ops[i]); - } - return tmp; -} - /* functions */ #define MAX_ARGS 100 @@ -367,7 +292,11 @@ element_t *parser (char *str, char **next, int prio) keyword_t *operator = operators + i; if (codecmp (operator->keyword, str) == 0) { VERBOSE (DEBUG, fprintf (stdout, "start processing operator\n")); - if (root) { + if ((root) && (root->prio == 9)) { + VERBOSE (DEBUG, fprintf (stdout, "terminal function (%d)\n", root->func)); + delelement (root); + return ERROR_OP; + } else if (root) { if ((prio) && (prio > operator->prio)) { VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n")); *next = str; @@ -380,7 +309,7 @@ element_t *parser (char *str, char **next, int prio) return ERROR_OP; } } else if (*str == '-') { - root = newelement (Sig, 1, 9); + root = newelement (Sig, 1, 6); } else { return ERROR_OP; } @@ -609,100 +538,6 @@ void print_element (element_t *root, int level) } } -/* storage functions */ - -void memory (int nb) -{ - int i, l; - double *tmp = NULL; - if (nb != storage_size) { - l = (nb < storage_size) ? nb : storage_size; - tmp = (double *) callocordie (nb, sizeof (double)); - for (i = 0; i < l; i++) { - tmp[i] = storage[i]; - } - if (storage != NULL) { - free (storage); - } - storage = tmp; - storage_size = nb; - } -} - -double store (int index, double value) -{ - if (storage_size == -1) { - memory (DEFAULT_STORAGE_SIZE); - } - if ((index > 0) && (index <= storage_size)) { - storage[index - 1] = value; - } else { - VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); - } - return value; -} - -double recall (int index) -{ - if (storage_size == -1) { - memory (DEFAULT_STORAGE_SIZE); - } - if ((index > 0) && (index <= storage_size)) { - return storage[index - 1]; - } else { - VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); - } - return 0; -} - -double increase (int index) -{ - if (storage_size == -1) { - memory (DEFAULT_STORAGE_SIZE); - } - if ((index > 0) && (index <= storage_size)) { - return storage[index - 1]++; - } else { - VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); - } - return 0; -} - -double decrease (int index) -{ - if (storage_size == -1) { - memory (DEFAULT_STORAGE_SIZE); - } - if ((index > 0) && (index <= storage_size)) { - return storage[index - 1]--; - } else { - VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [%d, %d]\n", index, (storage_size) ? 1 : 0, storage_size)); - } - return 0; -} - -void display (void) -{ - int i; - if (storage_size == -1) { - memory (DEFAULT_STORAGE_SIZE); - } - fprintf (stdout, "storage:"); - for (i = 0; i < storage_size; i++) { - fprintf (stdout, " "); - fprintf (stdout, minform, storage[i]); - } - fprintf (stdout, "\n"); -} - -void clear () -{ - int i; - for (i = 0; i < storage_size; i++) { - storage[i] = 0; - } -} - /* While do function */ double while_do (element_t *cond, element_t *action) @@ -744,37 +579,6 @@ double execute_code (element_t **prog, int nbcalls) return ret; } -/* print function */ - -void set_format (char *prompt, int precision) -{ - char buffer[128] = {0}; - free_format (); - sprintf (buffer, "%s%%.%dg\n", prompt, precision); - format = strdup (buffer); - sprintf (buffer, "%%.%dg", precision); - minform = strdup (buffer); -} - -void free_format () -{ - if (format) { - free (format); - format = NULL; - } - if (minform) { - free (minform); - minform = NULL; - } -} - -double print (double value) -{ - fprintf (stdout, format ? format : DEFAULT_FORMAT, value); - fflush (stdout); - return value; -} - /* quit function */ void quit (void) @@ -783,482 +587,6 @@ void quit (void) exit (0); } -/* program function */ - -void prog (int id, element_t *root) -{ - int i, n = -1; - - if (programs == NULL) { - - /* initial memory allocation */ - programs = (workspace_t *) callocordie (1, sizeof (workspace_t)); - nb_programs = 1; - n = 0; - - } else { - - /* look for existing program */ - for (i = 0; i < nb_programs; i++) { - if ((programs + i)->id == id) { - n = i; - break; - } - } - if (n == -1) { - - /* new program */ - n = nb_programs++; - workspace_t *tmp = (workspace_t *) callocordie (nb_programs, sizeof (workspace_t)); - memcpy (tmp, programs, (nb_programs - 1) * sizeof (workspace_t)); - free (programs); - programs = tmp; - } else { - - /* clean old program */ - if ((programs + n)->storage) { - free ((programs + n)->storage); - } - if ((programs + n)->stack) { - free ((programs + n)->stack); - } - if ((programs + n)->root) { - delelement ((programs + n)->root); - } - if ((programs + n)->string) { - free ((programs + n)->string); - (programs + n)->string = NULL; - } - } - } - - /* set program */ - (programs + n)->id = id; - (programs + n)->answer = 0; - (programs + n)->storage = NULL; - (programs + n)->storage_size = 0; - (programs + n)->stack = NULL; - (programs + n)->stack_size = 0; - (programs + n)->root = dupelement (root); -} - -double arg (int id) -{ - double ret = 0; - if ((id <= 0) || (id > argument_size)) { - VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", id, argument_size)); - } else { - ret = argument[id - 1]; - } - return ret; -} - -double call (int id, int nbargs, element_t **args) -{ - workspace_t tmp = {0}; - int i, l, n = -1; - double ret = 0; - - if (programs) { - - /* look for program */ - for (i = 0; i < nb_programs; i++) { - if ((programs + i)->id == id) { - n = i; - break; - } - } - } - if (n == -1) { - VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id)); - return 0; - } - - /* store context */ - tmp.answer = answer; - tmp.argument = argument; - tmp.argument_size = argument_size; - tmp.storage = storage; - tmp.storage_size = storage_size; - tmp.stack = stack; - tmp.stack_size = stack_size; - - /* change context */ - answer = 0; - storage = (programs + n)->storage; - storage_size = (programs + n)->storage_size; - argument = NULL; - argument_size = 0; - stack = (programs + n)->stack; - stack_size = (programs + n)->stack_size; - if (nbargs > 0) { - argument = (double *) callocordie (nbargs, sizeof (double)); - for (i = 0, l = 0; i < nbargs; l++) { - if (args[l]) { - argument[i++] = evaluate_element (args[l], 0); - } - } - argument_size = nbargs; - } - - /* evaluate program */ - element_t *elements = dupelement ((programs + n)->root); - ret = evaluate_element (elements, 0); - delelement (elements); - (programs + n)->answer = answer; - (programs + n)->storage = storage; - (programs + n)->storage_size = storage_size; - if (argument) { - free (argument); - } - (programs + n)->stack = stack; - (programs + n)->stack_size = stack_size; - - /* restore context */ - answer = tmp.answer; - storage = tmp.storage; - storage_size = tmp.storage_size; - argument = tmp.argument; - argument_size = tmp.argument_size; - stack = tmp.stack; - stack_size = tmp.stack_size; - - return ret; -} - -void list () -{ - int i; - fprintf (stdout, "programs:"); - for (i = 0; i < nb_programs; i++) { - fprintf (stdout, " %d", (programs + i)->id); - } - fprintf (stdout, "\n"); -} - -void edit (int id) -{ - int i, n = -1; - - if (programs) { - - /* look for program */ - for (i = 0; i < nb_programs; i++) { - if ((programs + i)->id == id) { - n = i; - break; - } - } - } - if (n == -1) { - VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id)); - return; - } - - /* set string program */ - fprintf (stdout, "edit: %s\n", (programs + n)->string); -} - -void savestring (int id, char *string) -{ - int i, n = -1; - - if (programs) { - - /* look for program */ - for (i = 0; i < nb_programs; i++) { - if ((programs + i)->id == id) { - n = i; - break; - } - } - } - - /* unnecesary code */ - //if (n == -1) { - // VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id)); - // return; - //} - //if ((programs + n)->string) { - // free ((programs + n)->string); - //} - - if (string) { - (programs + n)->string = strdup (string); - } -} - -void del (int id) -{ - int i, j, n = -1; - - if (programs) { - - /* look for program */ - for (i = 0; i < nb_programs; i++) { - if ((programs + i)->id == id) { - n = i; - break; - } - } - } - if (n == -1) { - VERBOSE (WARNING, fprintf (stdout, "error unknown program (%d)\n", id)); - return; - } - - /* clean program */ - if ((programs + n)->storage) { - free ((programs + n)->storage); - } - if ((programs + n)->stack) { - free ((programs + n)->stack); - } - if ((programs + n)->root) { - delelement ((programs + n)->root); - } - if ((programs + n)->string) { - free ((programs + n)->string); - } - - /* remove entry */ - workspace_t *tmp = (workspace_t *) callocordie (nb_programs - 1, sizeof (workspace_t)); - for (i = 0, j = 0; i < nb_programs; i++) { - if (i != n) { - memcpy (tmp + j, programs + i, sizeof (workspace_t)); - j++; - } - } - free (programs); - programs = tmp; - nb_programs--; -} - -/* stack management */ - -double get (int n) -{ - double ret = 0; - if ((n <= 0) || (n > stack_size)) { - VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size)); - } else { - ret = stack[n - 1]; - } - return ret; -} - -double length () -{ - return stack_size; -} - -double pop () -{ - double ret = 0; - if (stack_size > 0) { - ret = stack[--stack_size]; - double *tmp = (double *) callocordie (stack_size, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - free (stack); - stack = tmp; - } else { - VERBOSE (WARNING, fprintf (stdout, "error stack empty\n")); - } - return ret; -} - -double push (double val) -{ - double *tmp = (double *) callocordie (stack_size + 1, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - if (stack) { - free (stack); - } - stack = tmp; - stack[stack_size++] = val; - return val; -} - -double put (int n, double val) -{ - if (n <= 0) { - VERBOSE (WARNING, fprintf (stdout, "error out of bound (%d/%d)\n", n, stack_size)); - return 0; - } - if (n > stack_size) { - double *tmp = (double *) callocordie (n, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - free (stack); - stack = tmp; - stack_size = n; - } - stack[n - 1] = val; - return val; -} - -double set (int nbops, element_t **ops) -{ - int i; - if (stack) { - free (stack); - } - stack = NULL; - stack_size = 0; - if (nbops != 0) { - stack = (double *) callocordie (nbops, sizeof (double)); - for (i = 0; i < nbops; i++) { - stack[i] = evaluate_element (ops[i], 0); - } - stack_size = nbops; - } - return stack_size; -} - -void show (void) -{ - int i; - fprintf (stdout, "stack:"); - for (i = 0; i < stack_size; i++) { - fprintf (stdout, " "); - fprintf (stdout, minform, stack[i]); - } - fprintf (stdout, "\n"); -} - -/* stack functions */ - -double max () -{ - double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - ret = stack[0]; - for (i = 1; i < stack_size; i++) { - if (stack[i] > ret) { - ret = stack[i]; - } - } - return ret; -} - -double mean () -{ - double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - for (i = 0; i < stack_size; i++) { - ret += stack[i]; - } - return ret / stack_size; -} - -double min () -{ - double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - ret = stack[0]; - for (i = 1; i < stack_size; i++) { - if (stack[i] < ret) { - ret = stack[i]; - } - } - return ret; -} - -void order () -{ - int i, j; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return; - } - for (i = 0; i < stack_size - 1; i++) { - int done = 0; - for (j = 0; j < stack_size - 1; j++) { - if (stack[j] > stack[j + 1]) { - double tmp = stack[j]; - stack[j] = stack[j + 1]; - stack[j + 1] = tmp; - done = 1; - } - } - if (done == 0) { - break; - } - } -} - -double median () -{ - double ret = 0; - if (stack_size < 3) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - double *tmp = (double *) callocordie (stack_size, sizeof (double)); - memcpy (tmp, stack, stack_size * sizeof (double)); - order (); - ret = stack[(stack_size - 1)/ 2]; - memcpy (stack, tmp, stack_size * sizeof (double)); - free (tmp); - return ret; -} - -double prod () -{ - double ret = 1; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - for (i = 0; i < stack_size; i++) { - ret *= stack[i]; - } - return ret; -} - -double sum () -{ - double ret = 0; - int i; - if (stack_size < 1) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - for (i = 0; i < stack_size; i++) { - ret += stack[i]; - } - return ret; -} - -double variance () -{ - double ret = 0; - double m = 0; - int i; - if (stack_size < 2) { - VERBOSE (WARNING, fprintf (stdout, "error not enough element in stack (%d)\n", stack_size)); - return 0; - } - m = mean (); - for (i = 0; i < stack_size; i++) { - ret += (stack[i] - m) * (stack[i] - m); - } - return ret / stack_size; -} - - /* help message */ void help (void) @@ -1609,5 +937,4 @@ void free_completion_list (char **list) } } - /* vim: set ts=4 sw=4 et: */