END_TEST START_TEST (test_FormulaTokenizer_numbers_nan_inf) { FormulaTokenizer_t *ft = FormulaTokenizer_createFromFormula("NaN Inf"); Token_t *t; t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL ); fail_unless( t->value.real != t->value.real ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL ); fail_unless( util_isInf(t->value.real) == 1 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_END ); Token_free(t); FormulaTokenizer_free(ft); }
END_TEST START_TEST (test_FormulaTokenizer_names) { FormulaTokenizer_t *ft = FormulaTokenizer_createFromFormula("foobar Foo2Bar _Foo_Bar"); Token_t *t; t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_NAME ); fail_unless( !strcmp(t->value.name, "foobar") ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_NAME ); fail_unless( !strcmp(t->value.name, "Foo2Bar") ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_NAME ); fail_unless( !strcmp(t->value.name, "_Foo_Bar") ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_END ); Token_free(t); FormulaTokenizer_free(ft); }
END_TEST START_TEST (test_FormulaTokenizer_empty) { FormulaTokenizer_t *ft = FormulaTokenizer_createFromFormula(""); Token_t *t; t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_END ); fail_unless( t->value.ch == '\0' ); Token_free(t); /** * Subsequent calls to FormulaTokenizer_nextToken() should continue to * return TT_END. */ t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_END ); fail_unless( t->value.ch == '\0' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_END ); fail_unless( t->value.ch == '\0' ); Token_free(t); FormulaTokenizer_free(ft); }
END_TEST START_TEST (test_FormulaTokenizer_numbers_exp_bug) { /* we were failing to correctly parse an exponentional followed * by a sign with no space */ const char *formula = "12.3e1+.314E1"; FormulaTokenizer_t *ft = FormulaTokenizer_createFromFormula(formula); Token_t *t; t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL_E ); fail_unless( t->value.real == 12.3 ); fail_unless( t->exponent == 1 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_PLUS ); fail_unless( t->value.ch == '+' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL_E ); fail_unless( t->value.real == .314 ); fail_unless( t->exponent == 1 ); Token_free(t); FormulaTokenizer_free(ft); }
END_TEST START_TEST (test_FormulaTokenizer_operators) { FormulaTokenizer_t *ft = FormulaTokenizer_createFromFormula("+-*/^(),"); Token_t *t; t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_PLUS ); fail_unless( t->value.ch == '+' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_MINUS ); fail_unless( t->value.ch == '-' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_TIMES ); fail_unless( t->value.ch == '*' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_DIVIDE ); fail_unless( t->value.ch == '/' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_POWER ); fail_unless( t->value.ch == '^' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_LPAREN ); fail_unless( t->value.ch == '(' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_RPAREN ); fail_unless( t->value.ch == ')' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_COMMA ); fail_unless( t->value.ch == ',' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless(t->type == TT_END ); fail_unless( t->value.ch == '\0' ); Token_free(t); FormulaTokenizer_free(ft); }
END_TEST START_TEST (test_FormulaTokenizer_accessWithNULL) { fail_unless( FormulaTokenizer_createFromFormula(NULL) == NULL ); FormulaTokenizer_free(NULL); fail_unless( FormulaTokenizer_nextToken(NULL) == NULL ); }
LIBSBML_CPP_NAMESPACE_USE CK_CPPSTART #endif START_TEST (test_FormulaTokenizer_create) { const char *formula = "1 + two * 3"; FormulaTokenizer_t *ft = FormulaTokenizer_createFromFormula(formula); fail_unless( !strcmp(ft->formula, formula) ); fail_unless( ft->pos == 0 ); FormulaTokenizer_free(ft); }
END_TEST START_TEST (test_FormulaTokenizer_whitespace) { FormulaTokenizer_t *ft = FormulaTokenizer_createFromFormula(" \t \n "); Token_t *t; t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_END ); fail_unless( t->value.ch == '\0' ); Token_free(t); FormulaTokenizer_free(ft); }
END_TEST START_TEST (test_FormulaTokenizer_unknown) { FormulaTokenizer_t *ft = FormulaTokenizer_createFromFormula("*****@*****.**"); Token_t *t; t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_NAME ); fail_unless( !strcmp(t->value.name, "bbornstein") ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_UNKNOWN ); fail_unless( t->value.ch == '@' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_NAME ); fail_unless( !strcmp(t->value.name, "acm") ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_UNKNOWN ); fail_unless( t->value.ch == '.' ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_NAME ); fail_unless( !strcmp(t->value.name, "org") ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_END ); Token_free(t); FormulaTokenizer_free(ft); }
END_TEST START_TEST (test_FormulaTokenizer_numbers) { FormulaTokenizer_t *ft = FormulaTokenizer_createFromFormula("123 3.14 .007 6.7 5."); Token_t *t; t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_INTEGER ); fail_unless( t->value.integer == 123 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL ); fail_unless( t->value.real == 3.14 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL ); fail_unless( t->value.real == .007 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL ); fail_unless( t->value.real == 6.7 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL ); fail_unless( t->value.real == 5.0 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_END ); Token_free(t); FormulaTokenizer_free(ft); }
END_TEST START_TEST (test_FormulaTokenizer_numbers_locale) { FormulaTokenizer_t *ft = FormulaTokenizer_createFromFormula("2.72"); Token_t *t; setlocale(LC_NUMERIC, "de_DE"); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL ); fail_unless( t->value.real == 2.72 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_END ); Token_free(t); setlocale(LC_NUMERIC, "C"); FormulaTokenizer_free(ft); }
END_TEST START_TEST (test_FormulaTokenizer_numbers_exp) { const char *formula = "12.3e1 .314E1 7e-3 .067e2 5E0 2e+12 3e 4"; FormulaTokenizer_t *ft = FormulaTokenizer_createFromFormula(formula); Token_t *t; t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL_E ); fail_unless( t->value.real == 12.3 ); fail_unless( t->exponent == 1 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL_E ); fail_unless( t->value.real == .314 ); fail_unless( t->exponent == 1 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL_E ); fail_unless( t->value.real == 7 ); fail_unless( t->exponent == -3 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL_E ); fail_unless( t->value.real == .067 ); fail_unless( t->exponent == 2 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL_E ); fail_unless( t->value.real == 5.0 ); fail_unless( t->exponent == 0 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL_E ); fail_unless( t->value.real == 2 ); fail_unless( t->exponent == 12 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_REAL_E ); fail_unless( t->value.real == 3.0 ); fail_unless( t->exponent == 0 ); Token_free(t); /** * Gobble-up the '4'. This last token is here as a test to ensure the * previous token is not interpreted as 3e4. */ t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_INTEGER ); fail_unless( t->value.integer == 4 ); Token_free(t); t = FormulaTokenizer_nextToken(ft); fail_unless( t->type == TT_END ); Token_free(t); FormulaTokenizer_free(ft); }
/** * @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; }