X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=parser.c;h=1e9b9861731ac2ccbc81f844afbd9c80f91859d6;hb=c91672f948d371d3ba2b1a47db9a31fcabb763f5;hp=74e980b39c4dac2ea4e3f812d7fe0483c8e9989e;hpb=4747e9a1aa15945d80f64feb9f23769d1d901c0e;p=calc.git diff --git a/parser.c b/parser.c index 74e980b..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,20 +18,6 @@ double answer = 0; -#define DEFAULT_STORAGE_SIZE 10 -int storage_size = -1; -double *storage = 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) @@ -48,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 @@ -134,7 +62,7 @@ keyword_t operators[NB_OPERATORS] = { { "|", Or, 2, 1, -2} }; -#define NB_FUNCTIONS 41 +#define NB_FUNCTIONS 50 keyword_t functions[NB_FUNCTIONS] = { { "sqrt", Sqr, 1, 4, 5}, { "pow", Pow, 2, 3, 5}, @@ -157,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, 9}, + { "mem", Mem, 1, 3, 5}, { "clr", Clear, 0, 3, 9}, { "quit", Quit, 0, 4, 9}, { "help", Help, 0, 4, 9}, @@ -165,7 +93,8 @@ keyword_t functions[NB_FUNCTIONS] = { { "cond", Cond, 3, 4, 5}, { "while", While, 2, 5, 5}, { "print", Print, 1, 5, 5}, - { "prog", Prog, 3, 4, 9}, + { "prog", Prog, 2, 4, 9}, + { "arg", Arg, 1, 3, 5}, { "call", Call, MAX_ARGS, 4, 5}, { "ls", List, 0, 2, 9}, { "edit", Edit, 1, 4, 9}, @@ -176,7 +105,15 @@ keyword_t functions[NB_FUNCTIONS] = { { "push", Push, 1, 4, 5}, { "put", Put, 2, 3, 5}, { "set", Set, MAX_ARGS, 3, 5}, - { "show", Show, 0, 4, 5}, + { "show", Show, 0, 4, 5}, + { "max", Max, 2, 3, 5}, + { "mean", Mean, 2, 4, 5}, + { "med", Median, 0, 3, 5}, + { "min", Min, 2, 3, 5}, + { "ord", Order, 0, 3, 5}, + { "prod", Prod, 0, 4, 5}, + { "sum", Sum, 0, 3, 5}, + { "var", Variance, 2, 3, 5}, }; #define NB_CONSTANTS 3 @@ -265,14 +202,14 @@ element_t *parser (char *str, char **next, int prio) delelement (root); return ERROR_OP; } - element_t *newprog = newelement (Code, root->nbops + 1, 5); + element_t *newcode = newelement (Code, root->nbops + 1, 5); for (i = 0; i < root->nbops; i++) { - newprog->ops[i] = root->ops[i]; + newcode->ops[i] = root->ops[i]; root->ops[i] = NULL; } - newprog->ops[root->nbops] = new; + newcode->ops[root->nbops] = new; delelement (root); - root = newprog; + root = newcode; } while (*str == ','); if (*str != '}') { @@ -355,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; @@ -368,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; } @@ -561,6 +502,7 @@ void print_element (element_t *root, int level) case Code: func = "Code"; break; case Print: func = "Print"; break; case Prog: func = "Program"; break; + case Arg: func = "Argument"; break; case Call: func = "Call"; break; case List: func = "List"; break; case Edit: func = "Edit"; break; @@ -572,6 +514,14 @@ void print_element (element_t *root, int level) case Put: func = "Put"; break; case Set: func = "Set"; break; case Show: func = "Show"; break; + case Max: func = "Maximum"; break; + case Mean: func = "Mean"; break; + case Median: func = "Median"; break; + case Min: func = "Minimum"; break; + case Order: func = "Order"; break; + case Prod: func = "Product"; break; + case Sum: func = "Sum"; break; + case Variance: func = "Variance"; break; } fprintf (stdout, "Function: %s\n", func); @@ -588,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) @@ -723,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) @@ -762,328 +587,6 @@ void quit (void) exit (0); } -/* program function */ - -void prog (int id, int nbmems, 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 = (double *) callocordie (nbmems, sizeof (double)); - (programs + n)->storage_size = nbmems; - (programs + n)->stack = NULL; - (programs + n)->stack_size = 0; - (programs + n)->root = dupelement (root); -} - -double call (int id, int nbops, element_t **ops) -{ - workspace_t tmp = {0}; - int i, 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.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; - stack = (programs + n)->stack; - stack_size = (programs + n)->stack_size; - if (nbops > storage_size) { - double *tmp = (double *) callocordie (nbops, sizeof (double)); - memcpy (tmp, storage, storage_size * sizeof (double)); - free (storage); - (programs + n)->storage = storage = tmp; - (programs + n)->storage_size = storage_size = nbops; - } - for (i = 0; i < nbops; i++) { - double val = evaluate_element (ops[i], 0); - store (i + 1, val); - } - - /* 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; - (programs + n)->stack = stack; - (programs + n)->stack_size = stack_size; - - /* restore context */ - answer = tmp.answer; - storage = tmp.storage; - storage_size = tmp.storage_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); - //} - - (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"); -} - /* help message */ void help (void) @@ -1108,9 +611,11 @@ void help (void) fprintf (stdout, "control flow prim.:"); fprintf (stdout, " cond print while {} ;\n"); fprintf (stdout, "program management:"); - fprintf (stdout, " call del edit ls prog\n"); + fprintf (stdout, " arg call del edit ls prog\n"); fprintf (stdout, "stack management:"); fprintf (stdout, " get len pop push put set show\n"); + 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, "constants:"); @@ -1173,7 +678,6 @@ double evaluate_element (element_t *root, char mask) case Lt: case And: case Or: - case Prog: if (root->ops[1]) { op1 = evaluate_element (root->ops[1], nextmask); } else if (root->func != Store) { @@ -1202,6 +706,8 @@ double evaluate_element (element_t *root, char mask) case Not: case Mem: case Cond: + case Prog: + case Arg: case Call: case Edit: case Del: @@ -1226,6 +732,10 @@ double evaluate_element (element_t *root, char mask) case Pop: case Set: case Show: + case Median: + case Order: + case Prod: + case Sum: break; case While: if (root->ops[0] == NULL) { @@ -1246,6 +756,14 @@ double evaluate_element (element_t *root, char mask) } op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer; break; + case Max: + case Mean: + case Min: + case Variance: + if (root->ops[0]) { + op0 = evaluate_element (root->ops[0], 0); + op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : answer; + } } switch (root->func) { @@ -1305,9 +823,10 @@ double evaluate_element (element_t *root, char mask) case Code: return execute_code (root->ops, root->nbops); case Print: return print (op0); case Prog: - prog ((int)op0, (int)op1, root->ops[2]); + prog ((int)op0, root->ops[1]); savestring ((int)op0, root->string); break; + case Arg: return arg ((int)op0); case Call: for (i = 1, nb =0; i < root->nbops; i++) { if (root->ops[i]) { @@ -1331,6 +850,33 @@ double evaluate_element (element_t *root, char mask) } return set (nb, root->ops); case Show: show (); break; + case Max: + if (root->ops[0]) { + return op0 > op1 ? op0 : op1; + } + return max (); + case Mean: + if (root->ops[0]) { + return (op0 + op1) / 2; + } + return mean (); + case Median: return median (); + case Min: + if (root->ops[0]) { + return op0 < op1 ? op0 : op1; + } + return min (); + case Order: order (); break; + case Prod: return prod (); + case Sum: return sum (); + case Variance: + if (root->ops[0]) { + double m = (op0 + op1) / 2; + op0 -= m; + op1 -= m; + return op0 * op0 + op1 * op1; + } + return variance (); } return 0; @@ -1391,5 +937,4 @@ void free_completion_list (char **list) } } - /* vim: set ts=4 sw=4 et: */