X-Git-Url: https://secure.softndesign.org/git/?a=blobdiff_plain;f=parser.c;h=1d35b4c44785dc85eee79b7600b2c62eebb40910;hb=89cf095594de27bde3e3be007d255cad56ab0eca;hp=fdabef2bf15e6c3848c87824b6a55b44fbc18169;hpb=d2ff8478555f878bdeb7f77b00fb5c77dfe8d05b;p=calc.git diff --git a/parser.c b/parser.c index fdabef2..1d35b4c 100644 --- a/parser.c +++ b/parser.c @@ -58,7 +58,7 @@ keyword_t operators[NB_OPERATORS] = { { "^", Pow, 2, 1, 4} }; -#define NB_FUNCTIONS 7 +#define NB_FUNCTIONS 9 keyword_t functions[NB_FUNCTIONS] = { { "sqrt", Sqr, 1, 4, 5}, { "pow", Pow, 2, 3, 5}, @@ -66,7 +66,9 @@ keyword_t functions[NB_FUNCTIONS] = { { "sin", Sin, 1, 3, 5}, { "atan", Atn, 1, 4, 5}, { "exp", Exp, 1, 3, 5}, - { "log", Log, 1, 3, 5} + { "log", Log, 1, 3, 5}, + { "quit", Qui, 0, 4, 5}, + { "help", Hel, 0, 4, 5} }; /* subparser function */ @@ -82,7 +84,7 @@ element_t *subparser (element_t **proot, char **pstr, func_t func, int nbops, in if (new->ops[1] == ERROR_OP) { return ERROR_OP; } - *proot = newelement (Val, 1, 4); + *proot = newelement (Val, 1, 5); if (*proot == ERROR_OP) { return ERROR_OP; } @@ -136,7 +138,7 @@ element_t *parser (char *str, char **next, int prio) } } while (*str == ','); } else { - root = newelement (Val, 1, 4); + root = newelement (Val, 1, 5); if (root == NULL) { return ERROR_OP; } @@ -177,6 +179,12 @@ element_t *parser (char *str, char **next, int prio) if (subparser (&root, &str, operator->func, operator->nbops, operator->prio) == ERROR_OP) { return ERROR_OP; } + } else if (*str == '-') { + new = newelement (Sig, 1, 9); + if (new == NULL) { + return ERROR_OP; + } + root = new; } else { return ERROR_OP; } @@ -225,7 +233,7 @@ element_t *parser (char *str, char **next, int prio) VERBOSE (INFO, PRINTOUT ("Value: %f\n", value)); if (str != pt) { if (root == NULL) { - new = newelement (Val, 1, 4); + new = newelement (Val, 1, 5); if (new == NULL) { return ERROR_OP; } @@ -284,6 +292,7 @@ void print_element (element_t *root, int level) switch (root->func) { case Val: func = "Value"; break; + case Sig: func = "Sign"; break; case Add: func = "Addition"; break; case Sub: func = "Subtraction"; break; case Mul: func = "Multiplication"; break; @@ -296,6 +305,8 @@ void print_element (element_t *root, int level) case Atn: func = "Arc Tangent"; break; case Log: func = "Logarithm"; break; case Exp: func = "Exponantial"; break; + case Qui: func = "Quit"; break; + case Hel: func = "Help"; break; } PRINTOUT ("Function: %s\n", func); @@ -312,24 +323,66 @@ void print_element (element_t *root, int level) } } +/* quit function */ + +void quit (void) +{ + PRINTOUT ("bye\n"); + exit (0); +} + +/* help message */ + +void help (void) +{ + PRINTOUT ("calc is a simple calculator\n\n"); + PRINTOUT ("supported operators:\n"); + PRINTOUT (" + - * / % ^\n\n"); + PRINTOUT ("supported functions:\n"); + PRINTOUT (" pow sqrt cos sin atan log exp\n\n"); + PRINTOUT ("miscellaneous functions:\n"); + PRINTOUT (" quit help\n"); +} + /* evaluate element tree */ -double evaluate_element (element_t *root) +#define MASK_SUB 0x1 +#define MASK_DIV 0x2 + +double evaluate_element (element_t *root, char mask) { double op0 = 0, op1 = 0; + char nextmask = mask; if ((root == NULL) || (root == ERROR_OP)) { VERBOSE (WARNING, PRINTOUT ("error while evaluating\n")); return 0; } + /* mask to manage sub operator sub and div */ + switch (root->func) { + case Add: + nextmask &= ~MASK_SUB; + nextmask &= ~MASK_DIV; + break; + case Sub: + nextmask |= MASK_SUB; + nextmask &= ~MASK_DIV; + break; + case Mul: + nextmask &= ~MASK_DIV; + break; + case Div: + nextmask |= MASK_DIV; + break; + default: + nextmask = mask; + } + switch (root->func) { case Val: - if (root->ops[0]) { - return evaluate_element (root->ops[0]); - } else { - return root->value; - } + case Sig: + op0 = (root->ops[0]) ? evaluate_element (root->ops[0], nextmask) : root->value; break; case Add: case Sub: @@ -338,7 +391,7 @@ double evaluate_element (element_t *root) case Mod: case Pow: if (root->ops[1]) { - op1 = evaluate_element (root->ops[1]); + op1 = evaluate_element (root->ops[1], nextmask); } else { VERBOSE (WARNING, PRINTOUT ("error while evaluating (op[1])\n")); return 0; @@ -351,18 +404,24 @@ double evaluate_element (element_t *root) case Log: case Exp: if (root->ops[0]) { - op0 = evaluate_element (root->ops[0]); + op0 = evaluate_element (root->ops[0], 0); } else { VERBOSE (WARNING, PRINTOUT ("error while evaluating (op[0])\n")); return 0; } + break; + case Qui: + case Hel: + break; } switch (root->func) { - case Add: return op0 + op1; - case Sub: return op0 - op1; - case Mul: return op0 * op1; - case Div: return op0 / op1; + case Val: return op0; + case Sig: return -op0; + case Add: return ((mask & MASK_SUB) == 0) ? op0 + op1 : op0 - op1; + case Sub: return ((mask & MASK_SUB) == 0) ? op0 - op1 : op0 + op1; + case Mul: return ((mask & MASK_DIV) == 0) ? op0 * op1 : op0 / op1; + case Div: return ((mask & MASK_DIV) == 0) ? op0 / op1 : op0 * op1; case Mod: return fmod (op0, op1); case Pow: return pow (op0, op1); case Sqr: return sqrt (op0); @@ -371,7 +430,8 @@ double evaluate_element (element_t *root) case Atn: return atan (op0); case Log: return log (op0); case Exp: return exp (op0); - default: break; + case Qui: quit (); break; + case Hel: help (); break; } return 0;