예제 #1
0
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;
}
예제 #2
0
	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
					}
				}
			}
		}
	}