void expression_evaluate(int n, double *value, EXPRESSION expression, double **substitute, double **work) { int i, e = 0, w = 0; while(expression[e].type != END) { if(expression[e].type == VALUE) { for(i = 0; i < n; i ++) work[w][i] = expression[e].value; w ++; } else if(expression[e].type >= SUBSTITUTE_ZERO) { for(i = 0; i < n; i ++) work[w][i] = substitute[expression[e].type - SUBSTITUTE_ZERO][i]; w ++; } else if(IS_OPERATOR(expression[e].type)) { switch(expression[e].type) { case POWER : for(i = 0; i < n; i ++) work[w-2][i] = pow( work[w-2][i] , work[w-1][i] ); break; case MULTIPLY: for(i = 0; i < n; i ++) work[w-2][i] = work[w-2][i] * work[w-1][i] ; break; case DIVIDE : for(i = 0; i < n; i ++) work[w-2][i] = work[w-2][i] / work[w-1][i] ; break; case PLUS : for(i = 0; i < n; i ++) work[w-2][i] = work[w-2][i] + work[w-1][i] ; break; case MINUS : for(i = 0; i < n; i ++) work[w-2][i] = work[w-2][i] - work[w-1][i] ; break; case LARGER : for(i = 0; i < n; i ++) work[w-2][i] = work[w-2][i] > work[w-1][i] ; break; case SMALLER : for(i = 0; i < n; i ++) work[w-2][i] = work[w-2][i] < work[w-1][i] ; break; } w --; } e ++; } for(i = 0; i < n; i ++) value[i] = work[0][i]; }
int expression_number_of_recursions(EXPRESSION expression) { int e = 0, w = 0, n = 0; while(expression[e].type != END) { if(expression[e].type == VALUE || expression[e].type >= SUBSTITUTE_ZERO) w ++; else if(IS_OPERATOR(expression[e].type)) w --; n = n > w ? n : w; e ++; } return n; }
void expression_simplify(EXPRESSION expression) { if(expression[0].type == END || expression[1].type == END) return; int i = 0, j, n; int type; double value; // fudge to make a non-allocated 2x1 matrix act like an allocated one double work[2], *p_work[2]; p_work[0] = &work[0]; p_work[1] = &work[1]; // loop until a pass is completed with no simplifications do { // start at the begining haveing done no simplifications i = n = 0; while(1) { // find the next value-value-operator pattern while(!(expression[i].type == VALUE && expression[i+1].type == VALUE && IS_OPERATOR(expression[i+2].type)) && expression[i+2].type != END) i ++; // reached the end if(expression[i+2].type == END) break; // evaluate the sub-expression type = expression[i+3].type; expression[i+3].type = END; expression_evaluate(1, &value, &expression[i], NULL, p_work); expression[i+3].type = type; // replace the sub-expression with the value expression[i].value = value; j = i + 3; while(expression[j-1].type != END) { expression[j-2] = expression[j]; j ++; } // increment the number of simplifications n ++; } } while(n); }
void expression_print(EXPRESSION expression) { int e = 0; while(expression[e].type != END) { if(IS_OPERATOR(expression[e].type) || IS_CONTROL(expression[e].type)) { printf("%c",expression[e].type); } else if(expression[e].type == VALUE) { printf("{%g}",expression[e].value); } else if(expression[e].type >= SUBSTITUTE_ZERO) { printf("{$%i}",expression[e].type - SUBSTITUTE_ZERO); } e ++; } }
int main(void) { gcinit(); stackinit(); while(1) { char buffer[80]; ssize_t bytes_read = raw_input("calc> ", buffer, sizeof(buffer)); if(bytes_read == EOF) { return 0; } else { Buffer p; buffer_init(&p, buffer, bytes_read); size_t i = 0; while(p.pos != p.end) { if(IS_DIGIT(*p.pos)) { int num = *p.pos - '0'; stackpush(newLong(num)); printf("PUSH %d\n", num); } else if(IS_OPERATOR(*p.pos)) { if(pstack.stacksize < 2) { fprintf(stderr, "operator '%c' takes 2 args\n", *p.pos); goto finally; } else { Object* op2 = stackpop(); Object* op1 = stackpop(); if(*p.pos == '+') { printf("POP %ld\n", O_LVAL(op2)); printf("POP %ld\n", O_LVAL(op1)); long result; result = O_LVAL(op1) + O_LVAL(op2); Object *retval = newLong(result); printf("ADD\n"); stackpush(retval); printf("PUSH %ld\n", result); } else if(*p.pos == '-') { long result; result = O_LVAL(op1) - O_LVAL(op2); Object *retval = newLong(result); stackpush(retval); } } } else if (IS_WHITE(*p.pos)) { goto out; } else { fprintf(stderr, "Invalid token %c\n", *p.pos); goto finally; } out: p.pos++; i++; } if(pstack.stacksize == 1) { Object *top = stackpop(); objectEcho(top); } else { printf("To many values: %zu", pstack.stacksize); } finally: gcterm(); gcinit(); stackinit(); printf("\n"); } } return 0; }
EXPRESSION expression_generate(char *original) { int i, length, offset; char *string = (char *)malloc(MAX_STRING * sizeof(char)); strcpy(string,original); // remove whitespace offset = 0; length = strlen(string); for(i = 0; i < length; i ++) { if(string[i + offset] == ' ') { offset ++; length --; } string[i] = string[i + offset]; } string[i] = '\0'; // convert multiple expressions into just one length = strlen(string); int n_name, n_expr; char *name = (char *)malloc(MAX_STRING * sizeof(char)); char *expr = (char *)malloc(MAX_STRING * sizeof(char)); char *temp = (char *)malloc(MAX_STRING * sizeof(char)); if(name == NULL || expr == NULL || temp == NULL) return NULL; while(IS_VARIABLE(string[0])) { i = 0; do name[i] = string[i]; while(string[++i] != EQUALITY); n_name = i; name[n_name] = '\0'; i ++; do expr[i - n_name - 1] = string[i]; while(string[++i] != SEPERATOR); n_expr = i - n_name - 1; expr[n_expr] = '\0'; i ++; while(string[i] == ';') i ++; sprintf(temp,"%s",&string[i]); strcpy(string,temp); i = 0; do { if(strncmp(&string[i],name,n_name) == 0 && (!IS_VARIABLE(string[i+n_name]) || string[i+n_name] == '\0')) { string[i] = '\0'; sprintf(temp,"%s%c%s%c%s",string,LEFTBRACE,expr,RIGHTBRACE,&string[i + n_name]); strcpy(string,temp); } i ++; } while(i < strlen(string)); } free(name); free(expr); free(temp); // convert the infix string into lists of postfix/RPN operations length = strlen(string); int o = 0; int *operator = (int *)malloc(MAX_ELEMENTS * sizeof(int)); if(operator == NULL) return NULL; int e = 0; EXPRESSION expression = (EXPRESSION)malloc(MAX_ELEMENTS * sizeof(struct s_EXPRESSION)); if(expression == NULL) return NULL; int index; i = 0; do { if(string[i] == LEFTBRACE) { operator[o++] = LEFTBRACE; i ++; } else if(string[i] == RIGHTBRACE) { while(operator[o-1] != LEFTBRACE) { expression[e++].type = operator[--o]; if(!o) return NULL; } i ++; o --; } else if(IS_OPERATOR(string[i])) { while(o > 0) if(precedence[(int)string[i]] <= precedence[operator[o-1]]) expression[e++].type = operator[--o]; else break; operator[o++] = string[i++]; } else if(IS_VALUE(string[i])) { sscanf(&string[i],"%lf",&expression[e].value); expression[e++].type = VALUE; while((i < length) && ((!IS_OPERATOR(string[i]) && !IS_CONTROL(string[i])) || ((string[i] == MINUS || string[i] == PLUS) && (string[i-(i>0)] == 'e' || string[i-(i>0)] == 'E')))) i ++; } else if(string[i] == SUBSTITUTE) { sscanf(&string[++i],"%i",&index); expression[e++].type = SUBSTITUTE_ZERO + index; while(IS_VALUE(string[i])) i ++; } else return NULL; } while(i < length); while(o) expression[e++].type = operator[--o]; expression[e].type = END; // simplify the expression as much as possible expression_simplify(expression); // clean up and return free(string); free(operator); e = 0; while(expression[e].type != END) e ++; return (EXPRESSION)realloc(expression, (e + 1) * sizeof(struct s_EXPRESSION)); }
static uri_template_expr *build_expr(char *tpl, int len) { uri_template_expr *expr; uri_template_var *var = uri_template_var_create(); char *name = tpl, *start = tpl, *prefix; if (IS_OPERATOR(*tpl)) { expr = uri_template_expr_create(*tpl++); name = tpl; } else { expr = uri_template_expr_create(0); } while (tpl - start <= len) { switch(*tpl) { case '%': if (name + len - tpl > 2) { if (isxdigit(*(tpl + 1))) { if (isxdigit(*(++tpl + 1))) { tpl++; } else { expr->error = URI_TEMPLATE_ERROR; } } else { expr->error = URI_TEMPLATE_ERROR; } } else { expr->error = URI_TEMPLATE_ERROR; } break; case ':': prefix = ++tpl; if (*tpl >= '1' && *tpl++ <= '9') { while (isdigit(*tpl)) { tpl++; } if (*tpl == ',' || *tpl == '}') { if (tpl - prefix < 5) { var->length = extract_num(tpl - (tpl - prefix), tpl - prefix); } else { expr->error = URI_TEMPLATE_ERROR; } tpl--; } else { expr->error = URI_TEMPLATE_ERROR; } } else { expr->error = URI_TEMPLATE_ERROR; } break; case '*': if (*(tpl + 1) == '}' || *(tpl + 1) == ',') { var->explode = 1; } else { expr->error = URI_TEMPLATE_ERROR; } break; case ',': case '}': var->name = estrndup(name, tpl - name - SHIFT_BACK(var)); uri_template_expr_add_var(expr, var); if (*tpl == ',') { var = uri_template_var_create(); name = tpl + 1; } break; default: expr->error |= !(isalnum(*tpl) || *tpl == '_' || *tpl == '.'); break; } tpl++; } return expr; }