示例#1
0
std::wstring VdfParser::ResolveFqId(const wchar_t * const id, 
	bool is_type_id, 
	Tokens& tokens) const
{
	vector<wstring> matching_fq_ids;
	assert(_variables);
	wstring search_namespace = _current_namespace;

	for (;;)
	{
		wstring fq_id = search_namespace.empty() ? id : (search_namespace + L"::" + id);
		if (IdExists(fq_id.c_str(), is_type_id))
		{
			matching_fq_ids.push_back(fq_id);
			break;
		}
		else if (search_namespace.empty())
		{
			break;
		}
		else
		{
			search_namespace = OuterNamespace(search_namespace);
		}
	}

	for (auto name_space : _namespace_in_use)
	{
		assert(!name_space.empty());

		wstring fq_id = name_space + L"::" + id;
		if (IdExists(fq_id.c_str(), is_type_id))
		{
			matching_fq_ids.push_back(fq_id);
		}
	}

	if (matching_fq_ids.empty())
	{
		throw CompileError(tokens.GetCurrentToken(), CompileErrorTypeNotFound, wstring(L"Type not found: ") + id);
	}
	else if (matching_fq_ids.size() > 1)
	{
		wstring error_message = L"Ambiguous ID: ";
		error_message += id;
		error_message += L". Could be: \n";
		for (auto fq_id : matching_fq_ids)
		{
			error_message += (fq_id + L"\n");
		}

		throw CompileError(tokens.GetCurrentToken(), CompileErrorAmbiguousId, error_message);
	}

	return matching_fq_ids[0];
}
示例#2
0
bool VdfParser::ProcessStatement(Tokens& tokens)
{
	while (!tokens.AtEnd())
	{
		switch (tokens.GetCurrentToken().type)
		{
        case TokenKeywordBool:
        case TokenKeywordInt:
        case TokenKeywordFloat:
        case TokenKeywordString:
			ProcessSimpleDeclaration(tokens);
			break;
        case TokenId:
            ProcessSimpleDeclaration(tokens);
            break;
        case TokenKeywordArray:
            ProcessArrayDeclaration(tokens, *_variables);
            break;
        case TokenKeywordStruct:
            ProcessStructDeclaration(tokens);
            break;
		case TokenKeywordEnum:
			ProcessEnumDeclaration(tokens);
			break;
		case TokenKeywordNamespace:
			ProcessNamespace(tokens);
			break;
		case TokenKeywordUsing:
			ProcessUsing(tokens);
			break;
        case TokenSemiColon:
            tokens.FinishProcessingStatement();
            break;
		case TokenRightBrace:
			// This function maybe called when the processing iterator is pointing to 
			// the beginning of a tokens, which maybe hosted in a namespace.
			// If current tokens is enclosed in a namespace, then the right brace
			// means the end of namespace.
			if (_current_namespace.empty())
			{
				throw CompileError(tokens.GetCurrentToken(), CompileErrorTypeExpected,
					L"Unexpected \'}\'");
			}
			else
				return true;
        default:
			throw(CompileError(tokens.GetCurrentToken(),
                  CompileErrorTypeExpected, L"Expected one of float, int, string, bool, array, struct."));
		}
	}

	return true;
}
示例#3
0
bool VdfParser::ProcessArrayDeclaration(Tokens& tokens, VariableSpace& variables)
{
    static map<TokenType, int> token_to_array_property{
        {TokenKeywordFloat, VariableFloatArray},
        {TokenKeywordInt, VariableIntArray},
        {TokenKeywordString, VariableStringArray},
        {TokenKeywordBool, VariableBoolArray},
		{TokenId, VariableStructArray},
    };

	tokens.AssertToken(TokenKeywordArray, true);
	tokens.AssertToken(TokenLessThan, true);

	auto type = tokens.GetCurrentToken().type;
	auto element_type_id = tokens.GetCurrentToken().text;
	auto fq_type_id = ResolveFqId(element_type_id.c_str(), true, tokens);

	assert(type == TokenKeywordFloat || type == TokenKeywordInt ||
		   type == TokenKeywordBool || type == TokenKeywordString ||
			type == TokenId);
	tokens.Next();
	tokens.AssertToken(TokenGreaterThan, true);

	auto id = (&variables == _variables.get()) ?
		GetFqId(tokens.GetId().c_str()) : tokens.GetId();

	if (!tokens.IsTokenOfType(TokenSharp, true))
	{
		variables.AddArray(fq_type_id.c_str(), id.c_str(), L"");
	}
	else
	{
		tokens.AssertToken(TokenLessThan, true);
		auto start_index = _wtoi(tokens.GetLiteralValue().c_str());
		tokens.AssertToken(TokenComma, true);
		auto end_index = _wtoi(tokens.GetLiteralValue().c_str());
		tokens.AssertToken(TokenGreaterThan, true);

		for (int i = start_index; i <= end_index; ++i)
		{
			wostringstream output;
			output << id << i;
			auto variable_id = (&variables == _variables.get()) ?
				GetFqId(output.str().c_str()) : output.str();
			variables.AddArray(fq_type_id.c_str(), variable_id.c_str(), L"");
		}
	}
	tokens.AssertToken(TokenSemiColon, true);

	return true;
}
示例#4
0
bool VdfParser::ProcessSimpleDeclaration(Tokens& tokens)
{
    assert(_variables);

	auto type = tokens.GetCurrentToken().type;
    auto type_id = tokens.GetCurrentToken().text;

	assert(type == TokenKeywordFloat || type == TokenKeywordInt ||
           type == TokenKeywordBool || type == TokenKeywordString ||
           type == TokenId);

	tokens.Next();
	auto id = tokens.GetId();
	auto fq_type_id = ResolveFqId(type_id.c_str(), true, tokens);

	if (!tokens.IsTokenOfType(TokenSharp, true))
	{
        _variables->Add(fq_type_id.c_str(), GetFqId(id.c_str()).c_str(), L"");
	}
	else
	{
		tokens.AssertToken(TokenLessThan, true);

		auto start_index = boost::lexical_cast<int>(tokens.GetLiteralValue());
		tokens.AssertToken(TokenComma, true);
		auto end_index = boost::lexical_cast<int>(tokens.GetLiteralValue());
		tokens.AssertToken(TokenGreaterThan, true);

		for (int i = start_index; i <= end_index; ++i)
		{
			wostringstream output;
			output << id << i;
			wstring variable_id = GetFqId(output.str().c_str());
			
            _variables->Add(fq_type_id.c_str(), variable_id.c_str(), L"");
		}
	}
	tokens.AssertToken(TokenSemiColon, true);

	return true;
}
示例#5
0
bool VdfParser::ProcessStructDeclaration(Tokens& tokens)
{
    tokens.AssertToken(TokenKeywordStruct, true);
    auto struct_id = GetFqId(tokens.GetId().c_str());

    tokens.AssertToken(TokenLeftBrace, true);

    VariableSpace struct_variables;
	static std::set<TokenType> s_allowed_types = {
		TokenKeywordBool, TokenKeywordFloat, TokenKeywordInt, TokenKeywordString,
		TokenKeywordArray, TokenId };
    do
    {
        auto& type_token = tokens.GetCurrentToken();
        if (s_allowed_types.find(type_token.type) == s_allowed_types.end())
        {
            throw(CompileError(type_token, CompileErrorTypeExpected,
                               L"Expected either one of float, int, string, bool, array, or a struct name."));
        }

		if (type_token.type == TokenKeywordArray)
		{
			ProcessArrayDeclaration(tokens, struct_variables);
		}
		else
		{
			auto type_id = ResolveFqId(type_token.text.c_str(), true, tokens);
			if (type_token.type == TokenId)
			{
				if (!_variables->TypeExists(type_id.c_str()))
					throw CompileError(type_token, CompileErrorTypeNotFound, L"Type not found.");

				if (type_token.text == struct_id)
					throw CompileError(type_token, CompileErrorNestStruct, L"Nested struct definition not allowed.");

			}

			tokens.Next();
			auto& member_token = tokens.GetCurrentToken();

			if (struct_variables.VariableExists(member_token.text.c_str()))
				throw CompileError(type_token, CompileErrorMemeberExists, L"Duplicated struct member ids.");


			auto prototype = _variables->GetType(type_id.c_str());
			if (prototype == nullptr)
				throw CompileError(type_token, CompileErrorTypeNotFound, L"Type not found.");

			auto member = dynamic_cast<IVariable*>(prototype->Clone());
			assert(member != nullptr);
			member->SetId(member_token.text.c_str());
			struct_variables.Add(member);

			tokens.Next();
			tokens.AssertToken(TokenSemiColon, true);
		}
    } while (!tokens.IsTokenOfType(TokenRightBrace, false));

	tokens.Next();
	tokens.AssertToken(TokenSemiColon, true);

    _variables->AddType(struct_id.c_str(), struct_variables.Variables());

    return true;
}