/* evalf1.c (yukino.c) - Don Yang (uguu.org) Preprocess step 1: remove comments / debug output. 11/05/99 */ #include #include #include #define isdigit0(x) (((x) >= '0' && (x) <= '9') || (x) == '.') #define MAX_EXPRESSION_LENGTH 2048 #define MAX_TREE_SIZE 2048 #define TOKEN_OPERATOR 0 #define TOKEN_LITERAL 1 #define OPERATOR_LITERAL 0x136 #define OPERATOR_PI 0x126 #define OPERATOR_E 0x116 #define OPERATOR_OPEN_PAREN 0x106 #define OPERATOR_POW 0x0f5 #define OPERATOR_SIN 0x0e4 #define OPERATOR_COS 0x0d4 #define OPERATOR_TAN 0x0c4 #define OPERATOR_ASIN 0x0b4 #define OPERATOR_ACOS 0x0a4 #define OPERATOR_ATAN 0x094 #define OPERATOR_LOG 0x084 #define OPERATOR_LN 0x074 #define OPERATOR_EXP 0x064 #define OPERATOR_NEG 0x053 #define OPERATOR_MUL 0x042 #define OPERATOR_DIV 0x032 #define OPERATOR_MOD 0x022 #define OPERATOR_ADD 0x011 #define OPERATOR_SUB 0x001 #define LABEL_SIN (OPERATOR_SIN >> 4) #define LABEL_COS (OPERATOR_COS >> 4) #define LABEL_TAN (OPERATOR_TAN >> 4) #define LABEL_LOG (OPERATOR_LOG >> 4) #define LABEL_EXP (OPERATOR_EXP >> 4) char *label[19] = { "-", "+", "%", "/", "*", "-", "exp", "ln", "log", "atan", "acos", "asin", "tan", "cos", "sin", "^", "(", "e", "PI"}; char expression[MAX_EXPRESSION_LENGTH + 1]; int expindex, lasttoken, lastop, nestlevel; double operand[MAX_TREE_SIZE], lit; int operator[MAX_TREE_SIZE]; int left[MAX_TREE_SIZE], right[MAX_TREE_SIZE], parent[MAX_TREE_SIZE]; int newnode, cursor; int i; double evaluate(int node) { switch( operator[node] ) { case OPERATOR_PI: return atan2(0, -1); case OPERATOR_E: return exp(1); case OPERATOR_OPEN_PAREN: return evaluate(right[node]); case OPERATOR_POW: return pow(evaluate(left[node]), evaluate(right[node])); case OPERATOR_SIN: return sin(evaluate(right[node])); case OPERATOR_COS: return cos(evaluate(right[node])); case OPERATOR_TAN: return tan(evaluate(right[node])); case OPERATOR_ASIN: return asin(evaluate(right[node])); case OPERATOR_ACOS: return acos(evaluate(right[node])); case OPERATOR_ATAN: return atan(evaluate(right[node])); case OPERATOR_LOG: return log10(evaluate(right[node])); case OPERATOR_LN: return log(evaluate(right[node])); case OPERATOR_EXP: return exp(evaluate(right[node])); case OPERATOR_NEG: return -evaluate(right[node]); case OPERATOR_MUL: return evaluate(left[node]) * evaluate(right[node]); case OPERATOR_DIV: return evaluate(left[node]) / evaluate(right[node]); case OPERATOR_MOD: return fmod(evaluate(left[node]), evaluate(right[node])); case OPERATOR_ADD: return evaluate(left[node]) + evaluate(right[node]); case OPERATOR_SUB: return evaluate(left[node]) - evaluate(right[node]); default: return operand[node]; } } void insertbop(int op) { printf("%s ", label[op >> 4]); for(; operator[parent[cursor]] != OPERATOR_OPEN_PAREN && (operator[parent[cursor]] & 7) >= (op & 7); cursor = parent[cursor]); operator[newnode] = op; left[newnode] = cursor; parent[newnode] = parent[cursor]; parent[cursor] = newnode; right[parent[newnode]] = newnode; cursor = newnode; newnode++; lasttoken = TOKEN_OPERATOR; lastop = 0; } void insertuop(int op) { if( lasttoken == TOKEN_LITERAL ) insertbop(OPERATOR_MUL); if( op == OPERATOR_LITERAL ) { printf("%lG ", lit); lasttoken = TOKEN_LITERAL; } else if( op == OPERATOR_PI || op == OPERATOR_E ) { printf("%s ", label[op >> 4]); lasttoken = TOKEN_LITERAL; } else { if( op == OPERATOR_OPEN_PAREN ) { nestlevel++; if( lastop ) putchar('\b'); } printf("%s", label[op >> 4]); lasttoken = TOKEN_OPERATOR; } lastop = 0; if( op >= OPERATOR_EXP && op <= OPERATOR_SIN ) { putchar(' '); lastop = 1; } operator[newnode] = op; operand[newnode] = lit; parent[newnode] = cursor; right[cursor] = newnode; cursor = newnode; newnode++; } int main(int argc, char *argv[]) { if( argc == 1 ) { puts("?"); return 0; } expindex = 0; strcpy(expression, argv[1]); for(i = 2; i < argc; i++) strcat(expression, argv[i]); strlwr(expression); operator[cursor = 0] = OPERATOR_OPEN_PAREN; newnode = 1; for(expindex = lasttoken = nestlevel = 0; expression[expindex];) { if( isdigit0(expression[expindex]) ) { sscanf(expression + expindex, "%lf", &lit); insertuop(OPERATOR_LITERAL); for(; isdigit0(expression[expindex]); expindex++); if( expression[expindex] == 'e' ) { if( expression[expindex + 1] == '+' || expression[expindex + 1] == '-' ) expindex++; for(expindex++; expression[expindex] >= '0' && expression[expindex] <= '9'; expindex++); } } else if( expression[expindex] > 'a' && expression[expindex] <= 't' ) { if( !memcmp(expression + expindex, label[LABEL_SIN], 3) ) insertuop(OPERATOR_SIN); else if( !memcmp(expression + expindex, label[LABEL_COS], 3) ) insertuop(OPERATOR_COS); else if( !memcmp(expression + expindex, label[LABEL_TAN], 3) ) insertuop(OPERATOR_TAN); else if( !memcmp(expression + expindex, label[LABEL_EXP], 3) ) insertuop(OPERATOR_EXP); else if( !memcmp(expression + expindex, label[LABEL_LOG], 3) ) insertuop(OPERATOR_LOG); else { if( !memcmp(expression + expindex, "pi", 2) ) insertuop(OPERATOR_PI); else if( !memcmp(expression + expindex, "ln", 2) ) insertuop(OPERATOR_LN); else { if( expression[expindex] == 'e' ) insertuop(OPERATOR_E); expindex--; } expindex--; } expindex += 3; } else if( expression[expindex] == 'a' ) { if( !memcmp(expression + expindex + 1, label[LABEL_SIN], 3) ) insertuop(OPERATOR_ASIN); else if( !memcmp(expression + expindex + 1, label[LABEL_COS], 3) ) insertuop(OPERATOR_ACOS); else if( !memcmp(expression + expindex + 1, label[LABEL_TAN], 3) ) insertuop(OPERATOR_ATAN); else expindex -= 3; expindex += 4; } else { i = expression[expindex++]; if( lasttoken == TOKEN_LITERAL ) { if( i == '(' ) { insertuop(OPERATOR_OPEN_PAREN); } else if( i == ')' && nestlevel ) { printf("\b) "); for(cursor = parent[cursor]; operator[cursor] != OPERATOR_OPEN_PAREN; cursor = parent[cursor]); nestlevel--; } else { if( i == '*' ) insertbop(OPERATOR_MUL); else if( i == '/' ) insertbop(OPERATOR_DIV); else if( i == '%' ) insertbop(OPERATOR_MOD); else if( i == '+' ) insertbop(OPERATOR_ADD); else if( i == '-' ) insertbop(OPERATOR_SUB); else if( i == '^' ) insertbop(OPERATOR_POW); } } else { if( i == '(' ) insertuop(OPERATOR_OPEN_PAREN); else if( i == '-' ) insertuop(OPERATOR_NEG); } } } if( lasttoken == TOKEN_OPERATOR ) { lit = 0; insertuop(OPERATOR_LITERAL); } for(i = !putchar('\b'); i < nestlevel; i++) putchar(')'); putchar('\n'); printf("\n= %.16lG\n", evaluate(0)); return 0; }