X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=parser.c;h=24afb116c98f19a4a2d0e2724a4d52b6982984fb;hb=807bdeba16ea9ed816ecf7d3900f601c37ffa204;hp=7bdcda5a1ec7c06b06c4400dcfd6dd39ef631ab9;hpb=2ddb38f03fffaba277fdd99ad5ae2b85e2f01dec;p=calc.git diff --git a/parser.c b/parser.c index 7bdcda5..24afb11 100644 --- a/parser.c +++ b/parser.c @@ -18,6 +18,8 @@ double answer = 0; +double anglefactor = 1; + /* compare codes */ int codecmp (char *ref, char *str) @@ -62,7 +64,7 @@ keyword_t operators[NB_OPERATORS] = { { "|", Or, 2, 1, -2} }; -#define NB_FUNCTIONS 50 +#define NB_FUNCTIONS 55 keyword_t functions[NB_FUNCTIONS] = { { "sqrt", Sqr, 1, 4, 5}, { "pow", Pow, 2, 3, 5}, @@ -85,7 +87,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}, @@ -114,6 +116,11 @@ 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}, + { "base", Base, 2, 4, 9}, + { "deg", Deg, 0, 3, 9}, + { "grad", Grad, 0, 4, 9}, + { "rad", Rad, 0, 3, 9} }; #define NB_CONSTANTS 3 @@ -370,51 +377,48 @@ element_t *parser (char *str, char **next, int prio) /* look for number */ - if (((*str >= '0') && (*str <= '9')) || - (*str == '.') || (*str == '+') || (*str == '-')) { - VERBOSE (DEBUG, fprintf (stdout, "start processing value\n")); - char *pt; - double value = strtod (str, &pt); - VERBOSE (INFO, fprintf (stdout, "Value: %f\n", value)); - if (str != pt) { - if ((root == NULL) || (root->prio == 6)) { - new = newelement (Val, 1, 5); - new->value = value; - if (root == NULL) { - root = new; - } else { - for (i = 0; i < root->nbops; i++) { - if (root->ops[i] == NULL) { - root->ops[i] = new; - found = 1; - break; - } - } - if (!found) { - delelement (new); - delelement (root); - return ERROR_OP; + VERBOSE (DEBUG, fprintf (stdout, "start processing value\n")); + char *pt; + double value = (get_ibase () == 10) ? strtod (str, &pt) : strtoul (str, &pt, get_ibase ()); + VERBOSE (INFO, fprintf (stdout, "Value: %f\n", value)); + if (str != pt) { + if ((root == NULL) || (root->prio == 6)) { + new = newelement (Val, 1, 5); + new->value = value; + if (root == NULL) { + root = new; + } else { + for (i = 0; i < root->nbops; i++) { + if (root->ops[i] == NULL) { + root->ops[i] = new; + found = 1; + break; } } - str = pt; - } else if ((*str == '+') || (*str == '-')) { - if ((prio) && (prio > 1)) { - VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n")); - *next = str; - return root; - } - if (subparser (&root, &str, Add, 2, 1) == ERROR_OP) { + if (!found) { + delelement (new); delelement (root); return ERROR_OP; } - } else { + } + str = pt; + } else if ((*str == '+') || (*str == '-')) { + if ((prio) && (prio > 1)) { + VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n")); + *next = str; + return root; + } + if (subparser (&root, &str, Add, 2, 1) == ERROR_OP) { delelement (root); return ERROR_OP; } - found = 1; + } else { + delelement (root); + return ERROR_OP; } - VERBOSE (DEBUG, fprintf (stdout, "stop processing value\n")); + found = 1; } + VERBOSE (DEBUG, fprintf (stdout, "stop processing value\n")); /* error */ @@ -449,7 +453,7 @@ void print_element (element_t *root, int level) } for (i = 0; i < level; i++) { - fprintf (stdout, " "); + printf (" "); } switch (root->func) { @@ -481,7 +485,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; @@ -522,15 +526,20 @@ 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; + case Base: func = "Base"; break; + case Deg: func = "Degree"; break; + case Grad: func = "Gradian"; break; + case Rad: func = "Radian"; break; } - fprintf (stdout, "Function: %s\n", func); + printf ("Function: %s\n", func); if ((root->func == Val) && (root->ops[0] == NULL)) { for (i = 0; i < level; i++) { - fprintf (stdout, " "); + printf (" "); } - fprintf (stdout, "value: %f\n", root->value); + printf ("value: %f\n", root->value); } else { for (i = 0; i < root->nbops; i++) { print_element (root->ops[i], level + 1); @@ -583,7 +592,7 @@ double execute_code (element_t **prog, int nbcalls) void quit (void) { - fprintf (stdout, "bye\n"); + printf ("bye\n"); exit (0); } @@ -591,35 +600,67 @@ void quit (void) void help (void) { - fprintf (stdout, "calc is a simple calculator\n\n"); - fprintf (stdout, "arithmetic op.:"); - fprintf (stdout, " + - * / %% ^\n"); - fprintf (stdout, "comparison op.:"); - fprintf (stdout, " == != >= <= > <\n"); - fprintf (stdout, "logical op.:"); - fprintf (stdout, " & | !\n"); - fprintf (stdout, "mathematic func.:"); - fprintf (stdout, " exp ln log pow sqrt\n"); - fprintf (stdout, "trigonometric func.:"); - fprintf (stdout, " acos asin atan cos sin tan\n"); - fprintf (stdout, "error functions:"); - fprintf (stdout, " erf erfc\n"); - fprintf (stdout, "miscellaneous func.:"); - fprintf (stdout, " abs ceil floor\n"); - fprintf (stdout, "storage func.:"); - fprintf (stdout, " clear dec disp inc mem rcl sto\n"); - fprintf (stdout, "control flow prim.:"); - fprintf (stdout, " cond print while {} ;\n"); - fprintf (stdout, "program management:"); - 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:"); - fprintf (stdout, " ans e pi\n"); + printf ("calc is a simple calculator\n\n"); + printf ("arithmetic op.:"); + printf (" + - * / %% ^\n"); + printf ("comparison op.:"); + printf (" == != >= <= > <\n"); + printf ("logical op.:"); + printf (" & | !\n"); + printf ("mathematic func.:"); + printf (" exp ln log pow sqrt\n"); + printf ("trigonometric func.:"); + printf (" acos asin atan cos sin tan\n"); + printf ("error functions:"); + printf (" erf erfc\n"); + printf ("miscellaneous func.:"); + printf (" abs ceil floor\n"); + printf ("storage func.:"); + printf (" clear dec disp inc mem rcl sto\n"); + printf ("control flow prim.:"); + printf (" cond print while {} ;\n"); + printf ("program management:"); + printf (" arg call del edit ls prog\n"); + printf ("stack management:"); + printf (" get len pop push put set show\n"); + printf ("stack func.:"); + printf (" max mean med min ord prod sum var\n"); + printf ("control management:"); + printf (" base deg format grad help quit rad\n"); + printf ("constants:"); + printf (" ans e pi\n"); +} + +/* format function */ + +int format (int precision) +{ + if (precision > 0) { + set_precision (precision); + set_format (); + } else if (precision != -1) { + VERBOSE (WARNING, fprintf (stdout, "error incorrect precision (%d)\n", precision)); + return 0; + } + return get_precision (); +} + +/* base function */ + +void base (int in, int out) +{ + if ((in > 0) && (in < 37)) { + set_base (in, in); + if ((out > 0) && (out < 37)) { + set_base (in, out); + } else if (out != - 1) { + VERBOSE (WARNING, fprintf (stdout, "error incorrect output base (%d)\n", out)); + } + } else if (in != -1 ) { + VERBOSE (WARNING, fprintf (stdout, "error incorrect input base (%d)\n", in)); + } else { + printf ("base (I/O): %s\n", show_base ()); + } } /* evaluate element tree */ @@ -669,7 +710,6 @@ double evaluate_element (element_t *root, char mask) case Div: case Mod: case Pow: - case Store: case Equal: case Diff: case Ge: @@ -680,7 +720,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; } @@ -704,7 +744,6 @@ double evaluate_element (element_t *root, char mask) case Inc: case Dec: case Not: - case Mem: case Cond: case Prog: case Arg: @@ -736,6 +775,9 @@ double evaluate_element (element_t *root, char mask) case Order: case Prod: case Sum: + case Deg: + case Grad: + case Rad: break; case While: if (root->ops[0] == NULL) { @@ -743,10 +785,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); @@ -764,6 +818,14 @@ 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; + case Base: + op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : -1; + op1 = (root->ops[1]) ? evaluate_element (root->ops[1], 0) : -1; + break; } switch (root->func) { @@ -776,12 +838,12 @@ double evaluate_element (element_t *root, char mask) case Mod: return fmod (op0, op1); case Pow: return pow (op0, op1); case Sqr: return sqrt (op0); - case Cos: return cos (op0); - case Sin: return sin (op0); - case Tan: return tan (op0); - case Acos: return acos (op0); - case Asin: return asin (op0); - case Atan: return atan (op0); + case Cos: return cos (op0 / anglefactor); + case Sin: return sin (op0 / anglefactor); + case Tan: return tan (op0 / anglefactor); + case Acos: return acos (op0) * anglefactor; + case Asin: return asin (op0) * anglefactor; + case Atan: return atan (op0) * anglefactor; case Ln: return log (op0); case Log: return log10 (op0); case Exp: return exp (op0); @@ -790,12 +852,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; @@ -877,6 +939,20 @@ double evaluate_element (element_t *root, char mask) return op0 * op0 + op1 * op1; } return variance (); + case Precision: + return format ((int)op0); + case Base: + base ((int)op0, (int)op1); + break; + case Deg: + anglefactor = 180 / M_PI; + break; + case Grad: + anglefactor = 200 / M_PI; + break; + case Rad: + anglefactor = 1; + break; } return 0;