END_TEST START_TEST (test_FormulaParser_accessWithNULL) { fail_unless ( FormulaParser_getAction(0, NULL) == ERROR_STATE); fail_unless ( SBML_parseFormula(NULL) == NULL); }
CK_CPPSTART #endif /** * The following are private and used only within FormulaParser.c; however, * I don't know how else to make them "public" only for testing than to put * them here */ #define START_STATE 0 #define ACCEPT_STATE 0 #define ERROR_STATE 27 #define NUM_STATES 27 /** * The Action[] table contains 144 entries. To test them all would be * laborious and silly. Instead, for a few token type, test the first, * last and middle entry in each token "run". Also, test some error * states. */ START_TEST (test_FormulaParser_getAction) { int i; Token_t *t = Token_create(); t->type = TT_NAME; fail_unless( FormulaParser_getAction( 0, t) == 6, NULL ); fail_unless( FormulaParser_getAction(10, t) == 6, NULL ); fail_unless( FormulaParser_getAction(25, t) == 6, NULL ); fail_unless( FormulaParser_getAction( 1, t) == ERROR_STATE, NULL ); t->type = TT_INTEGER; fail_unless( FormulaParser_getAction( 0, t) == 1, NULL ); fail_unless( FormulaParser_getAction(10, t) == 1, NULL ); fail_unless( FormulaParser_getAction(25, t) == 1, NULL ); fail_unless( FormulaParser_getAction( 1, t) == ERROR_STATE, NULL ); t->type = TT_PLUS; fail_unless( FormulaParser_getAction( 1, t) == -9, NULL ); fail_unless( FormulaParser_getAction(16, t) == -2, NULL ); fail_unless( FormulaParser_getAction(24, t) == -11, NULL ); fail_unless( FormulaParser_getAction( 2, t) == ERROR_STATE, NULL ); t->type = TT_MINUS; fail_unless( FormulaParser_getAction( 0, t) == 5, NULL ); fail_unless( FormulaParser_getAction(16, t) == -2, NULL ); fail_unless( FormulaParser_getAction(25, t) == 5, NULL ); fail_unless( FormulaParser_getAction( 2, t) == ERROR_STATE, NULL ); t->type = TT_END; fail_unless( FormulaParser_getAction( 1, t) == -9, NULL ); fail_unless( FormulaParser_getAction(17, t) == -5, NULL ); fail_unless( FormulaParser_getAction(24, t) == -11, NULL ); fail_unless( FormulaParser_getAction( 3, t) == ERROR_STATE, NULL ); /** * TT_UNKNOWN should always yield an error state. */ t->type = TT_UNKNOWN; for (i = 0; i < NUM_STATES; i++) { fail_unless( FormulaParser_getAction(i, t) == ERROR_STATE, NULL ); } Token_free(t); }
/** * @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; }