int _gmx_sel_lexer_process_pending(YYSTYPE *yylval, YYLTYPE *yylloc, gmx_sel_lexer_t *state) { if (state->nextparam) { gmx_ana_selparam_t *param = state->nextparam; bool bBoolNo = state->bBoolNo; if (state->neom > 0) { --state->neom; _gmx_sel_lexer_add_token(yylloc, nullptr, 0, state); return END_OF_METHOD; } state->nextparam = nullptr; state->bBoolNo = false; _gmx_sel_lexer_add_token(yylloc, param->name, -1, state); return init_param_token(yylval, param, bBoolNo); } if (state->prev_pos_kw > 0) { --state->prev_pos_kw; } if (state->nextMethodSymbol) { const gmx::SelectionParserSymbol *symbol = state->nextMethodSymbol; state->nextMethodSymbol = nullptr; return init_method_token(yylval, yylloc, symbol, true, state); } return 0; }
int _gmx_sel_lexer_process_pending(YYSTYPE *yylval, gmx_sel_lexer_t *state) { if (state->nextparam) { gmx_ana_selparam_t *param = state->nextparam; bool bBoolNo = state->bBoolNo; if (state->neom > 0) { --state->neom; return END_OF_METHOD; } state->nextparam = NULL; state->bBoolNo = false; _gmx_sel_lexer_add_token(param->name, -1, state); return init_param_token(yylval, param, bBoolNo); } if (state->prev_pos_kw > 0) { --state->prev_pos_kw; } if (state->nextmethod) { gmx_ana_selmethod_t *method = state->nextmethod; state->nextmethod = NULL; return init_method_token(yylval, method, true, state); } return 0; }
int _gmx_sel_lexer_process_identifier(YYSTYPE *yylval, YYLTYPE *yylloc, char *yytext, size_t yyleng, gmx_sel_lexer_t *state) { /* Check if the identifier matches with a parameter name */ if (state->msp >= 0) { gmx_ana_selparam_t *param = nullptr; bool bBoolNo = false; int sp = state->msp; while (!param && sp >= 0) { int i; for (i = 0; i < state->mstack[sp]->nparams; ++i) { /* Skip NULL parameters and too long parameters */ if (state->mstack[sp]->param[i].name == nullptr || strlen(state->mstack[sp]->param[i].name) > yyleng) { continue; } if (!strncmp(state->mstack[sp]->param[i].name, yytext, yyleng)) { param = &state->mstack[sp]->param[i]; break; } /* Check separately for a 'no' prefix on boolean parameters */ if (state->mstack[sp]->param[i].val.type == NO_VALUE && yyleng > 2 && yytext[0] == 'n' && yytext[1] == 'o' && !strncmp(state->mstack[sp]->param[i].name, yytext+2, yyleng-2)) { param = &state->mstack[sp]->param[i]; bBoolNo = true; break; } } if (!param) { --sp; } } if (param) { if (param->val.type == NO_VALUE && !bBoolNo) { state->bMatchBool = true; } if (sp < state->msp) { state->neom = state->msp - sp - 1; state->nextparam = param; state->bBoolNo = bBoolNo; return END_OF_METHOD; } _gmx_sel_lexer_add_token(yylloc, param->name, -1, state); return init_param_token(yylval, param, bBoolNo); } } /* Check if the identifier matches with a symbol */ const gmx::SelectionParserSymbol *symbol = state->sc->symtab->findSymbol(std::string(yytext, yyleng)); /* If there is no match, return the token as a string */ if (!symbol) { yylval->str = gmx_strndup(yytext, yyleng); _gmx_sel_lexer_add_token(yylloc, yytext, yyleng, state); return IDENTIFIER; } gmx::SelectionParserSymbol::SymbolType symtype = symbol->type(); /* For method symbols, we need some extra processing. */ if (symtype == gmx::SelectionParserSymbol::MethodSymbol) { return init_method_token(yylval, yylloc, symbol, state->prev_pos_kw > 0, state); } _gmx_sel_lexer_add_token(yylloc, symbol->name().c_str(), -1, state); /* Reserved symbols should have been caught earlier */ if (symtype == gmx::SelectionParserSymbol::ReservedSymbol) { GMX_THROW(gmx::InternalError(gmx::formatString( "Mismatch between tokenizer and reserved symbol table (for '%s')", symbol->name().c_str()))); } /* For variable symbols, return the type of the variable value */ if (symtype == gmx::SelectionParserSymbol::VariableSymbol) { const gmx::SelectionTreeElementPointer &var = symbol->variableValue(); /* Return simple tokens for constant variables */ if (var->type == SEL_CONST) { switch (var->v.type) { case INT_VALUE: yylval->i = var->v.u.i[0]; return TOK_INT; case REAL_VALUE: yylval->r = var->v.u.r[0]; return TOK_REAL; case POS_VALUE: break; default: GMX_THROW(gmx::InternalError("Unsupported variable type")); } } yylval->sel = new gmx::SelectionTreeElementPointer(var); switch (var->v.type) { case INT_VALUE: return VARIABLE_NUMERIC; case REAL_VALUE: return VARIABLE_NUMERIC; case POS_VALUE: return VARIABLE_POS; case GROUP_VALUE: return VARIABLE_GROUP; default: delete yylval->sel; GMX_THROW(gmx::InternalError("Unsupported variable type")); } /* This position should not be reached. */ } /* For position symbols, we need to return KEYWORD_POS, but we also need * some additional handling. */ if (symtype == gmx::SelectionParserSymbol::PositionSymbol) { state->bMatchOf = true; yylval->str = gmx_strdup(symbol->name().c_str()); state->prev_pos_kw = 2; return KEYWORD_POS; } /* Should not be reached */ return INVALID; }
/*! \brief * Processes a selection method token. */ static int init_method_token(YYSTYPE *yylval, YYLTYPE *yylloc, const gmx::SelectionParserSymbol *symbol, bool bPosMod, gmx_sel_lexer_t *state) { gmx_ana_selmethod_t *method = symbol->methodValue(); /* If the previous token was not KEYWORD_POS, return EMPTY_POSMOD * before the actual method to work around a limitation in Bison. */ if (!bPosMod && method->type != POS_VALUE) { state->nextMethodSymbol = symbol; _gmx_sel_lexer_add_token(yylloc, nullptr, 0, state); return EMPTY_POSMOD; } _gmx_sel_lexer_add_token(yylloc, symbol->name().c_str(), -1, state); yylval->meth = method; if (!(method->flags & SMETH_MODIFIER) && method->nparams == 0) { /* Keyword */ switch (method->type) { case INT_VALUE: case REAL_VALUE: state->bMatchOf = true; return KEYWORD_NUMERIC; case STR_VALUE: return KEYWORD_STR; case GROUP_VALUE: return KEYWORD_GROUP; default: GMX_THROW(gmx::InternalError("Unsupported keyword type")); } } else { /* Method with parameters or a modifier */ if (method->flags & SMETH_MODIFIER) { /* Remove all methods from the stack */ state->msp = -1; if (method->param[1].name == nullptr) { state->nextparam = &method->param[1]; } } else { if (method->param[0].name == nullptr) { state->nextparam = &method->param[0]; } } ++state->msp; if (state->msp >= state->mstack_alloc) { state->mstack_alloc += 10; srenew(state->mstack, state->mstack_alloc); } state->mstack[state->msp] = method; if (method->flags & SMETH_MODIFIER) { return MODIFIER; } switch (method->type) { case INT_VALUE: return METHOD_NUMERIC; case REAL_VALUE: return METHOD_NUMERIC; case POS_VALUE: return METHOD_POS; case GROUP_VALUE: return METHOD_GROUP; default: --state->msp; GMX_THROW(gmx::InternalError("Unsupported method type")); } } }