X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=parser.c;h=1e9b9861731ac2ccbc81f844afbd9c80f91859d6;hb=a3f2e6cf008678cfa2b1a868e38fefbe81009971;hp=c94a1e38841ce79e5056394646743ede94c4400a;hpb=72b7d4bcd0a74ff67e5249b9960c5b1d1ca80509;p=calc.git diff --git a/parser.c b/parser.c index c94a1e3..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,18 +18,6 @@ double answer = 0; -#define DEFAULT_STORAGE_SIZE 10 -int storage_size = -1; - -double *storage = 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) @@ -46,72 +40,10 @@ 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 + #define NB_OPERATORS 14 keyword_t operators[NB_OPERATORS] = { { "+\t", Add, 2, 1, 1}, @@ -130,7 +62,7 @@ keyword_t operators[NB_OPERATORS] = { { "|", Or, 2, 1, -2} }; -#define NB_FUNCTIONS 34 +#define NB_FUNCTIONS 50 keyword_t functions[NB_FUNCTIONS] = { { "sqrt", Sqr, 1, 4, 5}, { "pow", Pow, 2, 3, 5}, @@ -153,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}, @@ -161,11 +93,27 @@ 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}, - { "call", Call, 10, 4, 5}, + { "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}, - { "del", Del, 1, 3, 9} + { "del", Del, 1, 3, 9}, + { "get", Get, 1, 3, 5}, + { "len", Length, 0, 3, 5}, + { "pop", Pop, 0, 3, 5}, + { "push", Push, 1, 4, 5}, + { "put", Put, 2, 3, 5}, + { "set", Set, MAX_ARGS, 3, 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 @@ -254,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 != '}') { @@ -344,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; @@ -357,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; } @@ -516,7 +468,7 @@ void print_element (element_t *root, int level) case Acos: func = "Arc Cosine"; break; case Asin: func = "Arc Sine"; break; case Atan: func = "Arc Tangent"; break; - case Ln: func = "Logarithm (e base)"; break; + case Ln: func = "Logarithm (natural)"; break; case Log: func = "Logarithm (10 base)"; break; case Exp: func = "Exponantial"; break; case Erfc: func = "Complementary Error Function"; break; @@ -550,10 +502,26 @@ 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; case Del: func = "Del"; break; + case Get: func = "Get"; break; + case Length: func = "Length"; break; + case Pop: func = "Pop"; break; + case Push: func = "Push"; break; + 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); @@ -570,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) @@ -705,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) @@ -744,218 +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)->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)->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; - - /* change context */ - answer = 0; - storage = (programs + n)->storage; - storage_size = (programs + n)->storage_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); - - /* restore context */ - answer = tmp.answer; - storage = tmp.storage; - storage_size = tmp.storage_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)->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--; -} - /* help message */ void help (void) @@ -980,7 +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:"); @@ -1043,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) { @@ -1072,9 +706,12 @@ double evaluate_element (element_t *root, char mask) case Not: case Mem: case Cond: + case Prog: + case Arg: case Call: case Edit: case Del: + case Get: if (root->ops[0]) { op0 = evaluate_element (root->ops[0], 0); } else { @@ -1091,6 +728,14 @@ double evaluate_element (element_t *root, char mask) case E: case Code: case List: + case Length: + case Pop: + case Set: + case Show: + case Median: + case Order: + case Prod: + case Sum: break; case While: if (root->ops[0] == NULL) { @@ -1098,9 +743,27 @@ double evaluate_element (element_t *root, char mask) return 0; } break; + case Push: case Print: op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : answer; break; + case Put: + if (root->ops[0]) { + op0 = evaluate_element (root->ops[0], 0); + } else { + VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n")); + return 0; + } + 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) { @@ -1160,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]) { @@ -1173,6 +837,46 @@ double evaluate_element (element_t *root, char mask) case List: list (); break; case Edit: edit ((int)op0); break; case Del: del ((int)op0); break; + case Get: return get ((int)op0); + case Length: return length (); + case Pop: return pop (); + case Push: return push (op0); + case Put: return put ((int)op0, op1); + case Set: + for (i = 0, nb =0; i < root->nbops; i++) { + if (root->ops[i]) { + nb++; + } + } + 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; @@ -1233,5 +937,4 @@ void free_completion_list (char **list) } } - /* vim: set ts=4 sw=4 et: */