static Boolean test_is_spaces_only(int verbose) { static struct stringtest { char *str1; Boolean result; } tests[] = { { "bar", False }, { " \t\n ", True }, { " a ", False }, { "", True }, }; size_t i; Boolean result = True; for (i = 0; i < (sizeof tests / sizeof tests[0]); i++) { if (verbose) { INFO((stderr, "is_spaces_only(%s) -> %d == %d?\n", tests[i].str1, is_spaces_only(tests[i].str1), tests[i].result)); } if (is_spaces_only(tests[i].str1) != tests[i].result) { result = False; } } return result; }
void LexicalAnalyzer::line_analysis(const std::string& code, unsigned line_num) { // разбиваем входной код на лексемы и пробельные символы unsigned pos = 0; boost::regex regex(regex_separators); boost::smatch match; std::string::const_iterator itbegin = code.begin(); std::string::const_iterator itend = code.end(); std::vector<unsigned> division_points; // список точек биения текста while (boost::regex_search(itbegin, itend, match, regex)) { std::string dummy_str = match.str(); pos += match.position(); division_points.push_back(pos); // позиция начала разделителя pos += match.str().length(); itbegin = match[0].second; } if (division_points.front() != 0) // если в списке точек биения нет начала строки, добавим её { division_points.insert(division_points.begin(), 0); } if (division_points.back() != code.length()) // если в списке точек биения нет конца стороки, добавим её { division_points.insert(division_points.end(), code.length()); } // Делим текст на лексемы по точкам биения, если лексема состоит только из пробельных // символов, то её не включаем в список лексем. for (unsigned i = 0; i < division_points.size() - 1; i++) { std::string lexem = code.substr(division_points[i], division_points[i + 1] - division_points[i]); if (!is_spaces_only(lexem)) { Token token(lexem, line_num, division_points[i]); // проходимся по списку возможных типов лексемы CheckList::const_iterator checker = check_list_.begin(); for (; checker != check_list_.end(); ++checker) { if (checker->second(token)) { token.type_ = checker->first; break; } } // если лексемой оказался токен состоящий из символов, // используемых операторами, то есть вероятность, что // в этой лексеме несколько операторов, проверим это if (token.type_ == Token::Type_Operator && !is_exist_operator(token)) { while (!token.str_.empty()) { // Попробуем разбить на несколько операторов. // Правило разбития: сначала ищим операторы максимальной длинны // в начале лексемы из существующих. Потом для остатка лексемы // повторяем эти действия. Итак пока строка не закончится либо пока // ни найдём несуществующий оператор. unsigned cur_pos_in_lexem = 0; std::string temp_str; OperatorsList::const_iterator op_it = c_operator_list.begin(); for (; op_it != c_operator_list.end(); ++op_it) { if (token.str_.find(op_it->first) == 0) // нашли оператор и он вначеле { // длинна найдинного оператора больше найденного ранее if (temp_str.length() < op_it->first.length()) { temp_str = op_it->first; } } } // если нашли оператор (temp_str - не пустая строка), то ложим текущий оператор // в список токенов, удаляем оператор из начала лексемы if (!temp_str.empty()) { tokens_ptr_->push_back(Token(temp_str, token.line_, token.column_ + cur_pos_in_lexem, Token::Type_Operator)); cur_pos_in_lexem = temp_str.length(); token.str_ = token.str_.substr(temp_str.length()); } } } else { if (token.type_ != Token::Type_Unknown) { tokens_ptr_->push_back(token); } else { //!fixme add error } } } } }