void Checker::process_tokens() { int line_index = -1; for(token = tokens.begin(); token != tokens.end(); ++token) { if(token->type == TT_WHITESPACE) { whitespace_sequence_check(); continue; } if(token->line_index != line_index) { nesting_depth_check(); line_index = token->line_index; env.line_closed = false; } if(env.line_closed && token->type != TT_COMMENT && !is_blockbracket()) { add_result("two or more expressions at one line"); env.line_closed = false; } switch(token->type) { case TT_CBRACKET_OPEN: case TT_CBRACKET_CLOSE: case TT_BRACE: case TT_BRACKET: unibracket_check(); } switch(token->type) { case TT_CBRACKET_OPEN: case TT_PASBRACKET_OPEN: case TT_KEYWORD_DECLARING_VARBLOCK: blockbracket_check(); break; case TT_CLASSNAME: case TT_FUNCTION: case TT_IDENTIFIER: { NameType name_type = ( token->type == TT_CLASSNAME ? NT_CLASS : token->type == TT_FUNCTION ? NT_FUNCTION : NT_VARIABLE); auto name_in_list = env.list_of_names.find(token->line); if(name_in_list == env.list_of_names.end()) { env.list_of_names[token->line] = name_type; name_style_check(name_type); } else { if(name_type == NT_VARIABLE) //TODO: store checked names name_style_check(name_in_list->second); else if(name_in_list->second != name_type) { //constructors in C++ are exceptions //assume C++ function with name == classname is a constructor or destructor //TODO: do check? } } break; } case TT_KEYWORD_WITH_FOLLOWING_OPERATION: { if(keyword_equal("else")) { if(previous_is_blockbracket()) { else_check(); } else if( settings.ext_bool_options["forbid_multiple_expressions_per_line"] == EB_TRUE && file_language.first == L_PASCAL && token->start != lines[token->line_index].depth_by_fact) { add_result("two or more expressions at one line"); env.line_closed = false; } } if(settings.ext_bool_options["forbid_multiple_expressions_per_line"] == EB_TRUE) env.line_closed = true; env.indented_operation_expected = true; break; } case TT_KEYWORD_WITH_FOLLOWING_OPERATION_AFTER_BRACE: keyword_and_brace_check(); env.indented_operation_expected_after_braces = true; //required for multiple ops break; case TT_SEMICOLON: if(env.braces_opened == 0) if(settings.ext_bool_options["forbid_multiple_expressions_per_line"] == EB_TRUE) env.line_closed = true; break; case TT_BRACE: brace_check(); break; } if(env.indented_operation_expected && settings.ext_bool_options["compulsory_block_braces"] == EB_TRUE) { if(!next_is_blockbracket(false)) add_result("block brace expected: { or begin"); env.indented_operation_expected = false; } } }
bool colvarparse::key_lookup(std::string const &conf, char const *key_in, std::string &data, size_t &save_pos) { // add this keyword to the register (in its camelCase version) add_keyword(key_in); // use the lowercase version from now on std::string const key(to_lower_cppstr(key_in)); // "conf_lower" is only used to lookup the keyword, but its value // will be read from "conf", in order not to mess up file names std::string const conf_lower(to_lower_cppstr(conf)); // by default, there is no value, unless we found one data = ""; // when the function is invoked without save_pos, ensure that we // start from zero colvarparse::dummy_pos = 0; // start from the first occurrence of key size_t pos = conf_lower.find(key, save_pos); // iterate over all instances until it finds the isolated keyword while (true) { if (pos == std::string::npos) { // no valid instance of the keyword has been found return false; } bool b_isolated_left = true, b_isolated_right = true; if (pos > 0) { if ( std::string("\n"+white_space+ "}").find(conf[pos-1]) == std::string::npos ) { // none of the valid delimiting characters is on the left of key b_isolated_left = false; } } if (pos < conf.size()-key.size()-1) { if ( std::string("\n"+white_space+ "{").find(conf[pos+key.size()]) == std::string::npos ) { // none of the valid delimiting characters is on the right of key b_isolated_right = false; } } // check that there are matching braces between here and the end of conf bool const b_not_within_block = brace_check(conf, pos); bool const b_isolated = (b_isolated_left && b_isolated_right && b_not_within_block); if (b_isolated) { // found it break; } else { // try the next occurrence of key pos = conf_lower.find(key, pos+key.size()); } } // save the pointer for a future call (when iterating over multiple // valid instances of the same keyword) save_pos = pos + key.size(); // get the remainder of the line size_t pl = conf.rfind("\n", pos); size_t line_begin = (pl == std::string::npos) ? 0 : pos; size_t nl = conf.find("\n", pos); size_t line_end = (nl == std::string::npos) ? conf.size() : nl; std::string line(conf, line_begin, (line_end-line_begin)); size_t data_begin = (to_lower_cppstr(line)).find(key) + key.size(); data_begin = line.find_first_not_of(white_space, data_begin+1); // size_t data_begin_absolute = data_begin + line_begin; // size_t data_end_absolute = data_begin; if (data_begin != std::string::npos) { size_t data_end = line.find_last_not_of(white_space) + 1; data_end = (data_end == std::string::npos) ? line.size() : data_end; // data_end_absolute = data_end + line_begin; if (line.find('{', data_begin) != std::string::npos) { size_t brace_count = 1; size_t brace = line.find('{', data_begin); // start from the first opening brace while (brace_count > 0) { // find the matching closing brace brace = line.find_first_of("{}", brace+1); while (brace == std::string::npos) { // add a new line if (line_end >= conf.size()) { cvm::fatal_error("Parse error: reached the end while " "looking for closing brace; until now " "the following was parsed: \"\n"+ line+"\".\n"); return false; } size_t const old_end = line.size(); // data_end_absolute += old_end+1; line_begin = line_end; nl = conf.find('\n', line_begin+1); if (nl == std::string::npos) line_end = conf.size(); else line_end = nl; line.append(conf, line_begin, (line_end-line_begin)); brace = line.find_first_of("{}", old_end); } if (line[brace] == '{') brace_count++; if (line[brace] == '}') brace_count--; } // set data_begin after the opening brace data_begin = line.find_first_of('{', data_begin) + 1; data_begin = line.find_first_not_of(white_space, data_begin); // set data_end before the closing brace data_end = brace; data_end = line.find_last_not_of(white_space+"}", data_end) + 1; // data_end_absolute = line_end; if (data_end > line.size()) data_end = line.size(); } data.append(line, data_begin, (data_end-data_begin)); if (data.size() && save_delimiters) { data_begin_pos.push_back(conf.find(data, pos+key.size())); data_end_pos.push_back(data_begin_pos.back()+data.size()); // std::cerr << "key = " << key << ", data = \"" // << data << "\", data_begin, data_end = " // << data_begin_pos.back() << ", " << data_end_pos.back() // << "\n"; } } save_pos = line_end; return true; }