X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=parser.c;h=b9823abaa25f10acd08cc4f40e2667a2e94ea902;hb=e2a309f921968691af1566000dd694f191eca857;hp=223b173bafd76faf34ba7ac0eca01f7b438d1965;hpb=a28ab26a7d2d420a63cbbfdec0d2450263ecc352;p=calc.git diff --git a/parser.c b/parser.c index 223b173..b9823ab 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 @@ -137,7 +62,7 @@ keyword_t operators[NB_OPERATORS] = { { "|", Or, 2, 1, -2} }; -#define NB_FUNCTIONS 50 +#define NB_FUNCTIONS 51 keyword_t functions[NB_FUNCTIONS] = { { "sqrt", Sqr, 1, 4, 5}, { "pow", Pow, 2, 3, 5}, @@ -160,7 +85,7 @@ keyword_t functions[NB_FUNCTIONS] = { { "inc", Inc, 1, 3, 5}, { "dec", Dec, 1, 3, 5}, { "disp", Disp, 0, 4, 9}, - { "mem", Mem, 1, 3, 5}, + { "mem", Memory, 1, 3, 5}, { "clr", Clear, 0, 3, 9}, { "quit", Quit, 0, 4, 9}, { "help", Help, 0, 4, 9}, @@ -189,6 +114,7 @@ keyword_t functions[NB_FUNCTIONS] = { { "prod", Prod, 0, 4, 5}, { "sum", Sum, 0, 3, 5}, { "var", Variance, 2, 3, 5}, + { "format", Precision, 1, 6, 9} }; #define NB_CONSTANTS 3 @@ -556,7 +482,7 @@ void print_element (element_t *root, int level) case Inc: func = "Increase"; break; case Dec: func = "Decrease"; break; case Disp: func = "Display"; break; - case Mem: func = "Memory"; break; + case Memory: func = "Memory"; break; case Clear: func = "Clear"; break; case Quit: func = "Quit"; break; case Help: func = "Help"; break; @@ -597,6 +523,7 @@ void print_element (element_t *root, int level) case Prod: func = "Product"; break; case Sum: func = "Sum"; break; case Variance: func = "Variance"; break; + case Precision: func = "Precision"; break; } fprintf (stdout, "Function: %s\n", func); @@ -613,100 +540,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) @@ -748,37 +581,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) @@ -787,482 +589,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) @@ -1293,7 +619,7 @@ void help (void) fprintf (stdout, "stack func.:"); fprintf (stdout, " max mean med min ord prod sum var\n"); fprintf (stdout, "control management:"); - fprintf (stdout, " help quit\n"); + fprintf (stdout, " format help quit\n"); fprintf (stdout, "constants:"); fprintf (stdout, " ans e pi\n"); } @@ -1345,7 +671,6 @@ double evaluate_element (element_t *root, char mask) case Div: case Mod: case Pow: - case Store: case Equal: case Diff: case Ge: @@ -1356,7 +681,7 @@ double evaluate_element (element_t *root, char mask) case Or: if (root->ops[1]) { op1 = evaluate_element (root->ops[1], nextmask); - } else if (root->func != Store) { + } else { VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[1])\n")); return 0; } @@ -1380,7 +705,6 @@ double evaluate_element (element_t *root, char mask) case Inc: case Dec: case Not: - case Mem: case Cond: case Prog: case Arg: @@ -1419,10 +743,22 @@ double evaluate_element (element_t *root, char mask) return 0; } break; + case Memory: + if (root->ops[0] == NULL) { + op0 = -1; + } else { + op0 = (int)evaluate_element (root->ops[0], 0); + if (op0 < 0) { + VERBOSE (WARNING, fprintf (stdout, "error incorrect memory size (%d)\n", (int)op0)); + return 0; + } + } + break; case Push: case Print: op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : answer; break; + case Store: case Put: if (root->ops[0]) { op0 = evaluate_element (root->ops[0], 0); @@ -1440,6 +776,10 @@ double evaluate_element (element_t *root, char mask) op0 = evaluate_element (root->ops[0], 0); op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer; } + break; + case Precision: + op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : -1; + break; } switch (root->func) { @@ -1466,12 +806,12 @@ double evaluate_element (element_t *root, char mask) case Abs: return fabs (op0); case Ceil: return ceil (op0); case Floor: return floor (op0); - case Store: return store ((int)op0, (op1) ? op1 : answer); + case Store: return store ((int)op0, op1); case Recall: return recall ((int)op0); case Inc: return increase ((int)op0); case Dec: return decrease ((int)op0); case Disp: display (); break; - case Mem: memory ((int)op0); break; + case Memory: return memory ((root->ops[0]) ? (int)op0 : -1); case Clear: clear (); break; case Quit: quit (); break; case Help: help (); break; @@ -1504,7 +844,7 @@ double evaluate_element (element_t *root, char mask) break; case Arg: return arg ((int)op0); case Call: - for (i = 1, nb =0; i < root->nbops; i++) { + for (i = 1, nb = 0; i < root->nbops; i++) { if (root->ops[i]) { nb++; } @@ -1553,6 +893,15 @@ double evaluate_element (element_t *root, char mask) return op0 * op0 + op1 * op1; } return variance (); + case Precision: + if (op0 > 0) { + set_precision ((int)op0); + set_format (); + } else if (op0 != -1) { + VERBOSE (WARNING, fprintf (stdout, "error incorrect precision (%g)\n", op0)); + return 0; + } + return get_precision(); } return 0; @@ -1613,5 +962,4 @@ void free_completion_list (char **list) } } - /* vim: set ts=4 sw=4 et: */