int cvm::atom_group::parse(std::string const &conf) { std::string group_conf; // TODO move this to the cvc class constructor/init // save_delimiters is set to false for this call, because "conf" is // not the config string of this group, but of its parent object // (which has already taken care of the delimiters) save_delimiters = false; key_lookup(conf, key.c_str(), group_conf, dummy_pos); // restoring the normal value, because we do want keywords checked // inside "group_conf" save_delimiters = true; if (group_conf.size() == 0) { cvm::error("Error: atom group \""+key+ "\" is set, but has no definition.\n", INPUT_ERROR); return COLVARS_ERROR; } cvm::increase_depth(); cvm::log("Initializing atom group \""+key+"\".\n"); description = "atom group " + key; // whether or not to include messages in the log // colvarparse::Parse_Mode mode = parse_silent; // { // bool b_verbose; // get_keyval (group_conf, "verboseOutput", b_verbose, false, parse_silent); // if (b_verbose) mode = parse_normal; // } // colvarparse::Parse_Mode mode = parse_normal; int parse_error = COLVARS_OK; { std::string numbers_conf = ""; size_t pos = 0; while (key_lookup(group_conf, "atomNumbers", numbers_conf, pos)) { parse_error |= add_atom_numbers(numbers_conf); numbers_conf = ""; } } { std::string index_group_name; if (get_keyval(group_conf, "indexGroup", index_group_name)) { // use an index group from the index file read globally parse_error |= add_index_group(index_group_name); } } { std::string range_conf = ""; size_t pos = 0; while (key_lookup(group_conf, "atomNumbersRange", range_conf, pos)) { parse_error |= add_atom_numbers_range(range_conf); range_conf = ""; } } { std::vector<std::string> psf_segids; get_keyval(group_conf, "psfSegID", psf_segids, std::vector<std::string>()); std::vector<std::string>::iterator psii; for (psii = psf_segids.begin(); psii < psf_segids.end(); ++psii) { if ( (psii->size() == 0) || (psii->size() > 4) ) { cvm::error("Error: invalid PSF segment identifier provided, \""+ (*psii)+"\".\n", INPUT_ERROR); } } std::string range_conf = ""; size_t pos = 0; size_t range_count = 0; psii = psf_segids.begin(); while (key_lookup(group_conf, "atomNameResidueRange", range_conf, pos)) { range_count++; if (psf_segids.size() && (range_count > psf_segids.size())) { cvm::error("Error: more instances of \"atomNameResidueRange\" than " "values of \"psfSegID\".\n", INPUT_ERROR); } else { parse_error |= add_atom_name_residue_range(psf_segids.size() ? *psii : std::string(""), range_conf); if (psf_segids.size()) psii++; } range_conf = ""; } } { // read the atoms from a file std::string atoms_file_name; if (get_keyval(group_conf, "atomsFile", atoms_file_name, std::string(""))) { std::string atoms_col; if (!get_keyval(group_conf, "atomsCol", atoms_col, std::string(""))) { cvm::error("Error: parameter atomsCol is required if atomsFile is set.\n", INPUT_ERROR); } double atoms_col_value; bool const atoms_col_value_defined = get_keyval(group_conf, "atomsColValue", atoms_col_value, 0.0); if (atoms_col_value_defined && (!atoms_col_value)) { cvm::error("Error: atomsColValue, if provided, must be non-zero.\n", INPUT_ERROR); } cvm::load_atoms(atoms_file_name.c_str(), *this, atoms_col, atoms_col_value); } } // Catch any errors from all the initialization steps above if (parse_error || cvm::get_error()) return (parse_error || cvm::get_error()); // checks of doubly-counted atoms have been handled by add_atom() already if (get_keyval(group_conf, "dummyAtom", dummy_atom_pos, cvm::atom_pos())) { b_dummy = true; // note: atoms_ids.size() is used here in lieu of atoms.size(), // which can be empty for scalable groups if (atoms_ids.size()) { cvm::error("Error: cannot set up group \""+ key+"\" as a dummy atom " "and provide it with atom definitions.\n", INPUT_ERROR); } } else { b_dummy = false; if (!(atoms_ids.size())) { cvm::error("Error: no atoms defined for atom group \""+ key+"\".\n", INPUT_ERROR); } // whether these atoms will ever receive forces or not bool enable_forces = true; // disableForces is deprecated if (get_keyval(group_conf, "enableForces", enable_forces, true)) { noforce = !enable_forces; } else { get_keyval(group_conf, "disableForces", noforce, false, colvarparse::parse_silent); } } if (is_enabled(f_ag_scalable) && !b_dummy) { index = (cvm::proxy)->init_atom_group(atoms_ids); } parse_error |= parse_fitting_options(group_conf); // TODO move this to colvarparse object check_keywords(group_conf, key.c_str()); if (cvm::get_error()) { cvm::error("Error setting up atom group \""+key+"\"."); return COLVARS_ERROR; } // Calculate all required properties (such as total mass) setup(); if (cvm::debug()) cvm::log("Done initializing atom group \""+key+"\".\n"); cvm::log("Atom group \""+key+"\" defined, "+ cvm::to_str(atoms_ids.size())+" atoms initialized: total mass = "+ cvm::to_str(total_mass)+", total charge = "+ cvm::to_str(total_charge)+".\n"); cvm::decrease_depth(); return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK); }
static int next_token(parser_ctx_t *ctx, void *lval) { do { skip_spaces(ctx); if(ctx->ptr == ctx->end) return tEOF; }while(skip_comment(ctx) || skip_html_comment(ctx)); if(isalphaW(*ctx->ptr)) { int ret = check_keywords(ctx, lval); if(ret) return ret; return parse_identifier(ctx, lval); } if(isdigitW(*ctx->ptr)) return parse_numeric_literal(ctx, lval); switch(*ctx->ptr) { case '{': case '(': case ')': case '[': case ']': case ';': case ',': case '~': case '?': case ':': return *ctx->ptr++; case '}': *(const WCHAR**)lval = ctx->ptr++; return '}'; case '.': if(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) return parse_double_literal(ctx, 0, lval); return '.'; case '<': if(++ctx->ptr == ctx->end) { *(int*)lval = EXPR_LESS; return tRelOper; } switch(*ctx->ptr) { case '=': /* <= */ ctx->ptr++; *(int*)lval = EXPR_LESSEQ; return tRelOper; case '<': /* << */ if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* <<= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNLSHIFT; return tAssignOper; } *(int*)lval = EXPR_LSHIFT; return tShiftOper; default: /* < */ *(int*)lval = EXPR_LESS; return tRelOper; } case '>': if(++ctx->ptr == ctx->end) { /* > */ *(int*)lval = EXPR_GREATER; return tRelOper; } switch(*ctx->ptr) { case '=': /* >= */ ctx->ptr++; *(int*)lval = EXPR_GREATEREQ; return tRelOper; case '>': /* >> */ if(++ctx->ptr < ctx->end) { if(*ctx->ptr == '=') { /* >>= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNRSHIFT; return tAssignOper; } if(*ctx->ptr == '>') { /* >>> */ if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* >>>= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNRRSHIFT; return tAssignOper; } *(int*)lval = EXPR_RRSHIFT; return tRelOper; } } *(int*)lval = EXPR_RSHIFT; return tShiftOper; default: *(int*)lval = EXPR_GREATER; return tRelOper; } case '+': ctx->ptr++; if(ctx->ptr < ctx->end) { switch(*ctx->ptr) { case '+': /* ++ */ ctx->ptr++; return tINC; case '=': /* += */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNADD; return tAssignOper; } } return '+'; case '-': ctx->ptr++; if(ctx->ptr < ctx->end) { switch(*ctx->ptr) { case '-': /* -- or --> */ ctx->ptr++; if(ctx->is_html && ctx->nl && ctx->ptr < ctx->end && *ctx->ptr == '>') { ctx->ptr++; return tHTMLCOMMENT; } return tDEC; case '=': /* -= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNSUB; return tAssignOper; } } return '-'; case '*': if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* *= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNMUL; return tAssignOper; } return '*'; case '%': if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* %= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNMOD; return tAssignOper; } return '%'; case '&': if(++ctx->ptr < ctx->end) { switch(*ctx->ptr) { case '=': /* &= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNAND; return tAssignOper; case '&': /* && */ ctx->ptr++; return tANDAND; } } return '&'; case '|': if(++ctx->ptr < ctx->end) { switch(*ctx->ptr) { case '=': /* |= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNOR; return tAssignOper; case '|': /* || */ ctx->ptr++; return tOROR; } } return '|'; case '^': if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* ^= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNXOR; return tAssignOper; } return '^'; case '!': if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* != */ if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* !== */ ctx->ptr++; *(int*)lval = EXPR_NOTEQEQ; return tEqOper; } *(int*)lval = EXPR_NOTEQ; return tEqOper; } return '!'; case '=': if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* == */ if(++ctx->ptr < ctx->end && *ctx->ptr == '=') { /* === */ ctx->ptr++; *(int*)lval = EXPR_EQEQ; return tEqOper; } *(int*)lval = EXPR_EQ; return tEqOper; } return '='; case '/': if(++ctx->ptr < ctx->end) { if(*ctx->ptr == '=') { /* /= */ ctx->ptr++; *(int*)lval = EXPR_ASSIGNDIV; return kDIVEQ; } } return '/'; case '\"': case '\'': return parse_string_literal(ctx, lval, *ctx->ptr); case '_': case '$': return parse_identifier(ctx, lval); case '@': return '@'; } WARN("unexpected char '%c' %d\n", *ctx->ptr, *ctx->ptr); return 0; }
static int parse_next_token(void *lval, parser_ctx_t *ctx) { WCHAR c; skip_spaces(ctx); if(ctx->ptr == ctx->end) return ctx->last_token == tNL ? tEOF : tNL; c = *ctx->ptr; if('0' <= c && c <= '9') return parse_numeric_literal(ctx, lval); if(isalphaW(c)) { int ret = check_keywords(ctx); if(!ret) return parse_identifier(ctx, lval); if(ret != tREM) return ret; c = '\''; } switch(c) { case '\n': ctx->ptr++; return tNL; case '\'': return comment_line(ctx); case ':': case ')': case ',': case '=': case '+': case '*': case '/': case '^': case '\\': case '.': case '_': return *ctx->ptr++; case '-': if(ctx->is_html && ctx->ptr[1] == '-' && ctx->ptr[2] == '>') return comment_line(ctx); ctx->ptr++; return '-'; case '(': /* NOTE: * We resolve empty brackets in lexer instead of parser to avoid complex conflicts * in call statement special case |f()| without 'call' keyword */ ctx->ptr++; skip_spaces(ctx); if(*ctx->ptr == ')') { ctx->ptr++; return tEMPTYBRACKETS; } return '('; case '"': return parse_string_literal(ctx, lval); case '&': if(*++ctx->ptr == 'h' || *ctx->ptr == 'H') return parse_hex_literal(ctx, lval); return '&'; case '<': switch(*++ctx->ptr) { case '>': ctx->ptr++; return tNEQ; case '=': ctx->ptr++; return tLTEQ; case '!': if(ctx->is_html && ctx->ptr[1] == '-' && ctx->ptr[2] == '-') return comment_line(ctx); } return '<'; case '>': if(*++ctx->ptr == '=') { ctx->ptr++; return tGTEQ; } return '>'; default: FIXME("Unhandled char %c in %s\n", *ctx->ptr, debugstr_w(ctx->ptr)); } return 0; }