/** * @return the position of the first occurrence of item in the Stack or -1 * if item cannot be found. The search begins at the top of the Stack * (position 0) and proceeds downward (position 1, 2, etc.). * * Since ultimately the stack stores pointers, == is used to test for * equality. */ LIBSBML_EXTERN int Stack_find (Stack_t *s, void *item) { int pos = Stack_size(s); while ((pos-- > 0) && (s->stack[pos] != item)) ; if (pos >= 0) { pos = s->sp - pos; } return pos; }
/** * Pushes item onto the top of the Stack. */ LIBSBML_EXTERN void Stack_push (Stack_t *s, void *item) { if (s == NULL) return; if (Stack_size(s) == s->capacity) { s->capacity *= 2; s->stack = (void **) safe_realloc(s->stack, s->capacity * sizeof(void *)); } s->stack[ ++(s->sp) ] = item; }
/** * @return (but does not remove) the nth item from the top of the Stack, * starting at zero, i.e. Stack_peekAt(0) is equivalent to Stack_peek(). * If n is out of range (n < 0 or n >= Stack_size()) returns NULL. */ LIBSBML_EXTERN void * Stack_peekAt (Stack_t *s, int n) { int size = Stack_size(s); if (s == NULL) return NULL; if (n < 0 || n >= size) { REPORT_STACK_RANGE_ERROR("Stack_peekAt", n, size); return NULL; } return s->stack[ s->sp - n ]; }
/** * @if conly * @memberof ASTNode_t * @endif */ LIBSBML_EXTERN ASTNode_t * SBML_parseFormula (const char *formula) { long rule, state, action; ASTNode_t *node = NULL; FormulaTokenizer_t *tokenizer = NULL; Stack_t *stack = NULL; Token_t *token = NULL; if (formula == NULL) return NULL; tokenizer = FormulaTokenizer_createFromFormula(formula); token = FormulaTokenizer_nextToken(tokenizer); stack = Stack_create(20); Stack_push(stack, (void *) START_STATE); while (1) { state = (long) Stack_peek(stack); action = FormulaParser_getAction(state, token); if (action == ACCEPT_STATE) { node = Stack_peekAt(stack, 1); break; } else if (action == ERROR_STATE) { /** * Free ASTNodes on the Stack, skip the states. */ while (Stack_size(stack) > 1) { Stack_pop(stack); ASTNode_free( Stack_pop(stack) ); } node = NULL; break; } /** * Shift */ else if (action > 0) { Stack_push( stack, ASTNode_createFromToken(token) ); Stack_push( stack, (void *) action ); Token_free(token); token = FormulaTokenizer_nextToken(tokenizer); } /** * Reduce */ else if (action < 0) { rule = -action; node = FormulaParser_reduceStackByRule(stack, rule); state = (long) Stack_peek(stack); Stack_push( stack, node ); Stack_push( stack, (void *) FormulaParser_getGoto(state, rule) ); } } FormulaTokenizer_free(tokenizer); Stack_free(stack); Token_free(token); return node; }