int context_show_tree() { n = 0; printf("global\n"); stack_foreach(&stack, count, 0); stack_foreach(&stack, show1, 0); return 0; }
int context_print() { stack_foreach(&stack, (stack_iterator_t) prt, 0); printf("\n"); return 0; }
/* * This method of looking up identifiers worked for C, but it * is not sufficient for C++, so it is no longer used. */ struct identifier_s *context_c_lookup(const char *key) { struct search_data_s data = { 0, key }; stack_foreach(&stack, (stack_iterator_t) context_search, &data); return data.result; }
/* reverse polish https://en.wikipedia.org/wiki/Shunting-yard_algorithm */ queue *syard_run(const char *in) { /* init */ stack *s, *arity; queue *q; int len; tokenizer_ctx *tkc; char *tok, *op, *newstr; tokenizer_type tok_last = TOKEN_LBRACKET; char comma = ',', mul = '*'; int *arn; s = stack_new(); arity = stack_new(); q = queue_new(); tkc = tokenizer_new(); newstr = strdup(in); newstr[strcspn(newstr, "\r\n")] = 0; /* strip newlines */ tokenizer_reset(tkc, newstr); /* while there are tokens to be read, read a token. */ while ((tok = tokenizer_next(tkc)) != NULL) { switch (tkc->type) { /* if the token is a number, then push it to the output queue. */ case TOKEN_NUMBER: /* special case: last token was a rbracket and we have number now */ if (tok_last == TOKEN_RBRACKET) { /* push a * sign with high precendence */ stack_push(s, (void *)&mul); } queue_enqueue(q, syard_create_double(tok)); break; /* if the token is an operator, then: */ case TOKEN_OPERATOR: /* special case: last token was left bracket or operator and we have a minus sign now */ if ((tok_last == TOKEN_LBRACKET || tok_last == TOKEN_OPERATOR) && (*tok == '-')) { /* change the operator to the special 'm' operator that we'll deal with in rpn_calc */ *tok = 'm'; } /* while there is an operator at the top of the operator stack with greater than or equal to precedence: */ while (((op = stack_top(s)) != NULL) && operator_is_preceding(*op, *tok)) { /* pop operators from the operator stack, onto the output queue; */ queue_enqueue(q, create_char_data(*(char *)stack_pop(s))); } /* push the read operator onto the operator stack. */ stack_push(s, (void *)tok); break; /* if the token is a left bracket (i.e. "("), then: */ case TOKEN_LBRACKET: /* special case: last token was a number or rbracket and we have lbracket now */ if (tok_last == TOKEN_NUMBER || tok_last == TOKEN_RBRACKET) { /* push a * sign with high precendence */ stack_push(s, (void *)&mul); } /* push it onto the operator stack */ stack_push(s, tok); break; /* if the token is a right bracket (i.e. ")"), then: */ case TOKEN_RBRACKET: /* while the operator at the top of the operator stack is not a left bracket: */ while (((op = stack_top(s)) != NULL) && *op != '(') { /* pop operators from the operator stack onto the output queue. */ queue_enqueue(q, create_char_data(*(char *)stack_pop(s))); } /* if the stack runs out without finding a left bracket, then there are mismatched parentheses. */ if (op == NULL || (op != NULL && *op != '(')) { /* mismatched parentheses */ printf("! mismatched parentheses; extra )\n"); goto err_cleanup; } /* pop the left bracket from the stack. */ stack_pop(s); /* check if stack top is a function and if so, pop it */ if (stack_top(s) != NULL && *((char *)stack_top(s)) == '\0') { /* this was a function */ char *ps; void *p; /* pop item from stack */ ps = (char *)stack_pop(s); /* remove leading null */ memmove(ps, ps+1, strlen(ps+1)+1); /* fetch function arity */ arn = stack_pop(arity); /* create function data */ p = create_function_data(*arn, ps); free(ps); free(arn); /* enqueue */ queue_enqueue(q, p); } break; case TOKEN_FUNCTION: /* special case: last token was a number or rbracket and we have variable now */ if (tok_last == TOKEN_NUMBER || tok_last == TOKEN_RBRACKET) { /* push a * sign with high precendence */ stack_push(s, (void *)&mul); } len = strlen(tok); op = calloc(len + 2, sizeof(char)); op[0] = '\0'; op[len] = '\0'; memcpy(op+1, tok, len); stack_push(s, op); arn = malloc(sizeof(int)); *arn = 1; stack_push(arity, arn); break; case TOKEN_COMMA: while (((op = stack_top(s)) != NULL) && *op != ',' && *op != '(') { /* pop operators from the operator stack onto the output queue. */ queue_enqueue(q, create_char_data(*(char *)stack_pop(s))); } if (*op == ',') stack_pop(s); stack_push(s, &comma); arn = stack_pop(arity); (*arn)++; stack_push(arity, arn); break; case TOKEN_VARIABLE: /* special case: last token was a number or rbracket and we have variable now */ if (tok_last == TOKEN_NUMBER || tok_last == TOKEN_RBRACKET) { /* push a * sign with high precendence */ stack_push(s, (void *)&mul); } queue_enqueue(q, create_var_data(tok)); break; default: break; } tok_last = tkc->type; } /* if there are no more tokens to read: */ if (tkc->type == TOKEN_END) { /* while there are still operator tokens on the stack: */ while (((op = stack_top(s)) != NULL) && *op != '(') { /* pop the operator onto the output queue. */ queue_enqueue(q, create_char_data(*(char *)stack_pop(s))); } /* if the operator token on the top of the stack is a bracket, then there are mismatched parentheses. */ if (op != NULL && *op == '(') { printf("! mismatched parentheses; extra (\n"); goto err_cleanup; } } else { printf("! unknown character `%c` in equation\n", *(tkc->pos)); goto err_cleanup; } stack_destroy(s); stack_destroy(arity); tokenizer_destroy(tkc); free(newstr); return q; err_cleanup: stack_foreach(s, syard_string_cleanup, NULL); stack_destroy(s); stack_foreach(arity, syard_queue_cleanup, NULL); stack_destroy(arity); tokenizer_destroy(tkc); queue_foreach(q, syard_queue_cleanup, NULL); queue_destroy(q); free(newstr); return NULL; }