#include "ee.h" int error = 0; int main (int argc, const char* argv[]){ STACK expr = NULL; const char** endPtr = argv+argc, ** arg = argv+1 ; while ((arg < endPtr) && (!error)){ if (arrity(**arg)) expr = push(evaluate(&expr, **arg), expr); else if(isNum(*arg)) expr = push(strtod(*arg,NULL), expr); else error |= ERR_INVALID_INPUT; arg++; } if (expr == NULL) error |= ERR_NS_OPERANDS; else if (expr->tail!=NULL) error |= ERR_NS_OPERATORS; report(expr); return error; } int // Dependency of main() isNum(const char* query){ /* * If query is a string, isNum(query) iff query represents a number. */ char* alphas; strtod(query, &alphas); return !strcmp(alphas,""); } int // Dependency of main() arrity(const char query){ /* * If query is a string, isOperator iff query is a * supported operator. */ return (query == '+')? 2: (query == 'x')? 2: (query == '-')? 2: (query == '/')? 2: (query == '^')? 2: (query == '!')? 1: 0; } double // Dependency of main() evaluate(STACK* target_stack, int operator){ /* * if target_stack is a pointer to a STACK and operator is * an integer corresponding to the ascii value of a supported * operator, evaluate(target_stack,operator) is the result of * applying the given operator to the appropriate number of * operands from target_stack. */ double value = 0, a = 0, b = 0; double *_operands = operands(target_stack, arrity(operator)); switch (operator){ case '+' : value = _operands[1] + _operands[0]; break; case '-' : value = _operands[1] - _operands[0]; break; case 'x' : value = _operands[1] * _operands[0]; break; case '/' : value = _operands[1] / _operands[0]; break; case '^' : value = pow(_operands[1],_operands[0]); break; case '!' : if ( (*_operands != floor(*_operands)) || (*_operands < 0)) error |= ERR_INVALID_FACTORIAL; else value = fact(*_operands); break; default : break; } return value; } double* // Dependency of evaluate() operands(STACK* target_stack, int size){ /* * if target_stack is a pointer to a STACK, and size is an integer * corresponding to the number of operands desired, * getOperands(target_stack,size) returns an array of operands and * pops them off *target_stack. */ double * const _operands = (double*)malloc(size*sizeof(double)); if ((*target_stack) == NULL) error |= ERR_NS_OPERANDS; double * tPtr = _operands; double * endPtr = _operands + size; while ((tPtr < endPtr) && !error) { *tPtr = peek((*target_stack)); (*target_stack) = pop(*target_stack); tPtr += 1; } return _operands; } double // Dependency of evaluate() fact(int n){ /* * if n is an integer, fact(n) is 'n factorial'. */ return (n==0)? 1 : n*fact(n-1); } void // Dependency of main() report(STACK expr){ /* * reportErrors() returns an integer corresponding to * the number of discrete error types noted in global * variables ERR_NS_OPERANDS, ERR_NS_OPERATORS, and * ERR_INVALID_INPUT. */ if (error & ERR_INVALID_INPUT) printf("Error: Unexpected input.\n"); else if (error & ERR_NS_OPERATORS) printf("Error: insufficient operators.\n"); else if (error & ERR_NS_OPERANDS) printf("Error: insufficient operands.\n"); else if (error & ERR_INVALID_FACTORIAL) printf("Error: Factorials are only supported for positive integers.\n"); else printf("%g\n", peek(expr)); } STACK push(double datum, STACK tail){ /* Given a double value (datum), and a STACK (tail), * push(datum,tail) is the STACK resulting from * prepending datum to the STACK tail. */ NODE* new_node = (NODE*)malloc(sizeof(NODE)); (*new_node).datum = datum; (*new_node).tail = tail; return new_node; } STACK pop(STACK target_stack){ /* Given a STACK (target_stack), pop(target_stack) * is the STACK resulting from the removal of the first * item in target_stack; */ STACK tail = NULL; if (target_stack != NULL){ tail = (*target_stack).tail; free(target_stack); } return tail; } double peek(STACK target_stack){ /* Given a STACK (target_stack), peek(STACK) * is the first element's datum. */ return (target_stack)? (*target_stack).datum : 0; }