mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-04-21 03:38:15 +00:00
@@ -0,0 +1,59 @@
|
||||
#include "attribute_entity.h"
|
||||
|
||||
CAttributeEntity::CAttributeEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, bool bReadOnly) :
|
||||
CDeclarationEntity(rptrContext, ptrParent), m_bReadOnly(bReadOnly),
|
||||
m_iteratorReadExceptions(GetReadExceptionVector()), m_iteratorWriteExceptions(GetWriteExceptionVector())
|
||||
{}
|
||||
|
||||
sdv::interface_t CAttributeEntity::GetInterface(sdv::interface_id idInterface)
|
||||
{
|
||||
// Expose interfaces
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::IInterfaceAccess>())
|
||||
return static_cast<sdv::IInterfaceAccess*>(this);
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::idl::IAttributeEntity>())
|
||||
return static_cast<sdv::idl::IAttributeEntity*>(this);
|
||||
return CDeclarationEntity::GetInterface(idInterface);
|
||||
}
|
||||
|
||||
sdv::idl::IEntityIterator* CAttributeEntity::GetReadExceptions()
|
||||
{
|
||||
if (!GetReadExceptionVector().empty()) return &m_iteratorReadExceptions;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sdv::idl::IEntityIterator* CAttributeEntity::GetWriteExceptions()
|
||||
{
|
||||
if (!GetWriteExceptionVector().empty()) return &m_iteratorWriteExceptions;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CAttributeEntity::Process()
|
||||
{
|
||||
CDeclarationEntity::Process();
|
||||
}
|
||||
|
||||
bool CAttributeEntity::SupportArrays() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAttributeEntity::IsReadOnly() const
|
||||
{
|
||||
return m_bReadOnly;
|
||||
}
|
||||
|
||||
bool CAttributeEntity::SupportMultipleDeclarations() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAttributeEntity::SupportRaiseExceptions() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAttributeEntity::SupportSeparateSetGetRaiseExceptions() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
99
sdv_executables/sdv_idl_compiler/entities/attribute_entity.h
Normal file
99
sdv_executables/sdv_idl_compiler/entities/attribute_entity.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#ifndef ATTRIBUTE_ENTITY_H
|
||||
#define ATTRIBUTE_ENTITY_H
|
||||
|
||||
#include "declaration_entity.h"
|
||||
|
||||
/**
|
||||
* @brief The attribute definition of an IDL file.
|
||||
* @details The attribute section of the IDL file defines attribute values.
|
||||
*/
|
||||
class CAttributeEntity : public CDeclarationEntity, public sdv::idl::IAttributeEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
* @param[in] bReadOnly When set, the attribute is defined as readonly.
|
||||
*/
|
||||
CAttributeEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, bool bReadOnly);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CAttributeEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get access to another interface. Overload of sdv::IInterfaceAccess::GetInterface.
|
||||
* @param[in] idInterface The interface id to get access to.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
virtual sdv::interface_t GetInterface(sdv::interface_id idInterface) override;
|
||||
|
||||
/**
|
||||
* @brief Get the list of possible exceptions that might be fired during a read operation. Overload of
|
||||
* sdv::idl::IAttributeEntity::GetReadExceptions.
|
||||
* @return Returns a pointer to the exceptions iterator or NULL when no exceptions were defined.
|
||||
*/
|
||||
virtual sdv::idl::IEntityIterator* GetReadExceptions() override;
|
||||
|
||||
/**
|
||||
* @brief Get the list of possible exceptions that might be fired during a write operation. Overload of
|
||||
* sdv::idl::IAttributeEntity::GetWriteExceptions.
|
||||
* @return Returns a pointer to the exceptions iterator or NULL when no exceptions were defined.
|
||||
*/
|
||||
virtual sdv::idl::IEntityIterator* GetWriteExceptions() override;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns the attribute entity type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_attribute; }
|
||||
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Does the entity support arrays? Overload of CDeclarationEntity::SupportArrays.
|
||||
* @return Returns 'true' when the entity supports assignments; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportArrays() const override;
|
||||
|
||||
/**
|
||||
* @brief Is the entity readonly? Overload of IEntityInfo::IsReadOnly.
|
||||
* @return Returns 'true' when the entity defined as readonly; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsReadOnly() const override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support multiple declarations on one line of code? Overload of
|
||||
* CDeclarationEntity::SupportMultipleDeclarations.
|
||||
* @return Returns 'true' when the entity supports multiple declarations; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportMultipleDeclarations() const override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support raising exceptions? Overload of CDeclarationEntity::SupportRaiseExceptions.
|
||||
* @return Returns 'true' when the entity supports exceptions; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportRaiseExceptions() const override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support separate set/get raising exceptions? Overload of
|
||||
* CDeclarationEntity::SupportSeparateSetGetRaiseExceptions.
|
||||
* @return Returns 'true' when the entity supports separate set/get raise exceptions; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportSeparateSetGetRaiseExceptions() const override;
|
||||
|
||||
private:
|
||||
bool m_bReadOnly = false; ///< When set, the attribute is readonly.
|
||||
CEntityIterator m_iteratorReadExceptions; ///< Exceptions iterator for read exceptions
|
||||
CEntityIterator m_iteratorWriteExceptions; ///< Exceptions iterator for write exceptions
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // !defined(ATTRIBUTE_ENTITY_H)
|
||||
749
sdv_executables/sdv_idl_compiler/entities/declaration_entity.cpp
Normal file
749
sdv_executables/sdv_idl_compiler/entities/declaration_entity.cpp
Normal file
@@ -0,0 +1,749 @@
|
||||
#include "declaration_entity.h"
|
||||
#include "../exception.h"
|
||||
#include "../logger.h"
|
||||
#include "../token.h"
|
||||
#include "../tokenlist.h"
|
||||
#include "../support.h"
|
||||
#include "../lexer.h"
|
||||
#include "../constvariant.inl"
|
||||
#include "../parser.h"
|
||||
#include "struct_entity.h"
|
||||
#include "interface_entity.h"
|
||||
#include "typedef_entity.h"
|
||||
#include "variable_entity.h"
|
||||
#include "attribute_entity.h"
|
||||
#include "operation_entity.h"
|
||||
#include "exception_entity.h"
|
||||
#include "parameter_entity.h"
|
||||
#include "enum_entity.h"
|
||||
#include "union_entity.h"
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
|
||||
CDeclarationEntity::CDeclarationEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent) :
|
||||
CEntity(rptrContext, ptrParent)
|
||||
{}
|
||||
|
||||
CDeclarationEntity::CDeclarationEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent,
|
||||
const CTokenList& rlstTokenList) :
|
||||
CEntity(rptrContext, ptrParent, rlstTokenList)
|
||||
{}
|
||||
|
||||
sdv::interface_t CDeclarationEntity::GetInterface(sdv::interface_id idInterface)
|
||||
{
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::IInterfaceAccess>())
|
||||
return static_cast<sdv::IInterfaceAccess*>(this);
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::idl::IDeclarationEntity>())
|
||||
return static_cast<sdv::idl::IDeclarationEntity*>(this);
|
||||
return CEntity::GetInterface(idInterface);
|
||||
}
|
||||
|
||||
sdv::IInterfaceAccess* CDeclarationEntity::GetDeclarationType() const
|
||||
{
|
||||
return const_cast<CTypeDeclaration*>(&m_typedecl);
|
||||
}
|
||||
|
||||
CEntityPtr CDeclarationEntity::GetTypeEntity() const
|
||||
{
|
||||
return m_typedecl.GetTypeDefinitionEntityPtr();
|
||||
}
|
||||
|
||||
bool CDeclarationEntity::HasArray() const
|
||||
{
|
||||
return m_vecMultiArraySizeTokenList.size() ? true : false;
|
||||
}
|
||||
|
||||
sdv::sequence<sdv::idl::SArrayDimension> CDeclarationEntity::GetArrayDimensions() const
|
||||
{
|
||||
sdv::sequence<sdv::idl::SArrayDimension> seqArrayDimensions;
|
||||
if (!HasArray()) return seqArrayDimensions;
|
||||
|
||||
// Traverse through each array entry
|
||||
std::function<void(const CValueNodePtr& ptrValue)> fnCollectArrayDimensions =
|
||||
[&](const CValueNodePtr& ptrValue)
|
||||
{
|
||||
// Is the value node an array at all?
|
||||
CArrayValueNode* pArrayValue = ptrValue->Get<CArrayValueNode>();
|
||||
if (!pArrayValue) return;
|
||||
|
||||
// Fill the array dimension struct
|
||||
sdv::idl::SArrayDimension sArrayDimension{};
|
||||
sArrayDimension.eType = sdv::idl::SArrayDimension::EDimensionType::bound;
|
||||
if (pArrayValue->IsUnbound())
|
||||
sArrayDimension.eType = sdv::idl::SArrayDimension::EDimensionType::unbound;
|
||||
sArrayDimension.ssExpression = MakeFullScoped(pArrayValue->GetSizeExpression());
|
||||
|
||||
// Store in sequence
|
||||
seqArrayDimensions.push_back(sArrayDimension);
|
||||
|
||||
// Process the next array dimension
|
||||
if (pArrayValue->GetSize() != 0)
|
||||
fnCollectArrayDimensions((*pArrayValue)[0]);
|
||||
};
|
||||
|
||||
// Collect the array dimensions.
|
||||
fnCollectArrayDimensions(ValueRef());
|
||||
|
||||
return seqArrayDimensions;
|
||||
}
|
||||
|
||||
bool CDeclarationEntity::HasAssignment() const
|
||||
{
|
||||
return !m_lstAssignmentTokenList.empty();
|
||||
}
|
||||
|
||||
sdv::u8string CDeclarationEntity::GetAssignment() const
|
||||
{
|
||||
std::stringstream sstreamAssignment;
|
||||
bool bInitial = true;
|
||||
for (const CToken& rToken : m_lstAssignmentTokenList)
|
||||
{
|
||||
if (!bInitial) sstreamAssignment << " ";
|
||||
bInitial = false;
|
||||
sstreamAssignment << static_cast<std::string>(rToken);
|
||||
}
|
||||
return sstreamAssignment.str();
|
||||
}
|
||||
|
||||
void CDeclarationEntity::Process()
|
||||
{
|
||||
CLog log("Processing declaration (preparation)...");
|
||||
|
||||
// Determine whether the comments are preceding the token (either on the same line or the line before).
|
||||
CTokenList lstPreComments = GetPreCommentTokenList();
|
||||
if (!lstPreComments.empty()) SetCommentTokens(lstPreComments);
|
||||
|
||||
// Process the type
|
||||
CTypeDeclaration sTypeDecl = ProcessType();
|
||||
|
||||
// Check for the support of interface and void types
|
||||
if (sTypeDecl.GetBaseType() == sdv::idl::EDeclType::decltype_interface && !SupportInterface())
|
||||
throw CCompileException("The declaration of interfaces is not supported.");
|
||||
if (sTypeDecl.GetBaseType() == sdv::idl::EDeclType::decltype_void && !SupportVoid())
|
||||
throw CCompileException("The use of 'void' as type is not supported.");
|
||||
|
||||
// Preprocess potential array declaration (only for operations).
|
||||
if (GetType() == sdv::idl::EEntityType::type_operation)
|
||||
PreprocessArrayDeclaration();
|
||||
|
||||
// Process the declaration
|
||||
ProcessDeclaration(sTypeDecl);
|
||||
}
|
||||
|
||||
void CDeclarationEntity::ProcessDeclaration(const CTypeDeclaration& rTypeDecl)
|
||||
{
|
||||
// Store the type
|
||||
m_typedecl = rTypeDecl;
|
||||
|
||||
CLog log("Processing declaration...");
|
||||
|
||||
// Expecting an identifier.
|
||||
CToken token = GetToken();
|
||||
if (token.GetType() == ETokenType::token_keyword)
|
||||
{
|
||||
// Keywords as names are allowed if the extension is enabled.
|
||||
if (!GetParserRef().GetEnvironment().ContextDependentNamesExtension())
|
||||
throw CCompileException(token, "The identifier cannot be a reserved keyword.");
|
||||
}
|
||||
else if (token.GetType() != ETokenType::token_identifier)
|
||||
throw CCompileException(token, "Expecting an identifier.");
|
||||
SetName(token);
|
||||
log << "Declaration name '" << GetName() << "'..." << std::endl;
|
||||
|
||||
// Preprocess potential array declaration (not for operations).
|
||||
if (GetType() != sdv::idl::EEntityType::type_operation)
|
||||
PreprocessArrayDeclaration();
|
||||
|
||||
// Further processing...
|
||||
token = GetToken();
|
||||
|
||||
// Requires parameters?
|
||||
if (RequiresParameters())
|
||||
{
|
||||
// Expect a left bracket
|
||||
if (token != "(") throw CCompileException(token, "Expected left bracket '('.");
|
||||
|
||||
log << "Reading parameter list..." << std::endl;
|
||||
PreprocessTokenListVector(m_vecParametersTokenList);
|
||||
|
||||
// Expect a right bracket
|
||||
token = GetToken();
|
||||
if (token != ")")
|
||||
throw CCompileException(token, "Expected right bracket ')'.");
|
||||
|
||||
// Get the next token...
|
||||
token = GetToken();
|
||||
|
||||
// Check for the 'const' keyword. If set, the operation is defined as const-operation.
|
||||
if (token == "const")
|
||||
{
|
||||
SetOperationAsConst();
|
||||
token = GetToken();
|
||||
}
|
||||
}
|
||||
|
||||
// Supports exceptions
|
||||
if (SupportRaiseExceptions())
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// Check for the 'raises' keyword.
|
||||
enum class EExceptType {raises, getraises, setraises, none} eExceptType = EExceptType::none;
|
||||
if (token == "raises")
|
||||
eExceptType = EExceptType::raises;
|
||||
else if (token == "getraises")
|
||||
eExceptType = EExceptType::getraises;
|
||||
else if (token == "setraises")
|
||||
eExceptType = EExceptType::setraises;
|
||||
if (eExceptType == EExceptType::none)
|
||||
break;
|
||||
|
||||
// Check for validity
|
||||
if (!SupportSeparateSetGetRaiseExceptions() && eExceptType == EExceptType::getraises)
|
||||
throw CCompileException(token,
|
||||
"Cannot set a separate 'get-raises' exception list; use the 'raises' keyword instead.");
|
||||
if (!SupportSeparateSetGetRaiseExceptions() && eExceptType == EExceptType::setraises)
|
||||
throw CCompileException(token,
|
||||
"Cannot set a separate 'set-raises' exception list; use the 'raises' keyword instead.");
|
||||
if (SupportSeparateSetGetRaiseExceptions() && eExceptType == EExceptType::raises && IsReadOnly())
|
||||
eExceptType = EExceptType::getraises;
|
||||
if (eExceptType == EExceptType::setraises && IsReadOnly())
|
||||
throw CCompileException(token, "Cannot set a set-raises exception list for a readonly type.");
|
||||
if ((eExceptType == EExceptType::raises) && !m_vecRaisesExceptionsTokenList.empty())
|
||||
throw CCompileException(token, "Multiple definitions of 'raises' exceptions are not allowed.");
|
||||
if ((eExceptType == EExceptType::setraises) && !m_vecSetRaisesExceptionsTokenList.empty())
|
||||
throw CCompileException(token, "Multiple definitions of 'set-raises' exceptions are not allowed.");
|
||||
if ((eExceptType == EExceptType::getraises) && !m_vecGetRaisesExceptionsTokenList.empty())
|
||||
throw CCompileException(token, "Multiple definitions of 'get-raises' exceptions are not allowed.");
|
||||
|
||||
// Expect a left bracket
|
||||
token = GetToken();
|
||||
if (token != "(") throw CCompileException(token, "Expected left bracket '('.");
|
||||
|
||||
// Processes raises exception list.
|
||||
switch (eExceptType)
|
||||
{
|
||||
case EExceptType::raises:
|
||||
log << "Reading 'raises' exception list..." << std::endl;
|
||||
PreprocessTokenListVector(m_vecRaisesExceptionsTokenList);
|
||||
if (m_vecRaisesExceptionsTokenList.empty()) throw CCompileException(token, "Missing exception types.");
|
||||
break;
|
||||
case EExceptType::setraises:
|
||||
log << "Reading 'setraises' exception list..." << std::endl;
|
||||
PreprocessTokenListVector(m_vecSetRaisesExceptionsTokenList);
|
||||
if (m_vecSetRaisesExceptionsTokenList.empty()) throw CCompileException(token, "Missing exception types.");
|
||||
break;
|
||||
case EExceptType::getraises:
|
||||
log << "Reading 'getraises' exception list..." << std::endl;
|
||||
PreprocessTokenListVector(m_vecGetRaisesExceptionsTokenList);
|
||||
if (m_vecGetRaisesExceptionsTokenList.empty()) throw CCompileException(token, "Missing exception types.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Expect a right bracket
|
||||
token = GetToken();
|
||||
if (token != ")")
|
||||
throw CCompileException(token, "Expected right bracket ')'.");
|
||||
|
||||
// Get the next token...
|
||||
token = GetToken();
|
||||
}
|
||||
}
|
||||
|
||||
// Is there an assignment?
|
||||
if (token == "=")
|
||||
{
|
||||
if (!SupportAssignments())
|
||||
throw CCompileException(token, "Assignment operator detected, but type doesn't support assignments.");
|
||||
log << "Declaration assignment detected; storing expression for later processing..." << std::endl;
|
||||
|
||||
// Read the tokens for the assignment expression. Read until ';' or ','; the latter not within an expression
|
||||
// sub-statement.
|
||||
size_t nDepth = 0;
|
||||
log << "Assignment expression:" << std::endl;
|
||||
while(true)
|
||||
{
|
||||
token = GetToken();
|
||||
if (!token)
|
||||
throw CCompileException("Unexpected end of file found; missing ';'.");
|
||||
if (token == ";" || ((token == "," || token == "}") && !nDepth))
|
||||
break;
|
||||
|
||||
log << " " << static_cast<std::string>(token);
|
||||
|
||||
if (token == "{") nDepth++;
|
||||
if (token == "}") nDepth--;
|
||||
m_lstAssignmentTokenList.push_back(token);
|
||||
}
|
||||
log << std::endl;
|
||||
} else
|
||||
{
|
||||
// Does the entity need an assignment?
|
||||
if (RequiresAssignment())
|
||||
throw CCompileException(token, "Expecting an assignment operator.");
|
||||
}
|
||||
|
||||
// Assign any succeeding comments
|
||||
ProcessPostCommentTokenList(token.GetLine());
|
||||
|
||||
// Another declaration?
|
||||
if (token == ",")
|
||||
{
|
||||
if (!SupportMultipleDeclarations())
|
||||
throw CCompileException(token, "Multiple declarations on a single line of code is not supported for this type.");
|
||||
log << "Another declaration of the same type..." << std::endl;
|
||||
|
||||
// Peek for ending the definition
|
||||
if (DoNotEnfoceNextDeclarationAfterComma() && PeekToken() == "}") return;
|
||||
|
||||
// Create another declaration
|
||||
CDeclarationEntity* pTypeEntity = nullptr;
|
||||
if (Get<CVariableEntity>()) pTypeEntity = CreateChild<CVariableEntity>(token.GetContext(), GetParentEntity().get(), IsReadOnly(), false)->Get<CDeclarationEntity>();
|
||||
else if (Get<CEnumEntry>()) pTypeEntity = CreateChild<CEnumEntry>(token.GetContext(), GetParentEntity().get())->Get<CDeclarationEntity>();
|
||||
else if (Get<CAttributeEntity>()) pTypeEntity = CreateChild<CAttributeEntity>(token.GetContext(), GetParentEntity().get(), IsReadOnly())->Get<CDeclarationEntity>();
|
||||
else
|
||||
throw CCompileException(token, "Unexpected token ','.");
|
||||
if (!pTypeEntity) throw CCompileException(token, "Internal error: failed to create another declaration entity.");
|
||||
|
||||
// Set the new begin position of the declaration
|
||||
CToken tokenTemp = PeekToken();
|
||||
pTypeEntity->SetBeginPosition(tokenTemp.GetLine(), tokenTemp.GetCol());
|
||||
|
||||
// Use the same type for the processing.
|
||||
pTypeEntity->ProcessDeclaration(m_typedecl);
|
||||
|
||||
// Done.
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the end position of the declaration
|
||||
SetEndPosition(token.GetLine(), token.GetCol());
|
||||
|
||||
// Reinsert the token
|
||||
PrependToken(token);
|
||||
}
|
||||
|
||||
void CDeclarationEntity::PreprocessArrayDeclaration()
|
||||
{
|
||||
CLog log("Checking for array...");
|
||||
|
||||
// For each array dimension, add a tokenlist to the m_vecMultiArraySizeTokenList variable.
|
||||
bool bIsArray = false;
|
||||
while (true)
|
||||
{
|
||||
// Check for an array
|
||||
CToken token = GetToken();
|
||||
if (token != "[")
|
||||
{
|
||||
PrependToken(token);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!SupportArrays())
|
||||
throw CCompileException(token, "Unexpected token '['.");
|
||||
|
||||
log << "Array detected; storing expression for later processing..." << std::endl;
|
||||
log << "Array expression: [";
|
||||
|
||||
// Check for multidimensional arrays
|
||||
if (bIsArray && !GetParserRef().GetEnvironment().MultiDimArrayExtension())
|
||||
throw CCompileException(token, "Multi-dimentsional arrays are not allowed. Unexpected token '['.");
|
||||
bIsArray = true;
|
||||
|
||||
// Read the tokens for the array size. Read until ']'.
|
||||
CTokenList lstArraySize;
|
||||
size_t nDepth = 1;
|
||||
while (true)
|
||||
{
|
||||
token = GetToken();
|
||||
log << " " << static_cast<std::string>(token);
|
||||
if (!token)
|
||||
throw CCompileException("Unexpected end of file found; missing ']'.");
|
||||
if (token == ";")
|
||||
throw CCompileException("Unexpected end of declaration; missing ']'.");
|
||||
if (token == "[")
|
||||
nDepth++;
|
||||
if (token == "]")
|
||||
{
|
||||
nDepth--;
|
||||
if (!nDepth)
|
||||
{
|
||||
m_vecMultiArraySizeTokenList.push_back(std::move(lstArraySize));
|
||||
break;
|
||||
}
|
||||
}
|
||||
lstArraySize.push_back(token);
|
||||
}
|
||||
log << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void CDeclarationEntity::PreprocessTokenListVector(std::vector<CTokenList>& rvecTokenList)
|
||||
{
|
||||
CLog log("Checking for comma separated token lists...");
|
||||
|
||||
CTokenList lstTokens;
|
||||
bool bInitial = true;
|
||||
while (true)
|
||||
{
|
||||
// Check for array index (allowed in certain situations)
|
||||
CToken token = GetToken();
|
||||
if (token == "[")
|
||||
{
|
||||
do
|
||||
{
|
||||
lstTokens.push_back(token);
|
||||
token = GetToken();
|
||||
} while (token && token != "]");
|
||||
lstTokens.push_back(token);
|
||||
token = GetToken();
|
||||
}
|
||||
|
||||
// Check for template parameters
|
||||
if (token == "<")
|
||||
{
|
||||
size_t nDepth = 0;
|
||||
do
|
||||
{
|
||||
if (token == "<") nDepth++;
|
||||
if (token == ">>") // Special case when closing nested templates.
|
||||
{
|
||||
token = CToken(">", ETokenType::token_operator);
|
||||
PrependToken(token);
|
||||
}
|
||||
if (token == ">") nDepth--;
|
||||
lstTokens.push_back(token);
|
||||
token = GetToken();
|
||||
} while (token && static_cast<bool>(nDepth));
|
||||
lstTokens.push_back(token);
|
||||
token = GetToken();
|
||||
}
|
||||
|
||||
// Check for end of processing
|
||||
if (!token || token == "]" || token == ")" || token == ";")
|
||||
{
|
||||
if (!bInitial)
|
||||
rvecTokenList.push_back(std::move(lstTokens));
|
||||
PrependToken(token);
|
||||
break;
|
||||
}
|
||||
|
||||
if (bInitial)
|
||||
log << "Comma separated list detected: ";
|
||||
bInitial = false;
|
||||
|
||||
log << " " << static_cast<std::string>(token);
|
||||
|
||||
// Check for comma separator
|
||||
if (token == ",")
|
||||
{
|
||||
rvecTokenList.push_back(std::move(lstTokens));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the token to the token list
|
||||
lstTokens.push_back(token);
|
||||
}
|
||||
if (rvecTokenList.empty())
|
||||
log << "No comma separated list detected..." << std::endl;
|
||||
else
|
||||
log << std::endl;
|
||||
}
|
||||
|
||||
void CDeclarationEntity::PostProcess()
|
||||
{
|
||||
CLog log("Post process declaration...");
|
||||
|
||||
// Check the assignment processing progression state...
|
||||
switch (m_eProcAssState)
|
||||
{
|
||||
case EProcessAssignmentProgression::unprocessed:
|
||||
// Not processed yet, start processing...
|
||||
m_eProcAssState = EProcessAssignmentProgression::currently_processing;
|
||||
break;
|
||||
case EProcessAssignmentProgression::currently_processing:
|
||||
log << "Post processing declaration assignment takes place already; cannot do this more than once at the same time..."
|
||||
<< std::endl;
|
||||
// Alarm, circular references... cannot continue.
|
||||
throw CCompileException("Circular referencing entity.");
|
||||
case EProcessAssignmentProgression::processed:
|
||||
default:
|
||||
// Already done...
|
||||
log << "Post processing declaration was done before; no need to repeat..." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// The parent value is the value of the parent entity, if there is any value.
|
||||
CValueNodePtr ptrValueParent = GetParentEntity() ? GetParentEntity()->ValueRef() : nullptr;
|
||||
if (ptrValueParent)
|
||||
log << "The parent entity '" << GetParentEntity()->GetName() << "' has a value node..." << std::endl;
|
||||
else
|
||||
log << "No parent entity or no value node assigned to the parent entity..." << std::endl;
|
||||
|
||||
// Create a value at each bottom leaf of a multi-dimensional array.
|
||||
std::function<void(CValueNodePtr&, const CValueNodePtr, std::function<CValueNodePtr(const CValueNodePtr)>)> fnCreateAtBottomLeaf =
|
||||
[&](CValueNodePtr& rptrValue, const CValueNodePtr& rptrValueParent, std::function<CValueNodePtr(const CValueNodePtr)> fnCreate)
|
||||
{
|
||||
// Check for an array value
|
||||
CArrayValueNode* psArrayValue = dynamic_cast<CArrayValueNode*>(rptrValue.get());
|
||||
|
||||
// If there is an array value, call the function once more for each leaf.
|
||||
if (psArrayValue)
|
||||
{
|
||||
for (size_t nIndex = 0; nIndex < psArrayValue->GetSize(); nIndex++)
|
||||
fnCreateAtBottomLeaf((*psArrayValue)[nIndex], rptrValue, fnCreate);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new element...
|
||||
rptrValue = fnCreate(rptrValueParent);
|
||||
};
|
||||
|
||||
// Process parameters - since parameters might depend on other parameters, do the processing in two steps.
|
||||
size_t nIndex = 1;
|
||||
for (const CTokenList& rlstTokenList : m_vecParametersTokenList)
|
||||
{
|
||||
log << "Processing parameter #" << nIndex++ << std::endl;
|
||||
|
||||
CEntityPtr ptrEntity = std::make_shared<CParameterEntity>(GetContext(), shared_from_this(), rlstTokenList);
|
||||
ptrEntity->Process();
|
||||
|
||||
m_vecParameters.push_back(ptrEntity);
|
||||
}
|
||||
for (CEntityPtr& rptrParameter : m_vecParameters)
|
||||
rptrParameter->Get<CParameterEntity>()->PostProcess();
|
||||
|
||||
// Build array tree
|
||||
if (m_vecMultiArraySizeTokenList.empty()) log << "No array processing needed..." << std::endl;
|
||||
else if (m_vecMultiArraySizeTokenList.size() == 1) log << "Single-dimensional array processing needed..." << std::endl;
|
||||
else log << "Multi-dimensional array processing needed..." << std::endl;
|
||||
for (const CTokenList& rlstArrayExpression : m_vecMultiArraySizeTokenList)
|
||||
{
|
||||
std::pair<CConstVariant, bool> prArraySize = {0, false};
|
||||
log << "Start processing array dimension..." << std::endl;
|
||||
|
||||
// Empty expression indicates retrieving the size from the assignment.
|
||||
if (!rlstArrayExpression.empty())
|
||||
{
|
||||
log << "Calculate the array size..." << std::endl;
|
||||
prArraySize = ProcessNumericExpression(rlstArrayExpression);
|
||||
|
||||
// Is the array size dynamic?
|
||||
if (prArraySize.second)
|
||||
throw CCompileException(*rlstArrayExpression.begin(), "Cannot use non-const variable for the array size.");
|
||||
log << "The array has " << prArraySize.first.Get<uint32_t>() << " elements..." << std::endl;
|
||||
|
||||
// Check whether the size is integral
|
||||
if (!prArraySize.first.IsIntegral())
|
||||
throw CCompileException(*rlstArrayExpression.begin(), "Only integral data types are supported for the array size.");
|
||||
if ((prArraySize.first < CConstVariant(0)).Get<bool>())
|
||||
throw CCompileException(*rlstArrayExpression.begin(), "Invalid array size.");
|
||||
} else
|
||||
{
|
||||
log << "Array is defined as unbound array retrieving the size from the variable assignment..." << std::endl;
|
||||
|
||||
// Unbound arrays are not possible for writable variables. Exception are operations, attributes and parameters of local
|
||||
// interfaces.
|
||||
bool bError = true;
|
||||
switch (GetType())
|
||||
{
|
||||
case sdv::idl::EEntityType::type_typedef:
|
||||
bError = false;
|
||||
break;
|
||||
case sdv::idl::EEntityType::type_variable:
|
||||
// When not read-only, this is an error.
|
||||
if (IsReadOnly()) bError = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (bError)
|
||||
throw CCompileException("Retrieving the size of the array through its assignment is"
|
||||
" only possible with const declarations and typedefs.");
|
||||
}
|
||||
// The array creation function
|
||||
auto fnCreateArray = [&, this](const CValueNodePtr& rptrValueParent) -> CValueNodePtr
|
||||
{
|
||||
std::shared_ptr<CArrayValueNode> ptrArrayValue = std::make_shared<CArrayValueNode>(shared_from_this(), rptrValueParent);
|
||||
if (rlstArrayExpression.empty())
|
||||
ptrArrayValue->SetFixedSizeUnbound();
|
||||
else if (prArraySize.second)
|
||||
ptrArrayValue->SetDynamicSize(prArraySize.first.Get<size_t>(), rlstArrayExpression);
|
||||
else
|
||||
ptrArrayValue->SetFixedSize(prArraySize.first.Get<size_t>(), rlstArrayExpression);
|
||||
return ptrArrayValue;
|
||||
};
|
||||
|
||||
// Create the array value at the bottom leaf.
|
||||
fnCreateAtBottomLeaf(ValueRef(), ptrValueParent, fnCreateArray);
|
||||
|
||||
log << "Finalized processing array dimension..." << std::endl;
|
||||
}
|
||||
|
||||
// Add the values of the type.
|
||||
if (m_vecMultiArraySizeTokenList.size() == 0)
|
||||
log << "Copy the existing type value tree or create a declaration value node for this assignment..." << std::endl;
|
||||
else
|
||||
log << "For each array element, copy the existing type value tree or create a"
|
||||
" declaration value node for this assignment..." << std::endl;
|
||||
auto fnCreateTypeValues = [&, this](const CValueNodePtr& rptrValueParent) -> CValueNodePtr
|
||||
{
|
||||
if (m_typedecl.GetTypeDefinitionEntityPtr())
|
||||
{
|
||||
// In case the original type was not processed yet, do so now.
|
||||
CDeclarationEntity* pOriginalType = m_typedecl.GetTypeDefinitionEntityPtr()->Get<CDeclarationEntity>();
|
||||
if (pOriginalType) pOriginalType->PostProcess();
|
||||
|
||||
// Copy the existing entity of the type... this contains all the default assignments already...
|
||||
log << "Copy type value tree..." << std::endl;
|
||||
CValueNodePtr ptrValue = m_typedecl.GetTypeDefinitionEntityPtr()->ValueRef();
|
||||
if (ptrValue)
|
||||
return ptrValue->CreateCopy(shared_from_this(), rptrValueParent);
|
||||
else
|
||||
{
|
||||
if (pOriginalType)
|
||||
throw CCompileException("Internal error: value tree must be available for '", GetName(), "'.");
|
||||
log << "No value tree present; nothing to copy..." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log << "Create declaration value node..." << std::endl;
|
||||
return std::make_shared<CSimpleTypeValueNode>(shared_from_this(), ptrValueParent);
|
||||
}
|
||||
};
|
||||
fnCreateAtBottomLeaf(ValueRef(), ptrValueParent, fnCreateTypeValues);
|
||||
|
||||
// If this is a variable declaration, add the value as part of the parent tree
|
||||
if (CanSupportComplexTypeAssignments() && ptrValueParent)
|
||||
{
|
||||
log << "The entity value tree is part of the value tree of the parent node..." << std::endl;
|
||||
ptrValueParent->AddChild(ValueRef());
|
||||
}
|
||||
|
||||
// Add the assignment.
|
||||
if (!m_lstAssignmentTokenList.empty())
|
||||
{
|
||||
log << "Assignment was available, process the assignment..." << std::endl;
|
||||
if (!SupportAssignments())
|
||||
throw CCompileException(*m_lstAssignmentTokenList.begin(), "Type definitions cannot be assigned any values.");
|
||||
ValueRef()->ProcessValueAssignment(m_lstAssignmentTokenList);
|
||||
} else
|
||||
{
|
||||
// Does the entity need an assignment?
|
||||
if (RequiresAssignment())
|
||||
throw CCompileException("Expecting an assignment operator for '", GetName(), "'.");
|
||||
}
|
||||
|
||||
// Build raises exception lists
|
||||
for (const CTokenList& rlstTokenList : m_vecRaisesExceptionsTokenList)
|
||||
{
|
||||
log << "Processing raising exception..." << std::endl;
|
||||
std::pair<std::string, CEntityPtr> prBase = ProcessScopedName(rlstTokenList);
|
||||
if (prBase.first.empty() || !prBase.second || !prBase.second->Get<CExceptionEntity>())
|
||||
throw CCompileException("Exception definition not found.");
|
||||
if (SupportSeparateSetGetRaiseExceptions())
|
||||
{
|
||||
m_vecGetRaisesExceptions.push_back(prBase.second);
|
||||
m_vecSetRaisesExceptions.push_back(prBase.second);
|
||||
} else
|
||||
m_vecRaisesExceptions.push_back(prBase.second);
|
||||
log << "Entity could raise exception on operation/attribute: " << prBase.first << std::endl;
|
||||
}
|
||||
for (const CTokenList& rlstTokenList : m_vecSetRaisesExceptionsTokenList)
|
||||
{
|
||||
log << "Processing set-raising exception..." << std::endl;
|
||||
std::pair<std::string, CEntityPtr> prBase = ProcessScopedName(rlstTokenList);
|
||||
if (prBase.first.empty() || !prBase.second || !prBase.second->Get<CExceptionEntity>())
|
||||
throw CCompileException("Exception definition not found.");
|
||||
m_vecSetRaisesExceptions.push_back(prBase.second);
|
||||
log << "Entity could raise exception on set attribute: " << prBase.first << std::endl;
|
||||
}
|
||||
for (const CTokenList& rlstTokenList : m_vecGetRaisesExceptionsTokenList)
|
||||
{
|
||||
log << "Processing get-raising exception..." << std::endl;
|
||||
std::pair<std::string, CEntityPtr> prBase = ProcessScopedName(rlstTokenList);
|
||||
if (prBase.first.empty() || !prBase.second || !prBase.second->Get<CExceptionEntity>())
|
||||
throw CCompileException("Exception definition not found.");
|
||||
m_vecGetRaisesExceptions.push_back(prBase.second);
|
||||
log << "Entity could raise exception on get attribute: " << prBase.first << std::endl;
|
||||
}
|
||||
|
||||
// Processing is finalized...
|
||||
m_eProcAssState = EProcessAssignmentProgression::processed;
|
||||
}
|
||||
|
||||
bool CDeclarationEntity::RequiresAssignment() const
|
||||
{
|
||||
if (!ValueRef()) return false; // No value assigned yet...
|
||||
|
||||
// If the type has an unbound array in its value, it requires assignment to determine the size of the type.
|
||||
CValueNodePtr ptrValue = ValueRef();
|
||||
while (ptrValue)
|
||||
{
|
||||
if (ptrValue->IsArray() && ptrValue->IsUnbound())
|
||||
return true;
|
||||
ptrValue = ptrValue->GetParentNode();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CDeclarationEntity::CalcHash(CHashObject& rHash) const
|
||||
{
|
||||
// Add the type
|
||||
if (m_typedecl.GetTypeDefinitionEntityPtr())
|
||||
m_typedecl.GetTypeDefinitionEntityPtr()->CalcHash(rHash);
|
||||
else
|
||||
rHash << m_typedecl.GetTypeString();
|
||||
|
||||
// Add base entity
|
||||
CEntity::CalcHash(rHash);
|
||||
|
||||
// Add array dimensions
|
||||
sdv::sequence<sdv::idl::SArrayDimension> seqArray = GetArrayDimensions();
|
||||
for (const sdv::idl::SArrayDimension& rsDimentation : seqArray)
|
||||
{
|
||||
rHash << "[";
|
||||
if (!rsDimentation.ssExpression.empty())
|
||||
rHash << rsDimentation.ssExpression;
|
||||
rHash << "]";
|
||||
}
|
||||
|
||||
// Get the assignment
|
||||
std::string ssAssignment = GetAssignment();
|
||||
if (!ssAssignment.empty()) rHash << ssAssignment;
|
||||
|
||||
// Add parameters
|
||||
for (const CEntityPtr& rptrEntity : m_vecParameters)
|
||||
rptrEntity->CalcHash(rHash);
|
||||
|
||||
// Add exceptions
|
||||
for (const CEntityPtr& rptrEntity : m_vecRaisesExceptions)
|
||||
{
|
||||
rHash << "raises";
|
||||
rptrEntity->CalcHash(rHash);
|
||||
}
|
||||
|
||||
// Add get-exceptions
|
||||
for (const CEntityPtr& rptrEntity : m_vecGetRaisesExceptions)
|
||||
{
|
||||
rHash << "get_raises";
|
||||
rptrEntity->CalcHash(rHash);
|
||||
}
|
||||
|
||||
// Add set-exceptions
|
||||
for (const CEntityPtr& rptrEntity : m_vecSetRaisesExceptions)
|
||||
{
|
||||
rHash << "set_raises";
|
||||
rptrEntity->CalcHash(rHash);
|
||||
}
|
||||
|
||||
// Add whether it is readonly
|
||||
if (IsReadOnly())
|
||||
rHash << "const";
|
||||
}
|
||||
|
||||
372
sdv_executables/sdv_idl_compiler/entities/declaration_entity.h
Normal file
372
sdv_executables/sdv_idl_compiler/entities/declaration_entity.h
Normal file
@@ -0,0 +1,372 @@
|
||||
#ifndef BASIC_TYPE_ENTITY_H
|
||||
#define BASIC_TYPE_ENTITY_H
|
||||
|
||||
#include "entity_base.h"
|
||||
#include "entity_value.h"
|
||||
#include "../constvariant.h"
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @brief The base for declaration entity definitions within an IDL file (declarations, typedefs, attributes, operations,
|
||||
* parameters, case declarations, enum entries).
|
||||
* @details The declaration entity definitions all have a similar setup with small differences in detail. Consider the following
|
||||
* structures:
|
||||
* @code
|
||||
* <type> <name> = <value>
|
||||
* const <type> <name> = <value>
|
||||
* readonly attribute <name>
|
||||
* <operation_type> <operation_name>(<parameter_type> <parameter_name>) const
|
||||
* @endcode
|
||||
* The following generalized structure applies to all declaration structures:
|
||||
* @code
|
||||
* prefix type name
|
||||
* prefix type name = value
|
||||
* prefix type name(parameters) postfix
|
||||
* @endcode
|
||||
* The first statement is a declaration. The second statement is a declaration with an assignment. The last statement represents
|
||||
* an operation.
|
||||
* The prefix is used to provide a specific interpretation to the declaration (in, out, inout, const, attribute, readonly,
|
||||
* typedef, struct, union, enum).
|
||||
* The type defines the type the declaration represents (either a system type or a typedefed type - scoped name).
|
||||
* The name is the defined name o the declaration.
|
||||
* The value is the expression used for the assignment.
|
||||
* The parameters are a list of zero or more declaration statements.
|
||||
* The postfix is used to provide a specific interpretation to the declaration (const).
|
||||
* Some declarations might start as a complex type (e.g. struct, union, enum). The might contain the type definition as well as
|
||||
* the declaration. For example:
|
||||
* @code
|
||||
* struct <def_name> { <definition> } <decl_name>
|
||||
* struct { <definition> } <decl_name>
|
||||
* @endcode
|
||||
* In the first statement, the struct is defined and declared in one statement. In the second statement, an anonymous struct is
|
||||
* defined and declared in one statement.
|
||||
* Multiple declarations are possible for many types. The declarations are separated by a comma and follow the same rules as a
|
||||
* single declaration starting at the <name>.
|
||||
* @code
|
||||
* <type> <name_1> = <value_1>, <name_2> = <value_2>, <name_3>, <name_4> = <value_4>
|
||||
* @endcode
|
||||
*/
|
||||
class CDeclarationEntity : public CEntity, public sdv::idl::IDeclarationEntity
|
||||
{
|
||||
friend CSimpleTypeValueNode;
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
*/
|
||||
CDeclarationEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Constructor using the provided token-list to process the code.
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
* @param[in] rlstTokenList Reference to the token list holding the tokens to process.
|
||||
*/
|
||||
CDeclarationEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, const CTokenList& rlstTokenList);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CDeclarationEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get access to another interface. Overload of sdv::IInterfaceAccess::GetInterface.
|
||||
* @param[in] idInterface The interface id to get access to.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
virtual sdv::interface_t GetInterface(sdv::interface_id idInterface) override;
|
||||
|
||||
/**
|
||||
* @brief Get declaration type. Overload of sdv::idl::IDeclarationEntity::GetDeclarationType.
|
||||
* @return Interface to the declaration type object.
|
||||
*/
|
||||
virtual sdv::IInterfaceAccess* GetDeclarationType() const override;
|
||||
|
||||
/**
|
||||
* @brief Is array? Overload of sdv::idl::IDeclarationEntity::HasArray/HasDynamicArray.
|
||||
* @return Retrurns whether the declaration reqpresents an array.
|
||||
*/
|
||||
virtual bool HasArray() const override;
|
||||
|
||||
/**
|
||||
* @brief Get the array dimensions (if there are any). Overload of IDeclarationEntity::GetDimensionCount.
|
||||
* @return Smart pointer to the sequence of array dimensions.
|
||||
*/
|
||||
virtual sdv::sequence<sdv::idl::SArrayDimension> GetArrayDimensions() const override;
|
||||
|
||||
/**
|
||||
* @brief Has assignment? Overload of sdv::idl::IDeclarationEntity::HasAssignment.
|
||||
* @return Returns whether the declaration has an assignment.
|
||||
*/
|
||||
virtual bool HasAssignment() const override;
|
||||
|
||||
/**
|
||||
* @brief Get assignment string. Overload of sdv::idl::IDeclarationEntity::GetAssignment.
|
||||
* @details The assignment can be an algebraic expression composed from constants and variables. If the assignment is an array,
|
||||
* the expression is composed like this: {{expr1},{expr2},{expr...}}
|
||||
* @return On success, returns the assignment string object or an empty string when no assignment is available.
|
||||
*/
|
||||
virtual sdv::u8string GetAssignment() const override;
|
||||
|
||||
/**
|
||||
* @brief Get the base type of the entity.
|
||||
* @return Returns the base type.
|
||||
*/
|
||||
virtual sdv::idl::EDeclType GetBaseType() const { return m_typedecl.GetBaseType(); }
|
||||
|
||||
/**
|
||||
* @brief Get the type entity if the type is not a system type.
|
||||
* @details Complex types (struct, enum, union) and type definitions are based on a type entity.
|
||||
* @return Returns a pointer to the type entity if available.
|
||||
*/
|
||||
CEntityPtr GetTypeEntity() const;
|
||||
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Process a declaration.
|
||||
* @details The processing of a declaration is done through several steps: processing the declaration type, processing the
|
||||
* declaration identifier, processing (multi-dimensional) arrays, processing assignments, processing the next declaration
|
||||
* identifier and so on.
|
||||
* The following statement are examples:
|
||||
* @code
|
||||
* <type> <identifier>; // No assignment, one declaration
|
||||
* <type> <identifier>, <identifier>; // No assignment, multiple declarations
|
||||
* <type> <identifier>=<expression>; // One definition (declaration with assignment)
|
||||
* <type> <identifier>=<expressoin>, <identifier>=<expression>; // Multiple definitions
|
||||
* <type> <identifier>=<expression>, <identifier>; // Mixed expression, definition
|
||||
* <type> <identifier>[]={<expression>, <expression>}; // Array definition
|
||||
* <type> <identifier>[<expression>]; // Array declaration
|
||||
* <type> <identifier>[<expression>]={<expression>, <expression>}; // Array definition
|
||||
* struct <type> <identifier>; // Struct declaration with explicit struct keyword
|
||||
* struct <type> <identifier>={<expression>, <expression>}; // Struct declaration with assignment
|
||||
* union <type> <identifier>; // Union declaration with explicit union keyword
|
||||
* enum <type> <identifier>; // Enum declaration with explicit enum keyword
|
||||
* enum <type> <identifier>=<exppression>; // Enum definition with explicit enum keyword
|
||||
* @endcode
|
||||
* The 'type' can be a system type (short, int64, float) or a scoped type definition (MyType, \::MyModule\::MyType). Without
|
||||
* assignment the type can be 'struct' or 'union', with or without the 'struct' and 'union' type identification (not allowed
|
||||
* for const entities, which need an assignment).
|
||||
* The 'identifier' is the unique name for the declaration. This name must be case-insensitive unique within the current
|
||||
* scope. The identifier can be followed by square-brackets indicating an array. The size of the array can either be retrieved
|
||||
* through the assignment or through the expression. If both an assignment and an expression are available, they must match.
|
||||
* The array expression must be of an integral type and is not allowed to become negative. Furthermore, it can be created
|
||||
* through a mathematical expression existing of constants and/or when not defined to be a constant entity, through
|
||||
* declarations made before (this deviates to C/C++, where dynamic arrays are not allowed). In case of a dynamic array, an
|
||||
* assignment is not supported.
|
||||
* The assignment 'expression' defines a mathematical expression existing of constants and/or when not defined to be a
|
||||
* constant entity, through declarations made before.
|
||||
* @remarks Array size expressions and assignment expressions are stored as tokenlists to be processed by the
|
||||
* ProcessValueAssignment function.
|
||||
* @param[in] rTypeDecl Reference to the type identifier (can be a system type as well as a scoped name to a previously
|
||||
* defined type).
|
||||
*/
|
||||
void ProcessDeclaration(const CTypeDeclaration& rTypeDecl);
|
||||
|
||||
/**
|
||||
* @brief Preprocess the multi-dimensional array declaration.
|
||||
* @details Preprocess the potential multi-dimensional array declaration by detecting square brackets and storing the tokens
|
||||
* between the brackets. The tokens for each dimension are placed in the m_vecMultiArraySizeTokenList vector.
|
||||
*/
|
||||
void PreprocessArrayDeclaration();
|
||||
|
||||
/**
|
||||
* @brief Preprocess a list of comma separated declarations.
|
||||
* @details Preprocess a list of tokens separated by the comma ',' separator and place the tokens in the provided vector. The
|
||||
* processing is continued until a square bracket ']' or normal bracket ')' or no token exists any more.
|
||||
* @param[in] rvecTokenList Reference to the vector containing the token lists to be filled.
|
||||
*/
|
||||
void PreprocessTokenListVector(std::vector<CTokenList>& rvecTokenList);
|
||||
|
||||
/**
|
||||
* @brief Postprocess the token lists that where read in the preprocess functions.
|
||||
* @pre SupportAssignments returns true and at least m_vecMultiArraySizeTokenList or m_lstAssignmentTokenList is filled.
|
||||
* @details For typedef, const and declaration entities, create the value structure containing the arrays and the values of
|
||||
* the type entity. For const and declaration entities, fill the value structure using the assignment stored in the assignment
|
||||
* expression token list. For attributes and operations build the raising exception lists. For the operations process the
|
||||
* parameter list.
|
||||
*/
|
||||
void PostProcess();
|
||||
|
||||
/**
|
||||
* @brief Does the entity support assignments (const and variable declarations do, others don't)?
|
||||
* @details Determines whether the entity supports assignments. Default value is 'false'.
|
||||
* @return Returns 'true' when the entity supports assignments; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportAssignments() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity require an assignment (const declarations do)?
|
||||
* @details Determines whether the entity requires an assignment. Default value is is based on the presence of an unbound
|
||||
* value in the type.
|
||||
* @return Returns 'true' when the entity requires an assignment; 'false' otherwise.
|
||||
*/
|
||||
virtual bool RequiresAssignment() const;
|
||||
|
||||
/**
|
||||
* @brief Can the entity be used for assignments of complex types (variable declarations do)?
|
||||
* @details Returns whether the entity is defined to be usable for complex type assignments. Default value is 'false'.
|
||||
* @return Returns 'true' when the entity defined as declaration; 'false' otherwise.
|
||||
*/
|
||||
virtual bool CanSupportComplexTypeAssignments() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support arrays (const and variable declarations, as well as typedefs and attributes do)?
|
||||
* @details Determines whether the entity supports arrays. Default value is 'false'.
|
||||
* @return Returns 'true' when the entity supports assignments; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportArrays() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Is the entity readonly (variable declarations and writable attributes aren't)? Overload of
|
||||
* IDeclarationEntity::IsReadOnly.
|
||||
* @details Returns whether the entity is readonly by design or whether it is defined readonly by the code. Default value is
|
||||
* 'true'.
|
||||
* @return Returns 'true' when the entity defined as readonly; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsReadOnly() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Is the entity transparent when used in a struct? Overload of IDeclarationEntity::IsAnonymous.
|
||||
* @details Returns whether the entity is anonymous when used in a struct/union (unnamed and not declared). This allows its
|
||||
* members to appear directly as members within the struct. Default value is 'false'.
|
||||
* @return Returns 'true' when the entity defined as anonymous; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsAnonymous() const override { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support multiple declarations on one line of code (const and var declarations and attributes do)?
|
||||
* @details Returns whether the entity supports multiple declarations separated by a comma ','. Default value is 'false'.
|
||||
* @return Returns 'true' when the entity supports multiple declarations; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportMultipleDeclarations() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Do not enforce next declaration after comma (enums do)?
|
||||
* @pre SupportMultipleDeclarations needs to be supported.
|
||||
* @details Returns whether the entity supports ending the definition after a comma ','. Default value is 'false'.
|
||||
* @return Returns 'true' when not enforcing the next declaration; 'false' otherwise.
|
||||
*/
|
||||
virtual bool DoNotEnfoceNextDeclarationAfterComma() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support raising exceptions (attributes and operations do)?
|
||||
* @details Returns whether the entity supports exceptions (defined through the keywords: raises, getraises and setraises).
|
||||
* Default value is 'false'.
|
||||
* @return Returns 'true' when the entity supports exceptions; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportRaiseExceptions() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support separate set/get raising exceptions (only attributes do)?
|
||||
* @details Returns whether the entity supports exceptions (defined through the keywords: getraises and setraises).
|
||||
* Default value is 'false'.
|
||||
* @return Returns 'true' when the entity supports separate set/get raise exceptions; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportSeparateSetGetRaiseExceptions() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support an interface as base type (non-const variables, operations and parameters do)?
|
||||
* @details Returns whether the entity supports the an interface as base type base type. Default value is 'false'.
|
||||
* @return Returns 'true' when the entity supports interfaces as base type; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportInterface() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support 'void' as base type (operations do)?
|
||||
* @details Returns whether the entity supports the 'void' base type. Default value is 'false'.
|
||||
* @return Returns 'true' when the entity supports void as base type; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportVoid() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity require parameters (operations do)?
|
||||
* @details Returns whether the entity requires parameters. Default value is 'false'.
|
||||
* @return Returns 'true' when the entity requires parameters; 'false' otherwise.
|
||||
*/
|
||||
virtual bool RequiresParameters() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Set operation as const (operations only).
|
||||
* @details If the declaration requires parameters, the declaration is checked for being defined as const operation. If so,
|
||||
* this function is called. Default implementation doesn't do anything.
|
||||
* @pre Only called when RequiresParameters is true and the declaration is defined as const.
|
||||
*/
|
||||
virtual void SetOperationAsConst() {}
|
||||
|
||||
/**
|
||||
* @brief Calculate the hash of this entity and all encapsulated entities. Overload of CBaseEntity::CalcHash.
|
||||
* @param[in, out] rHash Hash object to be filled with data.
|
||||
*/
|
||||
virtual void CalcHash(CHashObject& rHash) const override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Get parameter vector.
|
||||
* @return Returns the vector with the parameter entities.
|
||||
*/
|
||||
CEntityVector& GetParamVector() { return m_vecParameters; }
|
||||
|
||||
/**
|
||||
* @brief Get parameter vector.
|
||||
* @return Returns the vector with the parameter entities.
|
||||
*/
|
||||
const CEntityVector& GetParamVector() const { return m_vecParameters; }
|
||||
|
||||
/**
|
||||
* @brief Get "raises" exceptions vector.
|
||||
* @return Returns the vector with the exception entities.
|
||||
*/
|
||||
CEntityVector& GetExceptionVector() { return m_vecRaisesExceptions; }
|
||||
|
||||
/**
|
||||
* @brief Get "get_raises" exceptions vector.
|
||||
* @return Returns the vector with the exception entities.
|
||||
*/
|
||||
CEntityVector& GetReadExceptionVector() { return m_vecGetRaisesExceptions; }
|
||||
|
||||
/**
|
||||
* @brief Get "set_raises" exceptions vector.
|
||||
* @return Returns the vector with the exception entities.
|
||||
*/
|
||||
CEntityVector& GetWriteExceptionVector() { return m_vecSetRaisesExceptions; }
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Process assignment state.
|
||||
* @details The assignment processing progression state which is used to control the processing of assignments as well as to
|
||||
* prevent circular use of assignments.
|
||||
*/
|
||||
enum class EProcessAssignmentProgression
|
||||
{
|
||||
unprocessed, ///< Assignment hasn't been processed yet
|
||||
currently_processing, ///< Processing currently takes place
|
||||
processed, ///< Processing has been done
|
||||
};
|
||||
|
||||
CTypeDeclaration m_typedecl; ///< The type definition of this declaration.
|
||||
std::vector<CTokenList> m_vecMultiArraySizeTokenList; ///< The list of tokens for each array dimension to be
|
||||
///< calculated during the post processing phase.
|
||||
CTokenList m_lstAssignmentTokenList; ///< The list of tokens forming the assignment.
|
||||
std::vector<CTokenList> m_vecRaisesExceptionsTokenList; ///< The list of tokens for each exception to be parsed
|
||||
///< during the post processing phase.
|
||||
std::vector<CTokenList> m_vecSetRaisesExceptionsTokenList; ///< The list of tokens for each exception to be parsed
|
||||
///< during the post processing phase.
|
||||
std::vector<CTokenList> m_vecGetRaisesExceptionsTokenList; ///< The list of tokens for each exception to be parsed
|
||||
///< during the post processing phase.
|
||||
std::vector<CTokenList> m_vecParametersTokenList; ///< The list of tokens for each parameter to be parsed
|
||||
///< during the post processing phase.
|
||||
EProcessAssignmentProgression m_eProcAssState = EProcessAssignmentProgression::unprocessed; ///< Processing assignment
|
||||
///< progression state.
|
||||
CEntityVector m_vecRaisesExceptions; ///< Can raise the exceptions while reading/writing.
|
||||
CEntityVector m_vecGetRaisesExceptions; ///< Can raise the exceptions while reading.
|
||||
CEntityVector m_vecSetRaisesExceptions; ///< Can raise the exceptions while writing.
|
||||
CEntityVector m_vecParameters; ///< Vector of parameters.
|
||||
};
|
||||
|
||||
#endif // !defined(BASIC_TYPE_ENTITY_H)
|
||||
765
sdv_executables/sdv_idl_compiler/entities/definition_entity.cpp
Normal file
765
sdv_executables/sdv_idl_compiler/entities/definition_entity.cpp
Normal file
@@ -0,0 +1,765 @@
|
||||
#include "definition_entity.h"
|
||||
#include "../exception.h"
|
||||
#include "../logger.h"
|
||||
#include "../parser.h"
|
||||
#include "struct_entity.h"
|
||||
#include "union_entity.h"
|
||||
#include "typedef_entity.h"
|
||||
#include "variable_entity.h"
|
||||
#include "attribute_entity.h"
|
||||
#include "operation_entity.h"
|
||||
#include "enum_entity.h"
|
||||
#include "exception_entity.h"
|
||||
#include "interface_entity.h"
|
||||
#include "meta_entity.h"
|
||||
#include <iostream>
|
||||
|
||||
CDefinitionEntity::CDefinitionEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent) :
|
||||
CEntity(rptrContext, ptrParent), m_iteratorChildren(GetChildrenVector()), m_iteratorInheritance(m_vecInheritance)
|
||||
{}
|
||||
|
||||
CDefinitionEntity::CDefinitionEntity(CParser& rParser, const CContextPtr& rptrContext) :
|
||||
CEntity(rParser, rptrContext), m_iteratorChildren(GetChildrenVector()), m_iteratorInheritance(m_vecInheritance)
|
||||
{}
|
||||
|
||||
sdv::interface_t CDefinitionEntity::GetInterface(sdv::interface_id idInterface)
|
||||
{
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::idl::IDefinitionEntity>())
|
||||
return static_cast<sdv::idl::IDefinitionEntity*>(this);
|
||||
return CEntity::GetInterface(idInterface);
|
||||
}
|
||||
|
||||
void CDefinitionEntity::ProcessContent()
|
||||
{
|
||||
CLog log("Processing definition content...");
|
||||
|
||||
// Get tokens until no token is returned any more.
|
||||
while (true)
|
||||
{
|
||||
// Prepare proocessing the next token
|
||||
CToken token = PeekToken();
|
||||
|
||||
// Add any meta entity
|
||||
std::list<CParser::SMetaToken> lstMeta = GetParserRef().GetAndRemoveMeta();
|
||||
for (const CParser::SMetaToken& rsMeta : lstMeta)
|
||||
AddChild(std::make_shared<CMetaEntity>(rsMeta.tokenMeta.GetContext(), shared_from_this(), rsMeta.tokenMeta,
|
||||
rsMeta.lstComments));
|
||||
|
||||
// Process the acquired token
|
||||
if (!token) break;
|
||||
if (!IsRootEntity() && token == "}")
|
||||
break;
|
||||
|
||||
// Determine whether the comments are preceding the token (either on the same line or the line before).
|
||||
CTokenList lstPreComments = GetPreCommentTokenList();
|
||||
|
||||
// Check for prefixes
|
||||
bool bPrefixConst = false;
|
||||
bool bPrefixReadOnly = false;
|
||||
bool bPrefixTypedef = false;
|
||||
bool bPrefixLocal = false;
|
||||
token = GetToken();
|
||||
uint32_t uiLineBegin = token.GetLine();
|
||||
uint32_t uiColBegin = token.GetCol();
|
||||
if (token == "const") // This must be a const declaration
|
||||
{
|
||||
if (!Supports(EDefinitionSupport::support_const_variable))
|
||||
throw CCompileException(token, "Unexpected keyword 'const'.");
|
||||
bPrefixConst = true;
|
||||
token = GetToken();
|
||||
}
|
||||
else if (token == "readonly") // This must be a readonly attribute
|
||||
{
|
||||
if (!Supports(EDefinitionSupport::support_attribute))
|
||||
throw CCompileException(token, "Unexpected keyword 'readonly'.");
|
||||
bPrefixReadOnly = true;
|
||||
token = GetToken();
|
||||
} else if (token == "typedef") // This must be a typedef declaration
|
||||
{
|
||||
if (!Supports(EDefinitionSupport::support_typedef))
|
||||
throw CCompileException(token, "Unexpected keyword 'typedef'.");
|
||||
bPrefixTypedef = true;
|
||||
token = GetToken();
|
||||
} else if (token == "local") // This must be a const declaration
|
||||
{
|
||||
if (!Supports(EDefinitionSupport::support_interface))
|
||||
throw CCompileException(token, "Unexpected keyword 'local'.");
|
||||
bPrefixLocal = true;
|
||||
token = GetToken();
|
||||
// The next token must be interface
|
||||
if (token != "interface")
|
||||
throw CCompileException(token, "Unexpected token. Only interfaces can be local.");
|
||||
}
|
||||
|
||||
// For keywords that could be a definition as well as a declaration, find out whether the statement here is a
|
||||
// - forward declaration
|
||||
// - a definition
|
||||
// - a definition as well as a declaration
|
||||
// - a declaration
|
||||
// Check for a definition (first three points).
|
||||
auto fnIsDefinition = [&]() -> bool
|
||||
{
|
||||
// A declaration without definition has the construction
|
||||
// <def type> <def identifier> <decl identifier>;
|
||||
// e.g.
|
||||
// struct STest sTest;
|
||||
// The <def type> was retrieved already. The next token would be the identifier.
|
||||
if (PeekToken(0).GetType() == ETokenType::token_identifier &&
|
||||
PeekToken(1).GetType() == ETokenType::token_identifier) return false;
|
||||
|
||||
// All other situations indicate a definition (possibly followed by a declaration).
|
||||
return true;
|
||||
};
|
||||
|
||||
CEntityPtr ptrDefinitionEntity;
|
||||
CToken tokenDefinitionType = token;
|
||||
if (token == "module" && fnIsDefinition())
|
||||
{
|
||||
if (!Supports(EDefinitionSupport::support_module))
|
||||
throw CCompileException(token, "Unexpected keyword 'module'.");
|
||||
ptrDefinitionEntity = CreateChild<CModuleEntity>(token.GetContext(), this);
|
||||
}
|
||||
else if (token == "enum" && fnIsDefinition())
|
||||
{
|
||||
if (fnIsDefinition() && !Supports(EDefinitionSupport::support_enum))
|
||||
throw CCompileException(token, "Unexpected keyword 'enum'.");
|
||||
ptrDefinitionEntity = CreateChild<CEnumEntity>(token.GetContext(), this);
|
||||
}
|
||||
else if (token == "exception" && fnIsDefinition())
|
||||
{
|
||||
if (!Supports(EDefinitionSupport::support_exception))
|
||||
throw CCompileException(token, "Unexpected keyword 'exception'.");
|
||||
ptrDefinitionEntity = CreateChild<CExceptionEntity>(token.GetContext(), this);
|
||||
}
|
||||
else if (token == "struct" && fnIsDefinition())
|
||||
{
|
||||
if (!Supports(EDefinitionSupport::support_struct))
|
||||
throw CCompileException(token, "Unexpected keyword 'struct'.");
|
||||
ptrDefinitionEntity = CreateChild<CStructEntity>(token.GetContext(), this);
|
||||
}
|
||||
else if (token == "union" && fnIsDefinition())
|
||||
{
|
||||
if (!Supports(EDefinitionSupport::support_union))
|
||||
throw CCompileException(token, "Unexpected keyword 'union'.");
|
||||
ptrDefinitionEntity = CreateChild<CUnionEntity>(token.GetContext(), this);
|
||||
}
|
||||
else if (token == "interface" && fnIsDefinition())
|
||||
{
|
||||
if (!Supports(EDefinitionSupport::support_interface))
|
||||
throw CCompileException(token, "Unexpected keyword 'interface'.");
|
||||
ptrDefinitionEntity = CreateChild<CInterfaceEntity>(token.GetContext(), this, bPrefixLocal);
|
||||
}
|
||||
|
||||
// Definition available?
|
||||
if (ptrDefinitionEntity)
|
||||
{
|
||||
// Assign the preceding comments (only if not prefixed)
|
||||
if (!bPrefixConst && !bPrefixReadOnly && !bPrefixTypedef && !lstPreComments.empty())
|
||||
{
|
||||
ptrDefinitionEntity->SetCommentTokens(lstPreComments);
|
||||
lstPreComments.clear();
|
||||
}
|
||||
|
||||
// Set the location in the source file
|
||||
ptrDefinitionEntity->SetBeginPosition(uiLineBegin, uiColBegin);
|
||||
|
||||
// Process the definition
|
||||
log << "Detected " << static_cast<std::string>(token) << " definition..." << std::endl;
|
||||
ptrDefinitionEntity->Process();
|
||||
token = GetToken();
|
||||
|
||||
// Assign any succeeding comments
|
||||
ptrDefinitionEntity->ProcessPostCommentTokenList(token.GetLine());
|
||||
}
|
||||
|
||||
// A struct allows the definition of types that require a declaration within the struct, but the declaration is anonymous
|
||||
// (unnamed and not declared) so the members of the definition appear as if they are part of the struct.
|
||||
bool bAnonymousDecl = false;
|
||||
if (token == ";" && GetType() == sdv::idl::EEntityType::type_struct && ptrDefinitionEntity &&
|
||||
ptrDefinitionEntity->Get<CDefinitionEntity>()->RequireDeclaration())
|
||||
{
|
||||
if (ptrDefinitionEntity->Get<CDefinitionEntity>()->AllowAutoTransparentDeclaration())
|
||||
{
|
||||
// Allow processing still
|
||||
PrependToken(token);
|
||||
|
||||
// Create a dummy name
|
||||
token = CToken(GetParserRef().GenerateAnonymousEntityName("var"));
|
||||
|
||||
bAnonymousDecl = true;
|
||||
} else
|
||||
throw CCompileException(token,
|
||||
"The definition requires a declaration following the definition content or cannot find a variable within "
|
||||
"current scope - unexpected token ';'.");
|
||||
}
|
||||
|
||||
// Statement finished?
|
||||
if (token == ";")
|
||||
{
|
||||
if (bPrefixConst || bPrefixReadOnly || bPrefixTypedef)
|
||||
throw CCompileException(token, "Unexpected token ';'.");
|
||||
|
||||
if (ptrDefinitionEntity)
|
||||
{
|
||||
// Assign any succeeding comments
|
||||
ptrDefinitionEntity->ProcessPostCommentTokenList(token.GetLine());
|
||||
|
||||
// Set the end position in the source file.
|
||||
ptrDefinitionEntity->SetEndPosition(token.GetLine(), token.GetCol());
|
||||
|
||||
// Declaration needed?
|
||||
if (ptrDefinitionEntity->Get<CDefinitionEntity>()->RequireDeclaration())
|
||||
throw CCompileException(token,
|
||||
"The definition requires a declaration following the definition content - unexpected token ';'.");
|
||||
}
|
||||
|
||||
continue;
|
||||
};
|
||||
|
||||
if (!token && !bPrefixConst && !bPrefixReadOnly && !bPrefixTypedef)
|
||||
throw CCompileException(GetLastValidToken(), "Missing ';' following the token.");
|
||||
|
||||
// The declarative part can consist of the following types of declaration
|
||||
// - an attribute - read-only prefix possible
|
||||
// - a typedef
|
||||
// - an operation
|
||||
// - a variable - const prefix possible
|
||||
CEntityPtr ptrDeclarationEntity;
|
||||
if (bPrefixReadOnly && token != "attribute")
|
||||
throw CCompileException(token, "Expecting 'attribute' keyword following 'readonly'.");
|
||||
if (token == "attribute")
|
||||
{
|
||||
if (bPrefixConst || bPrefixTypedef || ptrDefinitionEntity || !Supports(EDefinitionSupport::support_attribute))
|
||||
throw CCompileException(token, "Unexpected keyword 'attribute'.");
|
||||
ptrDeclarationEntity = CreateChild<CAttributeEntity>(token.GetContext(), this, bPrefixReadOnly);
|
||||
if (bPrefixReadOnly)
|
||||
log << "Detected read-only attribute declaration..." << std::endl;
|
||||
else
|
||||
log << "Detected attribute declaration..." << std::endl;
|
||||
}
|
||||
else if (token == "case" || token == "default")
|
||||
{
|
||||
if (bPrefixReadOnly || bPrefixConst || bPrefixTypedef || ptrDefinitionEntity || !Supports(EDefinitionSupport::support_case_declaration))
|
||||
throw CCompileException(token, "Unexpected keyword 'case'.");
|
||||
ptrDeclarationEntity = CreateChild<CCaseEntry>(token.GetContext(), this, token == "default");
|
||||
log << "Detected case entry declaration..." << std::endl;
|
||||
} else
|
||||
{
|
||||
// Reinsert the token into the tokenlist
|
||||
PrependToken(token);
|
||||
|
||||
// Check whether the declaration is a variable declaration or an operation.
|
||||
// An operation can have the following structure:
|
||||
// <keyword> <identifier>(); e.g. int32 Func()
|
||||
// <keyword> <keyword> <identifier>(); e.g. long long Func()
|
||||
// <keyword> <keyword> <keyword> <identifier>(); e.g. unsigned long long Func()
|
||||
// <identifier> <identifier>() e.g. mytype Func()
|
||||
// A variable declaration can have the following structure:
|
||||
// <keyword> <identifier>; e.g. int32 iVar;
|
||||
// <keyword> <keyword> <identifier>; e.g. long long llVar;
|
||||
// <keyword> <keyword> <keyword> <identifier>; e.g. unsigned long long ullVar;
|
||||
// <keyword> <identifier> = <expression>; e.g. int32 iVar = 10;
|
||||
// <keyword> <keyword> <identifier> = <expression>; e.g. long long llVar = 10;
|
||||
// <keyword> <keyword> <keyword> <identifier> = <expression>; e.g. unsigned long long ullVar = 10;
|
||||
// Only variables can be declared with const prefix.
|
||||
// A variable declaration without assignment can also be a typedef when declared with typedef prefix.
|
||||
// Operations cannot be declared follwoing a definition.
|
||||
|
||||
// As type expecting up to three keywords or one scoped identifier (composition of identifier and scope operator).
|
||||
// If there is a definition, then the declaration and definition are combined. The type is there then already.
|
||||
size_t nIndex = 0;
|
||||
bool bTypeFound = ptrDefinitionEntity ? true : false;
|
||||
CToken tokenLocal;
|
||||
bool bLongType = false;
|
||||
bool bUnsignedType = false;
|
||||
while ((tokenLocal = PeekToken(nIndex)).GetType() == ETokenType::token_keyword)
|
||||
{
|
||||
// Unsigned is allowed only as first keyword
|
||||
if (tokenLocal == "unsigned")
|
||||
{
|
||||
if (nIndex) break;
|
||||
bUnsignedType = true;
|
||||
}
|
||||
|
||||
// Long should be followed by long or double.
|
||||
if (bLongType && tokenLocal != "long" && tokenLocal != "double") break;
|
||||
|
||||
// Increase the token index...
|
||||
nIndex++;
|
||||
|
||||
// Type found...
|
||||
bTypeFound = true;
|
||||
|
||||
// After unsigned, at least one more keyword needs to follow
|
||||
if (bUnsignedType && nIndex == 1) continue;
|
||||
|
||||
// After long, another type can follow, but only when this long didn't follow a previous long already.
|
||||
if (tokenLocal == "long")
|
||||
{
|
||||
if (bLongType) break; // type was long long.
|
||||
bLongType = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The type can be a templated type (or even nested templated types are possible).
|
||||
tokenLocal = PeekToken(nIndex);
|
||||
CToken tokenLocalTemplate;
|
||||
if (tokenLocal == "<")
|
||||
{
|
||||
size_t nDepth = 0;
|
||||
tokenLocalTemplate = tokenLocal;
|
||||
do
|
||||
{
|
||||
if (tokenLocal == "<") nDepth++;
|
||||
if (tokenLocal == ">") nDepth--;
|
||||
if (tokenLocal == ">>") nDepth-=2; // This actually is an operator
|
||||
nIndex++;
|
||||
tokenLocal = PeekToken(nIndex);
|
||||
} while (tokenLocal && static_cast<bool>(nDepth));
|
||||
}
|
||||
|
||||
// No more types are expected to follow
|
||||
break;
|
||||
}
|
||||
while (!bTypeFound)
|
||||
{
|
||||
// Check for the scope parameter
|
||||
tokenLocal = PeekToken(nIndex);
|
||||
if (tokenLocal == "::")
|
||||
{
|
||||
nIndex++;
|
||||
tokenLocal = PeekToken(nIndex);
|
||||
}
|
||||
|
||||
// Check for the identifier
|
||||
if (tokenLocal.GetType() == ETokenType::token_identifier)
|
||||
{
|
||||
nIndex++;
|
||||
if (PeekToken(nIndex) != "::")
|
||||
bTypeFound = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Coming here means, there was no type
|
||||
throw CCompileException(tokenLocal, "Invalid token '", static_cast<std::string>(tokenLocal),
|
||||
"' found for type name.");
|
||||
}
|
||||
|
||||
// The return value can be an array - but only in case of operations.
|
||||
tokenLocal = PeekToken(nIndex);
|
||||
CToken tokenLocalArray;
|
||||
while (tokenLocal == "[")
|
||||
{
|
||||
if (!tokenLocalArray) tokenLocalArray = tokenLocal;
|
||||
do
|
||||
{
|
||||
nIndex++;
|
||||
tokenLocal = PeekToken(nIndex);
|
||||
} while (tokenLocal && tokenLocal != "]");
|
||||
nIndex++;
|
||||
tokenLocal = PeekToken(nIndex);
|
||||
}
|
||||
|
||||
// Expecting identfier representing the name
|
||||
// If the extension is enabled, this could also be a keyword.
|
||||
if (tokenLocal.GetType() != ETokenType::token_identifier &&
|
||||
(!GetParserRef().GetEnvironment().ContextDependentNamesExtension() ||
|
||||
tokenLocal.GetType() != ETokenType::token_keyword))
|
||||
throw CCompileException(tokenLocal, "Invalid token '", static_cast<std::string>(tokenLocal),
|
||||
"' found for type name (or missing semi-colon ';' ?).");
|
||||
nIndex++;
|
||||
|
||||
// An operation has a left bracket
|
||||
tokenLocal = PeekToken(nIndex);
|
||||
if (tokenLocal == "(") // This indicates a operation
|
||||
{
|
||||
if (ptrDefinitionEntity || bPrefixConst || bPrefixTypedef || !Supports(EDefinitionSupport::support_operation))
|
||||
throw CCompileException(tokenLocal, "Unexpected left bracket '('.");
|
||||
ptrDeclarationEntity = CreateChild<COperationEntity>(token.GetContext(), this);
|
||||
log << "Detected operation declaration..." << std::endl;
|
||||
}
|
||||
else // This could be a variable declaration or a typedef declaration
|
||||
{
|
||||
// An array is not allowed when not using an operation
|
||||
if (tokenLocalArray)
|
||||
throw CCompileException(tokenLocalArray, "Invalid token '[' found for type name.");
|
||||
|
||||
// If there is a definition, add the name of the definition
|
||||
if (ptrDefinitionEntity)
|
||||
{
|
||||
CToken tokenName(ptrDefinitionEntity->GetName());
|
||||
PrependToken(tokenName);
|
||||
}
|
||||
|
||||
// Check for typedef declaration
|
||||
if (bPrefixTypedef)
|
||||
{
|
||||
ptrDeclarationEntity = CreateChild<CTypedefEntity>(token.GetContext(), this);
|
||||
log << "Detected typedef declaration..." << std::endl;
|
||||
}
|
||||
else // Variable declaration
|
||||
{
|
||||
if (!bPrefixConst && !Supports(EDefinitionSupport::support_variable))
|
||||
throw CCompileException(token, "Variable declaration is not supported.");
|
||||
ptrDeclarationEntity = CreateChild<CVariableEntity>(token.GetContext(), this, bPrefixConst, bAnonymousDecl);
|
||||
if (bPrefixConst)
|
||||
log << "Detected const variable declaration..." << std::endl;
|
||||
else
|
||||
log << "Detected variable declaration..." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process the entity declaration.
|
||||
if (!ptrDeclarationEntity) throw CCompileException("Declaration expected.");
|
||||
ptrDeclarationEntity->SetBeginPosition(uiLineBegin, uiColBegin);
|
||||
ptrDeclarationEntity->Process();
|
||||
|
||||
if (!lstPreComments.empty())
|
||||
ptrDeclarationEntity->SetCommentTokens(lstPreComments);
|
||||
|
||||
// Expect ';'
|
||||
token = GetToken();
|
||||
if (token != ";")
|
||||
throw CCompileException(token, "Missing semicolon ';' following the declaration.");
|
||||
}
|
||||
|
||||
log << "For definition '" << GetName() << "', processing value assignments within content..." << std::endl;
|
||||
|
||||
// If supported create the value node for the definition (this allows assignments of values to this entity).
|
||||
CreateValueNode();
|
||||
|
||||
// If there is a value node (assignment is supported), add the inherited value sub-trees to the type as children. If there are
|
||||
// inherited entities with value nodes of their own, of course.
|
||||
if (ValueRef())
|
||||
CreateInheritanceValueChildNodes();
|
||||
|
||||
// Go through all the type members and do post processing (building value chains, resolving arrays, etc.).
|
||||
for (CEntityPtr ptrTypeEntity : m_lstTypeMembers)
|
||||
{
|
||||
CTypedefEntity* pTypedefEntity = ptrTypeEntity->Get<CTypedefEntity>();
|
||||
if (pTypedefEntity)
|
||||
{
|
||||
log << "Post-processing typedef entity '" << pTypedefEntity->GetName() << "'..." << std::endl;
|
||||
pTypedefEntity->PostProcess();
|
||||
}
|
||||
CUnionEntity* pUnionEntity = ptrTypeEntity->Get<CUnionEntity>();
|
||||
if (pUnionEntity)
|
||||
{
|
||||
log << "Post-processing union entity '" << pUnionEntity->GetName() << "'..." << std::endl;
|
||||
pUnionEntity->PostProcess();
|
||||
}
|
||||
}
|
||||
|
||||
// Go through all the typedef members and do post processing (building value chains, resolving arrays, variable assignment,
|
||||
// etc.).
|
||||
for (CEntityPtr ptrConstEntity : m_lstConstMembers)
|
||||
{
|
||||
CVariableEntity* pConstEntity = ptrConstEntity->Get<CVariableEntity>();
|
||||
if (!pConstEntity)
|
||||
throw CCompileException("Internal error: non-const entities in const entity list.");
|
||||
else
|
||||
{
|
||||
log << "Post-processing const variable entity '" << pConstEntity->GetName() << "'..." << std::endl;
|
||||
pConstEntity->PostProcess();
|
||||
}
|
||||
}
|
||||
|
||||
// Go through all the definition members and do post processing (resolving arrays, creating exception and parameter lists,
|
||||
// etc.).
|
||||
for (CEntityPtr ptrDefinitionEntity : m_lstAttributesOperation)
|
||||
{
|
||||
CAttributeEntity* pAttribute = ptrDefinitionEntity->Get<CAttributeEntity>();
|
||||
COperationEntity* pOperation = ptrDefinitionEntity->Get<COperationEntity>();
|
||||
if (!pAttribute && !pOperation)
|
||||
throw CCompileException("Internal error: wrong entities in definition list.");
|
||||
|
||||
if (pAttribute)
|
||||
{
|
||||
log << "Postprocessing attribute entity '" << pAttribute->GetName() << "'..." << std::endl;
|
||||
pAttribute->PostProcess();
|
||||
}
|
||||
if (pOperation)
|
||||
{
|
||||
log << "Postprocessing operation entity '" << pOperation->GetName() << "'..." << std::endl;
|
||||
pOperation->PostProcess();
|
||||
}
|
||||
}
|
||||
|
||||
// Go through all the variable members and create the default values for all var members if the value node is a compound type
|
||||
// value node.
|
||||
for (CEntityPtr ptrDeclEntity : m_lstDeclMembers)
|
||||
{
|
||||
CVariableEntity *pDeclEntity = ptrDeclEntity->Get<CVariableEntity>();
|
||||
if (!pDeclEntity)
|
||||
throw CCompileException("Internal error: non-declaration entity in declaration entity list.");
|
||||
else
|
||||
{
|
||||
log << "Postprocess variable entity '" << pDeclEntity->GetName() << "'..." << std::endl;
|
||||
pDeclEntity->PostProcess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CDefinitionEntity::Process()
|
||||
{
|
||||
CLog log("Processing definition of entity...");
|
||||
|
||||
// Check for an identifier.
|
||||
// If present, this is the name of the definition.
|
||||
CToken token = GetToken();
|
||||
std::string ssName;
|
||||
m_bAnonymousDefinition = false;
|
||||
if (token.GetType() == ETokenType::token_identifier)
|
||||
{
|
||||
ssName = static_cast<std::string>(token);
|
||||
log << "Definition type name '" << ssName << "'..." << std::endl;
|
||||
} else
|
||||
if (SupportsAnonymous())
|
||||
{
|
||||
if (!GetParentEntity() || GetParentEntity()->IsRootEntity())
|
||||
throw CCompileException(token, "Unnamed definitions are not supported at root level.");
|
||||
std::string ssPrefix = "anonymous";
|
||||
switch (GetType())
|
||||
{
|
||||
case sdv::idl::EEntityType::type_enum: ssPrefix = "enum"; break;
|
||||
case sdv::idl::EEntityType::type_struct: ssPrefix = "struct"; break;
|
||||
case sdv::idl::EEntityType::type_union: ssPrefix = "union"; break;
|
||||
case sdv::idl::EEntityType::type_module: ssPrefix = "namespace"; break;
|
||||
case sdv::idl::EEntityType::type_interface: ssPrefix = "interface"; break;
|
||||
case sdv::idl::EEntityType::type_exception: ssPrefix = "except"; break;
|
||||
case sdv::idl::EEntityType::type_typedef: ssPrefix = "typedef"; break;
|
||||
default: break;
|
||||
}
|
||||
ssName = GetParserRef().GenerateAnonymousEntityName(ssPrefix);
|
||||
log << "Unnamed definition was automatically assigned name '" << ssName << "'..." << std::endl;
|
||||
m_bRequiresContent = true;
|
||||
m_bAnonymousDefinition = true;
|
||||
PrependToken(token);
|
||||
} else
|
||||
throw CCompileException(token, "Unnamed definition is not supported.");
|
||||
|
||||
// Process the definition addendum
|
||||
ProcessDefinitionAddendum();
|
||||
|
||||
// Expecting curly bracket when for a
|
||||
token = GetToken();
|
||||
if (RequireContentDefinition() && token != "{")
|
||||
throw CCompileException(token, "Expecting curly bracket '{'.");
|
||||
|
||||
// If there is no content, consider the statement as a (forward) declaration.
|
||||
SetName(ssName, token != "{");
|
||||
|
||||
// If there is no content, the processing is done.
|
||||
if (token != "{")
|
||||
{
|
||||
log << "Definition type was defined as forward declaration." << std::endl;
|
||||
log << "Finished processing definition entity..." << std::endl;
|
||||
PrependToken(token);
|
||||
return;
|
||||
}
|
||||
|
||||
// Definition content...
|
||||
ProcessContent();
|
||||
|
||||
// Close the definition
|
||||
token = GetToken();
|
||||
if (token != "}")
|
||||
throw CCompileException(token, "Expecting curly bracket '}'.");
|
||||
|
||||
log << "Finished processing definition entity..." << std::endl;
|
||||
}
|
||||
|
||||
void CDefinitionEntity::ProcessDefinitionAddendum()
|
||||
{
|
||||
// Check for inheritance
|
||||
CToken token = GetToken();
|
||||
if (token != ":")
|
||||
{
|
||||
PrependToken(token);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SupportsInheritance()) throw CCompileException(token, "Inheritance is not supported.");
|
||||
|
||||
// When an inheritance list is provided, the content should also be provided.
|
||||
m_bRequiresContent = true;
|
||||
|
||||
CLog log("Processing inheritance list...");
|
||||
|
||||
// Get the list of base entities
|
||||
while (true)
|
||||
{
|
||||
// Find the base entity.
|
||||
std::pair<std::string, CEntityPtr> prBase = ProcessScopedName();
|
||||
if (prBase.first.empty() || !prBase.second)
|
||||
throw CCompileException("Base not found.");
|
||||
log << "Inherited from base entity: " << prBase.first << std::endl;
|
||||
|
||||
if (prBase.second->GetResolvedEntity()->GetType() != GetType())
|
||||
throw CCompileException("Cannot inherit from different types.");
|
||||
|
||||
// Check whether the base entity is more than only a declaration.
|
||||
if (prBase.second->ForwardDeclaration())
|
||||
throw CCompileException("Base type found, but only declared; definition is missing.");
|
||||
|
||||
// TODO: Check whether the entity was already previously inherited directly or indirectly. Inheriting through a base
|
||||
// prevents inheriting again.
|
||||
|
||||
// Add the base entity to the base entity list.
|
||||
m_vecInheritance.push_back(prBase.second);
|
||||
|
||||
// Get the next base entity or the beginning of the definition.
|
||||
token = GetToken();
|
||||
if (token != ",")
|
||||
{
|
||||
PrependToken(token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CDefinitionEntity::CreateInheritanceValueChildNodes()
|
||||
{
|
||||
CLog log("Creating values for inherited child nodes...");
|
||||
|
||||
if (!ValueRef()) throw CCompileException("Internal error: cannot create inheritance value child nodes.");
|
||||
|
||||
// For each base entity, copy the value tree
|
||||
for (CEntityPtr ptrInheritedEntity : m_vecInheritance)
|
||||
{
|
||||
// Check for a valid value of the base entity.
|
||||
if (!ptrInheritedEntity->GetResolvedEntity()->ValueRef())
|
||||
throw CCompileException("Internal error: base entity wasn't processed for assignment yet.");
|
||||
|
||||
log << "Assigning values from base entity '" << ptrInheritedEntity->GetName() << "'." << std::endl;
|
||||
|
||||
// Create a copy of the tree and add as child to own tree.
|
||||
ValueRef()->AddChild(ptrInheritedEntity->GetResolvedEntity()->ValueRef()->CreateCopy(shared_from_this(), ValueRef()));
|
||||
}
|
||||
}
|
||||
|
||||
sdv::idl::IEntityIterator* CDefinitionEntity::GetChildren()
|
||||
{
|
||||
if (SupportsChildren()) return &m_iteratorChildren;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sdv::idl::IEntityIterator* CDefinitionEntity::GetInheritance()
|
||||
{
|
||||
if (SupportsInheritance() && !m_vecInheritance.empty()) return &m_iteratorInheritance;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CDefinitionEntity::CalcHash(CHashObject& rHash) const
|
||||
{
|
||||
// First calc the hash of the base entity.
|
||||
CEntity::CalcHash(rHash);
|
||||
|
||||
// Add the hashes of all inherited entities
|
||||
for (const CEntityPtr& ptrEntity : m_vecInheritance)
|
||||
ptrEntity->CalcHash(rHash);
|
||||
|
||||
// Add the declarations
|
||||
for (const CEntityPtr& ptrEntity : m_lstDeclMembers)
|
||||
ptrEntity->CalcHash(rHash);
|
||||
|
||||
// Add the attributes and operations
|
||||
for (const CEntityPtr& ptrEntity : m_lstAttributesOperation)
|
||||
ptrEntity->CalcHash(rHash);
|
||||
}
|
||||
|
||||
const CEntityList CDefinitionEntity::GetDeclMembers() const
|
||||
{
|
||||
CEntityList lstMembers;
|
||||
|
||||
// Add all declarations from the inherited members
|
||||
for (const CEntityPtr& rptrInheritedEntity : m_vecInheritance)
|
||||
{
|
||||
const CDefinitionEntity* pDefinition = rptrInheritedEntity->GetResolvedEntity()->Get<CDefinitionEntity>();
|
||||
if (pDefinition)
|
||||
{
|
||||
CEntityList lstInheritedEntities = pDefinition->GetDeclMembers();
|
||||
for (const CEntityPtr& ptrInheritedMember : lstInheritedEntities)
|
||||
lstMembers.push_back(ptrInheritedMember);
|
||||
}
|
||||
}
|
||||
|
||||
// Add own declarations
|
||||
for (const CEntityPtr& rptrMember : m_lstDeclMembers)
|
||||
lstMembers.push_back(rptrMember);
|
||||
|
||||
return lstMembers;
|
||||
}
|
||||
|
||||
void CDefinitionEntity::AddChild(CEntityPtr ptrChild)
|
||||
{
|
||||
CLog log;
|
||||
|
||||
// Call base class first
|
||||
CEntity::AddChild(ptrChild);
|
||||
|
||||
// Dependable on the type of entity, add the entity to dedicated lists as well.
|
||||
if (ptrChild->Get<CTypedefEntity>())
|
||||
{
|
||||
m_lstTypeMembers.push_back(ptrChild);
|
||||
log << "Added typedef declaration to type member list..." << std::endl;
|
||||
}
|
||||
else if (ptrChild->Get<CAttributeEntity>())
|
||||
{
|
||||
m_lstAttributesOperation.push_back(ptrChild);
|
||||
log << "Added attribute to definition list..." << std::endl;
|
||||
} else if (ptrChild->Get<COperationEntity>())
|
||||
{
|
||||
m_lstAttributesOperation.push_back(ptrChild);
|
||||
log << "Added operation to definition list..." << std::endl;
|
||||
}
|
||||
else if (ptrChild->Get<CDeclarationEntity>())
|
||||
{
|
||||
if (ptrChild->Get<CDeclarationEntity>()->IsReadOnly())
|
||||
{
|
||||
m_lstConstMembers.push_back(ptrChild);
|
||||
log << "Added const declaration to const member list..." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lstDeclMembers.push_back(ptrChild);
|
||||
log << "Added declaration to variable member list..." << std::endl;
|
||||
}
|
||||
}
|
||||
else if (ptrChild->Get<CDefinitionEntity>())
|
||||
{
|
||||
m_lstTypeMembers.push_back(ptrChild);
|
||||
log << "Added definition to type member list..." << std::endl;
|
||||
}
|
||||
else if (ptrChild->Get<CMetaEntity>())
|
||||
{
|
||||
GetRootEntity()->Get<CRootEntity>()->AddMeta(ptrChild);
|
||||
log << "Added meta data to root based meta list..." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<CEntityPtr, bool> CDefinitionEntity::FindLocal(const std::string& rssName, bool bDeclaration) const
|
||||
{
|
||||
// Call base class implementation first.
|
||||
std::pair<CEntityPtr, bool> prEntity = CEntity::FindLocal(rssName, bDeclaration);
|
||||
if (prEntity.first) return prEntity;
|
||||
|
||||
// Check through all inherited entities
|
||||
for (const CEntityPtr& rptrBaseEntity : m_vecInheritance)
|
||||
{
|
||||
if (!rptrBaseEntity) continue;
|
||||
CEntityPtr ptrResolvedBaseEntity = rptrBaseEntity->GetResolvedEntity();
|
||||
if (!ptrResolvedBaseEntity->Get<CDefinitionEntity>()) continue;
|
||||
prEntity = ptrResolvedBaseEntity->Get<CDefinitionEntity>()->FindLocal(rssName, bDeclaration);
|
||||
if (prEntity.first)
|
||||
{
|
||||
// Set the inherited flag
|
||||
prEntity.second = true;
|
||||
return prEntity;
|
||||
}
|
||||
}
|
||||
|
||||
// No entity found.
|
||||
return std::make_pair(CEntityPtr(), false);
|
||||
}
|
||||
249
sdv_executables/sdv_idl_compiler/entities/definition_entity.h
Normal file
249
sdv_executables/sdv_idl_compiler/entities/definition_entity.h
Normal file
@@ -0,0 +1,249 @@
|
||||
#ifndef DEFINITION_ENTITY_H
|
||||
#define DEFINITION_ENTITY_H
|
||||
|
||||
#include "entity_base.h"
|
||||
|
||||
/**
|
||||
* @brief Support flags for the content of a definition (the part between the curly brackets '{...}').
|
||||
*/
|
||||
enum class EDefinitionSupport : uint32_t
|
||||
{
|
||||
support_variable, ///< Support variable declarations.
|
||||
support_const_variable, ///< Support const variable declarations.
|
||||
support_case_declaration, ///< Support case declarations.
|
||||
support_enum_entry, ///< Support enumerator entry.
|
||||
support_module, ///< Support module definitions.
|
||||
support_typedef, ///< Support typedef declarations.
|
||||
support_interface, ///< Support interface definitions.
|
||||
support_struct, ///< Support struct definitions.
|
||||
support_union, ///< Support union definitions.
|
||||
support_enum, ///< Support enum definitions.
|
||||
support_exception, ///< Support exception definitions.
|
||||
support_attribute, ///< Support attribute declarations.
|
||||
support_operation, ///< Support operation declarations.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The base for definition entity definitions within an IDL file (struct, union, exception, interface, enum).
|
||||
* @details The definition entity definitions all have a similar setup with small differences in detail. Consider the following
|
||||
* structures:
|
||||
* @code
|
||||
* struct <name | anonymous> : <inheritance list> { <member list> }
|
||||
* union <name | anonymous> switch(<type>) { <case member list> }
|
||||
* interface <name> : <inheritance list> { <member list> }
|
||||
* exception <name> { <member list> }
|
||||
* enum <name> : <type> { <item list> }
|
||||
* @endcode
|
||||
* The following generalized structure applies to all complex structures:
|
||||
* @code
|
||||
* keyword name
|
||||
* prefix keyword name postfix { definition }
|
||||
* @endcode
|
||||
* The first statement is a forward declaration. The second represents the type definition.
|
||||
* The prefix is used to provide a specific interpretation to the definition.
|
||||
* The keyword defines the type of definition (can be struct, union, interface, exception, enum).
|
||||
* The name is the defined name of the definition. For types that allow anonymous names, this part is optionally.
|
||||
* The postfix allows the specification of additional information needed for the definition (inheritynce list, switch list).
|
||||
* The definition defines the content of the type.
|
||||
* Some declarations might start as a type definition (e.g. struct, union, enum) followed with a declaration. For example:
|
||||
* @code
|
||||
* struct <def_name> { <definition> } <decl_name>
|
||||
* struct { <definition> } <decl_name>
|
||||
* @endcode
|
||||
* In the first statement, the struct is defined and declared in one statement. In the second statement, an anonymous struct is
|
||||
* defined and declared in one statement.
|
||||
*/
|
||||
class CDefinitionEntity : public CEntity, public sdv::idl::IDefinitionEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
*/
|
||||
CDefinitionEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Root entity constructor (name is 'root' and no parent).
|
||||
* @param[in] rParser Reference to the parser.
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
*/
|
||||
CDefinitionEntity(CParser& rParser, const CContextPtr& rptrContext);
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CDefinitionEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get access to another interface. Overload of IInterfaceAccess::GetInterface.
|
||||
* @param[in] idInterface The interface id to get access to.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
virtual sdv::interface_t GetInterface(sdv::interface_id idInterface) override;
|
||||
|
||||
/**
|
||||
* @brief Process the content of the definition.
|
||||
* @details Process the content of the definition. This function parses through the content until a closing curly bracket
|
||||
* has been detected. First the function checks for prefixes. Then the function determines whether the statement is a
|
||||
* declaration or a definition. It then creates the corresponding entity and let the entity process itself.
|
||||
*/
|
||||
virtual void ProcessContent();
|
||||
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Process the definition addendum.
|
||||
* @details Process the definition addendum following the definition statement before the content definition. The default
|
||||
* implementation checks for an inheritance list.
|
||||
*/
|
||||
virtual void ProcessDefinitionAddendum();
|
||||
|
||||
/**
|
||||
* @brief Create a values for inherited child nodes.
|
||||
*/
|
||||
void CreateInheritanceValueChildNodes();
|
||||
|
||||
/**
|
||||
* \brief Does the entity have an Unnamed definition. Overload of IDefinitionEntity::Unnamed.
|
||||
* @return Returns 'true' when the definition supports unnamed definition; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsUnnamed() const override { return m_bAnonymousDefinition; };
|
||||
|
||||
/**
|
||||
* @brief Request whether the definition supports the content. This function must be implemented by the derived entity.
|
||||
* @param[in] eSupport The type of support that is requested.
|
||||
* @return Returns 'true' when the definition supports the content; 'false' otherwise.
|
||||
*/
|
||||
virtual bool Supports(EDefinitionSupport eSupport) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support children? Overload of CEntity::SupportsChildren.
|
||||
* @details Complex types support children per default.
|
||||
* @return Returns whether the entity supports children (which is the case).
|
||||
*/
|
||||
virtual bool SupportsChildren() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support inheritance?
|
||||
* @details The default implementation is that inheritance is not supported.
|
||||
* @return Returns whether the entity supports inheritance (which is not the case).
|
||||
*/
|
||||
virtual bool SupportsInheritance() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support anonymous naming?
|
||||
* @details The default implementation is that anonymous naming is not supported.
|
||||
* @return Returns whether the entity supports inheritance (which is not the case).
|
||||
*/
|
||||
virtual bool SupportsAnonymous() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the complex entity support attributes in its content?
|
||||
* @details The default implementation doesn't support attributes (they are specific to interfaces).
|
||||
* @return Returns whether the entity supports attributes (which is not the case).
|
||||
*/
|
||||
virtual bool SupportContentAttributes() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the complex entity support operations in its content?
|
||||
* @details The default implementation doesn't support operations (they are specific to interfaces).
|
||||
* @return Returns whether the entity supports operations (which is not the case).
|
||||
*/
|
||||
virtual bool SupportContentOperations() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Does the definition entity require a content definition?
|
||||
* @details In certain cases, it is required that the content definition is following the definition statement. For example,
|
||||
* when an inheritance list is provided. The default implementation checks the m_bRequiresContent variable.
|
||||
* @return Returns whether the content definition should be defined following the definition statement.
|
||||
*/
|
||||
virtual bool RequireContentDefinition() const { return m_bRequiresContent; }
|
||||
|
||||
/**
|
||||
* @brief Does the definition require a declaration?
|
||||
* @details In certain cases, it is required that the definition is followed by a declaration. For example,
|
||||
* when the definition was made anonymously or when the definition is dependent on a variable within the same struct (e.g. with
|
||||
* unions).
|
||||
* @return Returns whether the definition requires a declaration.
|
||||
*/
|
||||
virtual bool RequireDeclaration() const { return IsUnnamed(); }
|
||||
|
||||
/**
|
||||
* @brief Does the definition allow automatic transparent declaration if not present?
|
||||
* @details When set an automatic transparent declaration is allowed without an explicit variable declaration. Currently this
|
||||
* is only the case with unions with a variable based switch type.
|
||||
* @return Returns whether the definition allows an automatic transparent declaration.
|
||||
*/
|
||||
virtual bool AllowAutoTransparentDeclaration() const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Get child entity iterator if children are available and supported by the definition. Overload of
|
||||
* sdv::idl::IDefinitionEntity::GetChildren.
|
||||
* @return Returns a pointer to the child entity iterator or NULL when not available.
|
||||
*/
|
||||
virtual sdv::idl::IEntityIterator* GetChildren() override;
|
||||
|
||||
/**
|
||||
* @brief Get inheritance entity iterator if the definition was inheriting from other entities. Overload of
|
||||
* sdv::idl::IDefinitionEntity::GetInheritance.
|
||||
* @return Returns a pointer to the inheritance entity iterator or NULL when not available.
|
||||
*/
|
||||
virtual sdv::idl::IEntityIterator* GetInheritance() override;
|
||||
|
||||
/**
|
||||
* @brief Calculate the hash of this entity and all encapsulated entities. Overload of CBaseEntity::CalcHash.
|
||||
* @param[in, out] rHash Hash object to be filled with data.
|
||||
*/
|
||||
virtual void CalcHash(CHashObject& rHash) const override;
|
||||
|
||||
/**
|
||||
* @brief Get the declaration members.
|
||||
* @return List of declaration members.
|
||||
*/
|
||||
const CEntityList GetDeclMembers() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Add the child to the children list. Called by CreateChild function. Overload of CEntity::AddChild.
|
||||
* @param[in] ptrChild Pointer to the child entity to add.
|
||||
*/
|
||||
virtual void AddChild(CEntityPtr ptrChild) override;
|
||||
|
||||
/**
|
||||
* @brief Find the entity locally by looking in the entity children map and the entity children maps of all the chained
|
||||
* entities. The search is done case-insensitive. Overload of CEntity::FindLocal.
|
||||
* @param[in] rssName Reference to the string object containing the name of the entity to search for.
|
||||
* @param[in] bDeclaration When set, the name belongs to a declaration; otherwise it belongs to a definition. Needed to allow
|
||||
* the reuse of names between declarations and definitions.
|
||||
* @return Returns a pair object containing an entity pointer if the entity exists or a NULL pointer if not as well as a
|
||||
* boolean that indicates that the entity was from an inherited entity.
|
||||
*/
|
||||
virtual std::pair<CEntityPtr, bool> FindLocal(const std::string& rssName, bool bDeclaration) const override;
|
||||
|
||||
/**
|
||||
* @brief Create the content value node. Overridable when supporting content values.
|
||||
* @details When supporting value assignments, create the value node and assign the value node to the ValueRef() reference. For
|
||||
* definitions that do not support value assignments, do nothing (default).
|
||||
*/
|
||||
virtual void CreateValueNode() {};
|
||||
|
||||
protected:
|
||||
CEntityVector m_vecInheritance; ///< List of base entities in the order of appearance.
|
||||
CEntityList m_lstTypeMembers; ///< List of typedef member declarations and type definitions.
|
||||
CEntityList m_lstConstMembers; ///< List of const member declarations.
|
||||
CEntityList m_lstDeclMembers; ///< List of variable member declarations.
|
||||
CEntityList m_lstAttributesOperation; ///< List with attributes and operations.
|
||||
bool m_bRequiresContent = false; ///< When set, the definition statement requires content to follow.
|
||||
bool m_bAnonymousDefinition = false; ///< When set, the entity has an anonymous generated name.
|
||||
CEntityIterator m_iteratorChildren; ///< Children iterator
|
||||
CEntityIterator m_iteratorInheritance; ///< Inheritance iterator
|
||||
};
|
||||
|
||||
|
||||
#endif // !defined(DEFINITION_ENTITY_H)
|
||||
1708
sdv_executables/sdv_idl_compiler/entities/entity_base.cpp
Normal file
1708
sdv_executables/sdv_idl_compiler/entities/entity_base.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1066
sdv_executables/sdv_idl_compiler/entities/entity_base.h
Normal file
1066
sdv_executables/sdv_idl_compiler/entities/entity_base.h
Normal file
File diff suppressed because it is too large
Load Diff
803
sdv_executables/sdv_idl_compiler/entities/entity_value.cpp
Normal file
803
sdv_executables/sdv_idl_compiler/entities/entity_value.cpp
Normal file
@@ -0,0 +1,803 @@
|
||||
#include "entity_value.h"
|
||||
#include "../exception.h"
|
||||
#include "variable_entity.h"
|
||||
#include "definition_entity.h"
|
||||
#include "../constvariant.inl"
|
||||
#include "../support.h"
|
||||
#include "../parser.h"
|
||||
|
||||
CEntityValueNode::CEntityValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
||||
m_ptrEntity(ptrEntity), m_ptrParent(ptrParent)
|
||||
{
|
||||
if (!ptrEntity) throw CCompileException("Internal error: expected a valid entity.");
|
||||
|
||||
CLog log;
|
||||
if (!ptrParent)
|
||||
log << "The value node of '" << ptrEntity->GetName() << "' has no parent node..." << std::endl;
|
||||
else
|
||||
log << "The value node of '" << ptrEntity->GetName() << "' has a parent node..." << std::endl;
|
||||
}
|
||||
|
||||
CEntityValueNode::CEntityValueNode(const CEntityValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
||||
m_ptrEntity(ptrEntity), m_ptrParent(ptrParent), m_vecChildren(rValueNode.m_vecChildren)
|
||||
{
|
||||
if (!ptrEntity) throw CCompileException("Internal error: expected a valid entity.");
|
||||
|
||||
CLog log;
|
||||
if (!ptrParent)
|
||||
log << "The value node of '" << ptrEntity->GetName() << "' has no parent node..." << std::endl;
|
||||
else
|
||||
log << "The value node of '" << ptrEntity->GetName() << "' has a parent node..." << std::endl;
|
||||
}
|
||||
|
||||
void CEntityValueNode::ProcessChildNodes(const CTokenList& rlstExpression)
|
||||
{
|
||||
CLog log;
|
||||
log << "Processing " << m_vecChildren.size() << " child nodes..." << std::endl;
|
||||
bool bInitial = true;
|
||||
for (CValueNodePtr& rptrValue : m_vecChildren)
|
||||
{
|
||||
// Check for a comma separator.
|
||||
if (!bInitial)
|
||||
{
|
||||
if (rlstExpression.Current() != ",")
|
||||
throw CCompileException(rlstExpression.LastValid(), "Missing comma ',' for value separation.");
|
||||
++rlstExpression;
|
||||
}
|
||||
bInitial = false;
|
||||
|
||||
log << "Processing child node..." << std::endl;
|
||||
rptrValue->ProcessValueAssignment(rlstExpression);
|
||||
}
|
||||
}
|
||||
|
||||
void CEntityValueNode::AddChild(CValueNodePtr ptrChild)
|
||||
{
|
||||
CLog log;
|
||||
log << "Adding child node..." << std::endl;
|
||||
if (!ptrChild)
|
||||
throw CCompileException("Internal error: cannot add an empty child node.");
|
||||
m_vecChildren.push_back(ptrChild);
|
||||
}
|
||||
|
||||
std::string CEntityValueNode::GetDeclTypeStr(bool bResolveTypedef) const
|
||||
{
|
||||
return GetDeclEntity()->GetDeclTypeStr(bResolveTypedef);
|
||||
}
|
||||
|
||||
bool CEntityValueNode::IsConst() const
|
||||
{
|
||||
// Default implementation
|
||||
// - In case the entity is a const entity, return 'true'.
|
||||
// - Otherwise check whether the parent value is available and ask the parent if the declaration entity is a const entity.
|
||||
// - If no parent is available, this entity must be a declaration entity and is therefore not a const entity.
|
||||
if (m_ptrEntity->Get<CVariableEntity>() && m_ptrEntity->Get<CVariableEntity>()->IsReadOnly()) return true;
|
||||
if (m_ptrParent) return m_ptrParent->IsConst();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CEntityValueNode::IsDeclaration() const
|
||||
{
|
||||
// Default implementation
|
||||
return m_ptrEntity->Get<CVariableEntity>();
|
||||
}
|
||||
|
||||
CSimpleTypeValueNode::CSimpleTypeValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
||||
CEntityValueNode(ptrEntity, ptrParent)
|
||||
{}
|
||||
|
||||
CSimpleTypeValueNode::CSimpleTypeValueNode(const CSimpleTypeValueNode& rValueNode, CEntityPtr ptrEntity,
|
||||
const CValueNodePtr ptrParent) :
|
||||
CEntityValueNode(rValueNode, ptrEntity, ptrParent), m_varValue(rValueNode.m_varValue),
|
||||
m_lstExpression(rValueNode.m_lstExpression), m_eValueDef(rValueNode.m_eValueDef)
|
||||
{}
|
||||
|
||||
CValueNodePtr CSimpleTypeValueNode::CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const
|
||||
{
|
||||
return std::make_shared<std::decay_t<std::remove_pointer_t<decltype(this)>>>(*this, ptrEntity, ptrParent);
|
||||
}
|
||||
|
||||
void CSimpleTypeValueNode::ProcessValueAssignment(const CTokenList& rlstExpression)
|
||||
{
|
||||
CLog log("Processing declaration value assignment...");
|
||||
|
||||
if (!m_ptrEntity) throw CCompileException("Internal error: no entity assigned to the value node.");
|
||||
|
||||
const CDeclarationEntity* pSystemTypeEntity = m_ptrEntity->Get<CDeclarationEntity>();
|
||||
if (!pSystemTypeEntity)
|
||||
throw CCompileException("Internal error: type mismatch between value node and entity type.");
|
||||
|
||||
// Process the assignment expression and convert the result in the target type.
|
||||
std::pair<CConstVariant, bool> prValue{0, false};
|
||||
switch (pSystemTypeEntity->GetBaseType())
|
||||
{
|
||||
case sdv::idl::EDeclType::decltype_short:
|
||||
log << "Processing system type value node of type 'int16/short'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<int16_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<int64_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_long:
|
||||
log << "Processing system type value node of type 'int32/long'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<int32_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<int64_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_long_long:
|
||||
log << "Processing system type value node of type 'int64/long long'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<int64_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<int64_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_unsigned_short:
|
||||
log << "Processing system type value node of type 'uint16/unsigned short'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<uint16_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_unsigned_long:
|
||||
log << "Processing system type value node of type 'uint32/unsigned long'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<uint32_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_unsigned_long_long:
|
||||
log << "Processing system type value node of type 'uint64/unsigned long long'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<uint64_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_char:
|
||||
log << "Processing system type value node of type 'int8/UTF-8 or ASCII char'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<int8_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<int64_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_char16:
|
||||
log << "Processing system type value node of type 'UTF-16 char'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<uint16_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_char32:
|
||||
log << "Processing system type value node of type 'UTF-32 char'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<uint32_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_wchar:
|
||||
log << "Processing system type value node of type 'wchar'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
if (sizeof(wchar_t) == 2)
|
||||
prValue.first.Convert<uint16_t>();
|
||||
else
|
||||
prValue.first.Convert<uint32_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_float:
|
||||
log << "Processing system type value node of type 'float'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<float>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<long double>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_double:
|
||||
log << "Processing system type value node of type 'double'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<double>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<long double>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_long_double:
|
||||
log << "Processing system type value node of type 'long double'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<long double>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<long double>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_fixed:
|
||||
log << "Processing system type value node of type 'fixed'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<fixed>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<long double>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_boolean:
|
||||
log << "Processing system type value node of type 'boolean'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<bool>();
|
||||
log << "Simple type value node has calculated value " << (prValue.first.Get<bool>() ? "'true'" : "'false'") << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_native:
|
||||
log << "Processing system type value node of type 'native'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<size_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<size_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_octet:
|
||||
log << "Processing system type value node of type 'uint8/octet'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
||||
prValue.first.Convert<uint8_t>();
|
||||
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_string:
|
||||
log << "Processing system type value node of type 'ASCII string'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessStringExpression(rlstExpression);
|
||||
prValue.first.Convert<std::string>();
|
||||
log << "Simple type value node has constructed string \"" << prValue.first.Get<std::string>() << "\"..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_u8string:
|
||||
log << "Processing system type value node of type 'UTF-8 string'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessStringExpression(rlstExpression);
|
||||
prValue.first.Convert<std::string>();
|
||||
log << "Simple type value node has constructed string \"" << prValue.first.Get<std::string>() << "\"..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_u16string:
|
||||
log << "Processing system type value node of type 'UTF-16 string'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessStringExpression(rlstExpression);
|
||||
prValue.first.Convert<std::u16string>();
|
||||
log << "Simple type value node has constructed string..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_u32string:
|
||||
log << "Processing system type value node of type 'UTF-32 string'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessStringExpression(rlstExpression);
|
||||
prValue.first.Convert<std::u32string>();
|
||||
log << "Simple type value node has constructed string..." << std::endl;
|
||||
break;
|
||||
case sdv::idl::EDeclType::decltype_wstring:
|
||||
log << "Processing system type value node of type 'wstring'..." << std::endl;
|
||||
prValue = pSystemTypeEntity->ProcessStringExpression(rlstExpression);
|
||||
prValue.first.Convert<std::wstring>();
|
||||
log << "Simple type value node has constructed string..." << std::endl;
|
||||
break;
|
||||
default:
|
||||
log << "Processing system type value node of unknown type..." << std::endl;
|
||||
throw CCompileException("Internal error: expression build error.");
|
||||
}
|
||||
|
||||
// Check for a dynamic result
|
||||
if (prValue.second)
|
||||
SetDynamicValue(rlstExpression);
|
||||
else
|
||||
SetFixedValue(prValue.first, rlstExpression);
|
||||
}
|
||||
|
||||
void CSimpleTypeValueNode::SetFixedValue(const CConstVariant& rvarValue, const CTokenList& rlstExpression)
|
||||
{
|
||||
CLog log;
|
||||
switch (m_eValueDef)
|
||||
{
|
||||
case EValueDef::dynamic:
|
||||
log << "The value was re-assigned; the previous value was a dynamic value..." << std::endl;
|
||||
break;
|
||||
case EValueDef::fixed:
|
||||
log << "The value was re-assigned; the previous value was a fixed value of " <<
|
||||
m_varValue.GetAsString() << "..." << std::endl;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_eValueDef = EValueDef::fixed;
|
||||
|
||||
log << "The system type value node was set to a fixed value of " << rvarValue.GetAsString() << "..." << std::endl;
|
||||
|
||||
m_varValue = rvarValue;
|
||||
m_lstExpression = rlstExpression;
|
||||
}
|
||||
|
||||
void CSimpleTypeValueNode::SetDynamicValue(const CTokenList& rlstExpression)
|
||||
{
|
||||
CLog log;
|
||||
switch (m_eValueDef)
|
||||
{
|
||||
case EValueDef::dynamic:
|
||||
log << "The value was re-assigned; the previous value was a dynamic value..." << std::endl;
|
||||
break;
|
||||
case EValueDef::fixed:
|
||||
log << "The value was re-assigned; the previous value was a fixed value of " <<
|
||||
m_varValue.GetAsString() << "..." << std::endl;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_eValueDef = EValueDef::dynamic;
|
||||
|
||||
log << "The system type value node was set to a dynamic value..." << std::endl;
|
||||
|
||||
m_lstExpression = rlstExpression;
|
||||
}
|
||||
|
||||
CArrayValueNode::CArrayValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
||||
CEntityValueNode(ptrEntity, ptrParent)
|
||||
{}
|
||||
|
||||
CArrayValueNode::CArrayValueNode(const CArrayValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
||||
CEntityValueNode(rValueNode, ptrEntity, ptrParent), m_lstArraySizeExpression(rValueNode.m_lstArraySizeExpression),
|
||||
m_eSizeDef(rValueNode.m_eSizeDef)
|
||||
{
|
||||
m_vecChildren = rValueNode.m_vecChildren;
|
||||
}
|
||||
|
||||
CValueNodePtr CArrayValueNode::CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const
|
||||
{
|
||||
return std::make_shared<std::decay_t<std::remove_pointer_t<decltype(this)>>>(*this, ptrEntity, ptrParent);
|
||||
}
|
||||
|
||||
void CArrayValueNode::ProcessValueAssignment(const CTokenList& rlstExpression)
|
||||
{
|
||||
CLog log("Process array value node...");
|
||||
|
||||
if (rlstExpression.End())
|
||||
throw CCompileException(rlstExpression.LastValid(), "Expecting left curly bracket '{'");
|
||||
|
||||
// The array assignment is placed between brackets.
|
||||
// In case the type is a character, the array might also be defined as a string literal
|
||||
// Or identified as a value sequence.
|
||||
|
||||
if (rlstExpression.Current() == "{")
|
||||
{
|
||||
// Skip the bracket
|
||||
++rlstExpression;
|
||||
|
||||
// Process the child nodes
|
||||
ProcessChildNodes(rlstExpression);
|
||||
|
||||
// Expecting '}'
|
||||
if (rlstExpression.End() || rlstExpression.Current() != "}")
|
||||
throw CCompileException(rlstExpression.LastValid(), "Expecting right curly bracket '}'");
|
||||
++rlstExpression;
|
||||
}
|
||||
else if (rlstExpression.Current().GetType() == ETokenType::token_literal && rlstExpression.Current().IsString())
|
||||
{
|
||||
// Process the string node
|
||||
ProcessStringNode(rlstExpression.Current());
|
||||
++rlstExpression;
|
||||
}
|
||||
else
|
||||
throw CCompileException(rlstExpression.LastValid(), "Expecting left curly bracket '{'");
|
||||
}
|
||||
|
||||
void CArrayValueNode::ProcessChildNodes(const CTokenList& rlstExpression)
|
||||
{
|
||||
CLog log;
|
||||
CValueNodePtr ptrValueTemplateUnbound;
|
||||
if (IsUnbound())
|
||||
{
|
||||
// The array should have one node. This is a template for all the nodes.
|
||||
if (m_vecChildren.size() != 1)
|
||||
throw CCompileException(rlstExpression.LastValid(), "Internal error: the size of the array value nodes is not as expected for the"
|
||||
" unbound array.");
|
||||
ptrValueTemplateUnbound = std::move(m_vecChildren[0]);
|
||||
|
||||
log << "Processing ubound element nodes..." << std::endl;
|
||||
}
|
||||
else
|
||||
log << "Processing " << m_vecChildren.size() << " element nodes..." << std::endl;
|
||||
|
||||
size_t nIndex = 0;
|
||||
while (!rlstExpression.End() && rlstExpression.Current() != "}")
|
||||
{
|
||||
// Check for a comma separator.
|
||||
if (nIndex)
|
||||
{
|
||||
if (rlstExpression.Current() != ",")
|
||||
throw CCompileException(rlstExpression.LastValid(), "Missing comma ',' for value separation.");
|
||||
++rlstExpression;
|
||||
}
|
||||
|
||||
// Extend the array for unbound
|
||||
if (IsUnbound())
|
||||
{
|
||||
m_vecChildren.resize(nIndex + 1);
|
||||
m_vecChildren[nIndex] = ptrValueTemplateUnbound->CreateCopy(m_ptrEntity, shared_from_this());
|
||||
}
|
||||
|
||||
// Does the size fit?
|
||||
if (nIndex >= m_vecChildren.size())
|
||||
throw CCompileException(rlstExpression.LastValid(), "The assignment doesn't fit the amount of elements.");
|
||||
|
||||
log << "Processing element node #" << nIndex << std::endl;
|
||||
m_vecChildren[nIndex]->ProcessValueAssignment(rlstExpression);
|
||||
|
||||
// Next node
|
||||
nIndex++;
|
||||
}
|
||||
|
||||
// Check whether the index corresponds to the size of the aray.
|
||||
if (nIndex != m_vecChildren.size())
|
||||
throw CCompileException(rlstExpression.LastValid(), "Missing elements for array assignment.");
|
||||
}
|
||||
|
||||
void CArrayValueNode::ProcessStringNode(const CToken& rToken)
|
||||
{
|
||||
CLog log;
|
||||
|
||||
if (!rToken.IsString())
|
||||
throw CCompileException(rToken, "Internal error: token is expected to be a string literal.");
|
||||
|
||||
|
||||
// Check for unbound arrays.
|
||||
CValueNodePtr ptrValueTemplateUnbound;
|
||||
if (IsUnbound())
|
||||
{
|
||||
// The array should have one node. This is a template for all the nodes.
|
||||
if (m_vecChildren.size() != 1)
|
||||
throw CCompileException(rToken, "Internal error: the size of the array value nodes is not as expected for the"
|
||||
" unbound array.");
|
||||
ptrValueTemplateUnbound = std::move(m_vecChildren[0]);
|
||||
|
||||
log << "Processing ubound element nodes..." << std::endl;
|
||||
}
|
||||
else
|
||||
log << "Processing " << m_vecChildren.size() << " element nodes..." << std::endl;
|
||||
|
||||
// Determine the start position of the string
|
||||
const std::string ssValue = static_cast<std::string>(rToken);
|
||||
size_t nStart = ssValue.find('"');
|
||||
if (nStart == std::string::npos)
|
||||
throw CCompileException(rToken, "Internal error: invalid string token.");
|
||||
nStart++;
|
||||
|
||||
// For raw string, determine the delimiter
|
||||
std::string ssDelimiter = "\"";
|
||||
bool bRaw = false;
|
||||
if (rToken.IsRawString())
|
||||
{
|
||||
bRaw = true;
|
||||
size_t nStart2 = ssValue.find('(', nStart);
|
||||
if (nStart2 == std::string::npos)
|
||||
throw CCompileException(rToken, "Internal error: invalid raw string token.");
|
||||
ssDelimiter = ")" + ssValue.substr(nStart, nStart2 - nStart) + "\"";
|
||||
nStart = nStart2;
|
||||
}
|
||||
|
||||
// Check whether the base type corresponds to the string and count the characters.
|
||||
bool bError = true;
|
||||
uint32_t uiByteCnt = 0;
|
||||
std::vector<CConstVariant> lstValues;
|
||||
switch (GetDeclEntity()->GetBaseType())
|
||||
{
|
||||
case sdv::idl::EDeclType::decltype_char:
|
||||
{
|
||||
if (!rToken.IsAscii() && !rToken.IsUtf8()) break;
|
||||
bError = false;
|
||||
std::string ssText;
|
||||
InterpretCText(ssValue.c_str() + nStart, ssDelimiter.c_str(), ssText, uiByteCnt, bRaw, rToken.IsAscii());
|
||||
for (char c : ssText)
|
||||
lstValues.push_back(c);
|
||||
break;
|
||||
}
|
||||
case sdv::idl::EDeclType::decltype_wchar:
|
||||
{
|
||||
if (!rToken.IsWide()) break;
|
||||
bError = false;
|
||||
std::wstring ssText;
|
||||
InterpretCText(ssValue.c_str() + nStart, ssDelimiter.c_str(), ssText, uiByteCnt, bRaw);
|
||||
for (wchar_t c : ssText)
|
||||
lstValues.push_back(c);
|
||||
break;
|
||||
}
|
||||
case sdv::idl::EDeclType::decltype_char16:
|
||||
{
|
||||
if (!rToken.IsUtf16()) break;
|
||||
bError = false;
|
||||
std::u16string ssText;
|
||||
InterpretCText(ssValue.c_str() + nStart, ssDelimiter.c_str(), ssText, uiByteCnt, bRaw);
|
||||
for (char16_t c : ssText)
|
||||
lstValues.push_back(c);
|
||||
break;
|
||||
}
|
||||
case sdv::idl::EDeclType::decltype_char32:
|
||||
{
|
||||
if (!rToken.IsUtf32()) break;
|
||||
bError = false;
|
||||
std::u32string ssText;
|
||||
InterpretCText(ssValue.c_str() + nStart, ssDelimiter.c_str(), ssText, uiByteCnt, bRaw);
|
||||
for (char32_t c : ssText)
|
||||
lstValues.push_back(c);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw CCompileException(rToken, "Expecting left curly bracket '{'");
|
||||
break;
|
||||
}
|
||||
if (bError)
|
||||
throw CCompileException(rToken, "Invalid string type for the assignment");
|
||||
|
||||
// Add the terminateing zero
|
||||
lstValues.push_back(0);
|
||||
|
||||
// Extend the array for unbound
|
||||
if (IsUnbound())
|
||||
{
|
||||
m_vecChildren.resize(lstValues.size());
|
||||
for (size_t nIndex = 0; nIndex < lstValues.size(); nIndex++)
|
||||
m_vecChildren[nIndex] = ptrValueTemplateUnbound->CreateCopy(m_ptrEntity, shared_from_this());
|
||||
}
|
||||
|
||||
// Does the size fit?
|
||||
if (lstValues.size() != m_vecChildren.size())
|
||||
throw CCompileException(rToken, "The assignment doesn't fit the amount of elements.");
|
||||
|
||||
// Assign the values
|
||||
for (size_t nIndex = 0; nIndex < m_vecChildren.size(); nIndex++)
|
||||
{
|
||||
log << "Processing element node #" << nIndex << std::endl;
|
||||
CSimpleTypeValueNode* pValueNode = m_vecChildren[nIndex]->Get<CSimpleTypeValueNode>();
|
||||
if (!pValueNode)
|
||||
throw CCompileException(rToken, "Internal error: the array element is not of type simple value node.");
|
||||
|
||||
CTokenList lstExpression;
|
||||
lstExpression.push_back(rToken);
|
||||
pValueNode->SetFixedValue(lstValues[0], lstExpression);
|
||||
}
|
||||
}
|
||||
|
||||
void CArrayValueNode::SetFixedSize(size_t nSize, const CTokenList& rlstExpression)
|
||||
{
|
||||
CLog log;
|
||||
if constexpr (std::is_signed_v<size_t>)
|
||||
{
|
||||
if (static_cast<int64_t>(nSize) < 0)
|
||||
throw CCompileException("Internal error: array index is negative.");
|
||||
}
|
||||
|
||||
if (m_eSizeDef != ESizeDef::not_defined)
|
||||
throw CCompileException("Internal error: size of the value array was defined more than once.");
|
||||
m_eSizeDef = ESizeDef::fixed;
|
||||
|
||||
// Allocate the array with empty value pointers.
|
||||
m_vecChildren.resize(nSize);
|
||||
log << "Array set to a fixed size of " << nSize << "..." << std::endl;
|
||||
|
||||
// Copy the token list resulting in the size.
|
||||
m_lstArraySizeExpression = rlstExpression;
|
||||
}
|
||||
|
||||
void CArrayValueNode::SetDynamicSize(size_t nSize, const CTokenList& rlstExpression)
|
||||
{
|
||||
if (IsConst()) throw CCompileException("Cannot use a value of a variable declaration as size within a const declaration.");
|
||||
|
||||
CLog log;
|
||||
if (m_eSizeDef != ESizeDef::not_defined)
|
||||
throw CCompileException("Internal error: size of the value array was defined more than once.");
|
||||
m_eSizeDef = ESizeDef::dynamic;
|
||||
|
||||
// Allocate the array with one element.
|
||||
m_vecChildren.resize(nSize);
|
||||
log << "Array set to a dynamic size based on a variable of " << nSize << "..." << std::endl;
|
||||
|
||||
// Copy the token list resulting in the size.
|
||||
m_lstArraySizeExpression = rlstExpression;
|
||||
}
|
||||
|
||||
void CArrayValueNode::SetFixedSizeUnbound()
|
||||
{
|
||||
CLog log;
|
||||
if (m_eSizeDef != ESizeDef::not_defined)
|
||||
throw CCompileException("Internal error: size of the value array was defined more than once.");
|
||||
|
||||
m_eSizeDef = ESizeDef::fixed_unbound;
|
||||
|
||||
// Allocate the array with one element.
|
||||
m_vecChildren.resize(1);
|
||||
log << "Array set to be unbound..." << std::endl;
|
||||
}
|
||||
|
||||
const CValueNodePtr& CArrayValueNode::operator[](size_t nIndex) const
|
||||
{
|
||||
if (m_eSizeDef == ESizeDef::not_defined)
|
||||
throw CCompileException("Internal error: accessing the array can only take place after the size has been defined.");
|
||||
|
||||
if constexpr (std::is_signed_v<size_t>)
|
||||
{
|
||||
if (static_cast<int64_t>(nIndex) < 0)
|
||||
throw CCompileException("Internal error: array index is negative.");
|
||||
}
|
||||
|
||||
return m_vecChildren[nIndex];
|
||||
}
|
||||
|
||||
CValueNodePtr& CArrayValueNode::operator[](size_t nIndex)
|
||||
{
|
||||
if (m_eSizeDef == ESizeDef::not_defined)
|
||||
throw CCompileException("Internal error: accessing the array can only take place after the size has been defined.");
|
||||
|
||||
if constexpr (std::is_signed_v<size_t>)
|
||||
{
|
||||
if (static_cast<int64_t>(nIndex) < 0)
|
||||
throw CCompileException("Internal error: array index is negative.");
|
||||
}
|
||||
|
||||
return m_vecChildren[nIndex];
|
||||
}
|
||||
|
||||
size_t CArrayValueNode::GetSize() const
|
||||
{
|
||||
return m_vecChildren.size();
|
||||
}
|
||||
|
||||
bool CArrayValueNode::IsArray() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CArrayValueNode::IsUnbound() const
|
||||
{
|
||||
return m_eSizeDef == ESizeDef::fixed_unbound;
|
||||
}
|
||||
|
||||
std::string CArrayValueNode::GetSizeExpression() const
|
||||
{
|
||||
if (IsUnbound()) return std::string();
|
||||
std::string ss;
|
||||
for (const CToken& rtoken : m_lstArraySizeExpression)
|
||||
ss += static_cast<std::string>(rtoken);
|
||||
return ss;
|
||||
}
|
||||
|
||||
std::string CArrayValueNode::GetDeclTypeStr(bool bResolveTypedef) const
|
||||
{
|
||||
if (!GetSize()) return "[]"; // Not resolved yet...
|
||||
|
||||
CValueNodePtr ptrValue = (*this)[0];
|
||||
if (!ptrValue) return std::string("[" + std::to_string(GetSize()) + "]"); // Not resolved yet...
|
||||
return ptrValue->GetDeclTypeStr(bResolveTypedef) + "[" + std::to_string(GetSize()) + "]";
|
||||
}
|
||||
|
||||
CCompoundTypeValueNode::CCompoundTypeValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
||||
CEntityValueNode(ptrEntity, ptrParent)
|
||||
{}
|
||||
|
||||
CCompoundTypeValueNode::CCompoundTypeValueNode(const CCompoundTypeValueNode& rValueNode, CEntityPtr ptrEntity,
|
||||
const CValueNodePtr ptrParent) : CEntityValueNode(rValueNode, ptrEntity, ptrParent)
|
||||
{}
|
||||
|
||||
CValueNodePtr CCompoundTypeValueNode::CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const
|
||||
{
|
||||
return std::make_shared<std::decay_t<std::remove_pointer_t<decltype(this)>>>(*this, ptrEntity, ptrParent);
|
||||
}
|
||||
|
||||
void CCompoundTypeValueNode::ProcessValueAssignment(const CTokenList& rlstExpression)
|
||||
{
|
||||
CLog log("Processing struct value node...");
|
||||
|
||||
if (rlstExpression.End())
|
||||
throw CCompileException(rlstExpression.LastValid(), "Missing assignment");
|
||||
if (!m_ptrEntity)
|
||||
throw CCompileException(rlstExpression.LastValid(), "Internal error: a value node should be assigned to an entity.");
|
||||
|
||||
// There are two options: either a scoped name representing a type (or typedef) being of the same type (identical name), or a
|
||||
// compound value (between curly brackets '{...}').
|
||||
if (rlstExpression.Current() != "{") // Type value assignment
|
||||
{
|
||||
CValueNodePtr ptrValue = m_ptrEntity->FindValue(rlstExpression);
|
||||
|
||||
// Check if the original type of the assginee and the assigned are identical. For this both entities must be declarations.
|
||||
if (!GetDeclEntity()->Get<CDeclarationEntity>())
|
||||
throw CCompileException(rlstExpression.LastValid(), "Internal error: the assignee entity must be a declaration entity.");
|
||||
|
||||
// Assignment can only work if the types are identical. This is regardless of the typedefs that have been made from the
|
||||
// type.
|
||||
if (GetDeclTypeStr(true) != ptrValue->GetDeclTypeStr(true))
|
||||
throw CCompileException(rlstExpression.LastValid(), "For '", GetDeclEntity()->GetName(), "', cannot assign '",
|
||||
ptrValue->GetDeclTypeStr(true), "' to '", ptrValue->GetDeclTypeStr(true), "'; base types are different.");
|
||||
|
||||
// Replace the value by the value chain of the assigned to the assignee.
|
||||
m_ptrEntity->ValueRef() = ptrValue->CreateCopy(m_ptrEntity, m_ptrParent);
|
||||
} else // Compound value assignment
|
||||
{
|
||||
++rlstExpression; // Skip left bracket
|
||||
|
||||
// Process the child nodes
|
||||
ProcessChildNodes(rlstExpression);
|
||||
|
||||
// Expecting '}'
|
||||
if (rlstExpression.End() || rlstExpression.Current() != "}")
|
||||
throw CCompileException(rlstExpression.LastValid(), "Expecting right curly bracket '}'");
|
||||
++rlstExpression; // Skip right bracket
|
||||
}
|
||||
}
|
||||
|
||||
CInterfaceValueNode::CInterfaceValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
||||
CEntityValueNode(ptrEntity, ptrParent)
|
||||
{}
|
||||
|
||||
CInterfaceValueNode::CInterfaceValueNode(const CInterfaceValueNode& rValueNode, CEntityPtr ptrEntity,
|
||||
const CValueNodePtr ptrParent) :
|
||||
CEntityValueNode(rValueNode, ptrEntity, ptrParent)
|
||||
{}
|
||||
|
||||
CValueNodePtr CInterfaceValueNode::CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const
|
||||
{
|
||||
return std::make_shared<std::decay_t<std::remove_pointer_t<decltype(this)>>>(*this, ptrEntity, ptrParent);
|
||||
}
|
||||
|
||||
void CInterfaceValueNode::ProcessValueAssignment(const CTokenList& rlstExpression)
|
||||
{
|
||||
CLog log("Processing declaration value assignment...");
|
||||
|
||||
if (!m_ptrEntity) throw CCompileException("Internal error: no entity assigned to the value node.");
|
||||
|
||||
const CDeclarationEntity* pSystemTypeEntity = m_ptrEntity->Get<CDeclarationEntity>();
|
||||
if (!pSystemTypeEntity)
|
||||
throw CCompileException("Internal error: type mismatch between value node and entity type.");
|
||||
|
||||
// Only "null" and "0" are allowed.
|
||||
if ((!m_ptrEntity->GetParserRef().GetEnvironment().InterfaceTypeExtension() || rlstExpression.Current() != "null") &&
|
||||
rlstExpression.Current() != "0")
|
||||
throw CCompileException(rlstExpression.Current(),
|
||||
"Error: assignment of interface values is only possible with the value \"null\".");
|
||||
|
||||
// Skip the value.
|
||||
++rlstExpression;
|
||||
}
|
||||
|
||||
|
||||
CValueNodePtr CCompoundTypeValueNode::Member(const std::string& rssName) const
|
||||
{
|
||||
// Check the entity names of the child value nodes.
|
||||
// ATTENTION: The child value nodes are copies of the original definition. They still contain the link to the declarations
|
||||
// that were part of the definition. The entity belonging to a declaration of a compound type does not have any children (the
|
||||
// entity itself is just the declaration and not the definition):
|
||||
for (const CValueNodePtr& rptrValue : m_vecChildren)
|
||||
if (rptrValue->GetDeclEntity()->GetName() == rssName) return rptrValue;
|
||||
return nullptr; // Value not found.
|
||||
}
|
||||
|
||||
CEnumValueNode::CEnumValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
||||
CEntityValueNode(ptrEntity, ptrParent)
|
||||
{}
|
||||
|
||||
CEnumValueNode::CEnumValueNode(const CEnumValueNode& rValueNode, CEntityPtr ptrEntity,
|
||||
const CValueNodePtr ptrParent) :
|
||||
CEntityValueNode(rValueNode, ptrEntity, ptrParent), m_ptrEntryVal(rValueNode.m_ptrEntryVal),
|
||||
m_lstExpression(rValueNode.m_lstExpression)
|
||||
{}
|
||||
|
||||
CValueNodePtr CEnumValueNode::CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const
|
||||
{
|
||||
return std::make_shared<std::decay_t<std::remove_pointer_t<decltype(this)>>>(*this, ptrEntity, ptrParent);
|
||||
}
|
||||
|
||||
void CEnumValueNode::ProcessValueAssignment(const CTokenList& rlstExpression)
|
||||
{
|
||||
CLog log("Processing enum value assignment...");
|
||||
// The assignment is done using the enum entry type. Find the scoped name. This could be the enum value. Check the type first.
|
||||
CTokenList rlstExpressionTemp = rlstExpression;
|
||||
std::pair<std::string, CEntityPtr> prEntity = GetDeclEntity()->GetTypeEntity()->ProcessScopedName(rlstExpression, true);
|
||||
// If not an enum value from the type, use as scope the parent of the current enum to search for other declarations.
|
||||
if (!prEntity.second) prEntity = GetDeclEntity()->GetParentEntity()->ProcessScopedName(rlstExpressionTemp, true);
|
||||
if (!prEntity.second) throw CCompileException(rlstExpression.LastValid(), "Expecting an enum value.");
|
||||
|
||||
// This could either be an assignment of an enum to another enum or an enum entry to an enum.
|
||||
log << "The to be assigned type is '" << prEntity.second->GetDeclTypeStr(true) << "'..." << std::endl;
|
||||
log << "The assignee type is '" << GetDeclEntity()->GetDeclTypeStr(true) << "'..." << std::endl;
|
||||
if (prEntity.second->GetDeclTypeStr(true) == GetDeclEntity()->GetDeclTypeStr(true))
|
||||
{
|
||||
if (!prEntity.second->ValueRef())
|
||||
throw CCompileException(rlstExpression.LastValid(), "Internal error: the enum doesn't have an assigned value.");
|
||||
if (!prEntity.second->ValueRef()->Get<CEnumValueNode>())
|
||||
throw CCompileException(rlstExpression.LastValid(), "Internal error: the enum doesn't have an assigned enum value.");
|
||||
m_ptrEntryVal = prEntity.second->ValueRef()->Get<CEnumValueNode>()->m_ptrEntryVal;
|
||||
} else if (prEntity.second->GetParentEntity()->GetDeclTypeStr(true) == GetDeclEntity()->GetDeclTypeStr(true))
|
||||
{
|
||||
log << "Assigning enum entry..." << std::endl;
|
||||
m_ptrEntryVal = prEntity.second;
|
||||
} else
|
||||
throw CCompileException(rlstExpression.LastValid(), "Invalid enum value; enum types are not identical.");
|
||||
log << "Enum entity was assigned value '" << m_ptrEntryVal->GetParentEntity()->GetName() << "::" <<
|
||||
m_ptrEntryVal->GetName() << "'..." << std::endl;
|
||||
}
|
||||
|
||||
const CConstVariant& CEnumValueNode::Variant() const
|
||||
{
|
||||
static CConstVariant temp;
|
||||
if (!m_ptrEntryVal) return temp;
|
||||
if (!m_ptrEntryVal->ValueRef()) return temp;
|
||||
const CSimpleTypeValueNode* pValueNode = m_ptrEntryVal->ValueRef()->Get<CSimpleTypeValueNode>();
|
||||
if (!pValueNode) return temp;
|
||||
return pValueNode->Variant();
|
||||
}
|
||||
|
||||
std::string CEnumValueNode::String() const
|
||||
{
|
||||
if (!m_ptrEntryVal) return std::string();
|
||||
return m_ptrEntryVal->GetParentEntity()->GetScopedName() + "::" + m_ptrEntryVal->GetName();
|
||||
}
|
||||
584
sdv_executables/sdv_idl_compiler/entities/entity_value.h
Normal file
584
sdv_executables/sdv_idl_compiler/entities/entity_value.h
Normal file
@@ -0,0 +1,584 @@
|
||||
#ifndef ENTITIY_VALUE_H
|
||||
#define ENTITIY_VALUE_H
|
||||
|
||||
#include "entity_base.h"
|
||||
#include "../constvariant.h"
|
||||
#include "../token.h"
|
||||
#include "../tokenlist.h"
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
// Forward declarations
|
||||
class CDeclarationEntity;
|
||||
|
||||
/**
|
||||
* @brief The entity value node base class.
|
||||
* @details Entity values form a value tree made of all the values that are part of one assignment. Each value has its special
|
||||
* value grammar when used in a assignment. All entities have their own personal linked list, which can be formed from other
|
||||
* entities when they are defined as type of a declaration. Variable declarations can also be part of a larger linked list. Arrays
|
||||
* form their own links within the linked list
|
||||
* Examples:
|
||||
* @code
|
||||
* // Value tree for i: CSimpleTypeValueNode assigning the value 10.
|
||||
* int32 i = 10;
|
||||
*
|
||||
* // Value tree for S1: CCompoundTypeValueNode with child CSimpleTypeValueNode assigning the value 20.
|
||||
* struct S1
|
||||
* {
|
||||
* const int32 m_i1 = 10; // Value node for m_i1: CSimpleTypeValueNode assigning the value 10.
|
||||
* int32 m_i2 = 20; // Part of the value tree of S1.
|
||||
* };
|
||||
*
|
||||
* // Value tree for s1: sub-tree of S1 assigning the value 200 to m_i2.
|
||||
* S1 s1 = {200};
|
||||
*
|
||||
* // Value tree for S2: CCompoundTypeValueNode with children sub-tree of S1 and CSimpleTypeValueNode assigning the value 5.
|
||||
* struct S2 : S1
|
||||
* {
|
||||
* int32 m_i3 = 5; // Part of value tree of S2.
|
||||
* };
|
||||
*
|
||||
* // Value tree for s2: sub-tree of S2 assigning the value 150 to S1 and 100 to m_i3.
|
||||
* s2 = {{150}, 100};
|
||||
*
|
||||
* // Value tree for rgi: CArrayValueNode having two children assigning the value 10 and 20.
|
||||
* int32 rgi[2] = {10, 20};
|
||||
*
|
||||
* // Value tree for rgs3: CarrayValueNode having two children S1 assigning the values 1000 and 2000.
|
||||
* S1 rgs3[2] = {{1000}, {2000}};
|
||||
* @endcode
|
||||
*/
|
||||
class CEntityValueNode : public std::enable_shared_from_this<CEntityValueNode>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Can only be nullptr for const and declaration entities or when
|
||||
* creating a value node for a definition which will be copied in a larger declaration at a later stage.
|
||||
*/
|
||||
CEntityValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor with new parent and entity.
|
||||
* @param[in] rValueNode Reference to the value node to copy from.
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
*/
|
||||
CEntityValueNode(const CEntityValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Default destructor
|
||||
* @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly.
|
||||
*
|
||||
*/
|
||||
virtual ~CEntityValueNode() = default;
|
||||
|
||||
/**
|
||||
* @brief Create a copy of the value. Prototype to be implemented from derived class.
|
||||
* @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
* @return Returns a smart pointer of the copy of the value.
|
||||
*/
|
||||
virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Process the assignment. Prototype, to be implemented by derived value class.
|
||||
* @param[in] rlstExpression Reference to the expression token list.
|
||||
*/
|
||||
virtual void ProcessValueAssignment(const CTokenList& rlstExpression) = 0;
|
||||
|
||||
/**
|
||||
* @brief Process the child nodes.
|
||||
* @param[in] rlstExpression Reference to the expression token list.
|
||||
*/
|
||||
virtual void ProcessChildNodes(const CTokenList& rlstExpression);
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @brief Get the derived value class.
|
||||
* @tparam TValue The value class to request a pointer for.
|
||||
* @return Returns a pointer to the derived class or NULL when the requested class didn't derive from this value.
|
||||
*/
|
||||
template <class TValue>
|
||||
TValue* Get();
|
||||
template <class TValue>
|
||||
const TValue* Get() const;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Add a child node
|
||||
* @param[in] ptrChild Pointer to the child value node.
|
||||
*/
|
||||
void AddChild(CValueNodePtr ptrChild);
|
||||
|
||||
/**
|
||||
* @brief Get the parent node.
|
||||
* @return Returns a reference to the smart pointer of the parent node (if assigned).
|
||||
*/
|
||||
const CValueNodePtr& GetParentNode() const { return m_ptrParent; }
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @brief Get the attached declaration entity.
|
||||
* @return Returns the smart pointer to the entity.
|
||||
*/
|
||||
const CDeclarationEntity* GetDeclEntity() const { return m_ptrEntity->Get<CDeclarationEntity>(); }
|
||||
CDeclarationEntity* GetDeclEntity() { return m_ptrEntity->Get<CDeclarationEntity>(); }
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get the declaration type build from the value chain.
|
||||
* @details The declaration type consists of "<base type> <type identifier> <arrays>".
|
||||
* @param[in] bResolveTypedef When set, resolve the typedef type into the base type.
|
||||
* @return Returns a string with entity type.
|
||||
*/
|
||||
virtual std::string GetDeclTypeStr(bool bResolveTypedef) const;
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @brief Information functions.
|
||||
* @details Each function is implemented by an entity value class. The IsConst function traverses through the parents to find
|
||||
* out whether or not a value is a const value (this is the case when the entity holding the top most value is a const
|
||||
* entity.)
|
||||
* @return Returns the information.
|
||||
*/
|
||||
virtual bool IsArray() const { return false; }
|
||||
virtual bool IsUnbound() const { return false; }
|
||||
virtual bool IsConst() const;
|
||||
virtual bool IsDeclaration() const;
|
||||
virtual bool IsDynamic() const { return false; }
|
||||
virtual bool IsLiteral() const { return false; }
|
||||
virtual bool IsComplex() const { return false; }
|
||||
virtual bool HasParent() const{ return m_ptrParent ? true : false; }
|
||||
virtual bool HasChildren() const{ return !m_vecChildren.empty(); }
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
protected:
|
||||
CEntityPtr m_ptrEntity; ///< The entity implementing the value type.
|
||||
const CValueNodePtr m_ptrParent; ///< Parent value node - can be nullptr for root node.
|
||||
std::vector<CValueNodePtr> m_vecChildren; ///< Child nodes.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Entity declaration value (used as const variable assignment as well as default declaration assignment).
|
||||
*/
|
||||
class CSimpleTypeValueNode : public CEntityValueNode
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Can only be nullptr for upper most value level.
|
||||
*/
|
||||
CSimpleTypeValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor with new parent and entity.
|
||||
* @param[in] rValueNode Reference to the value node to copy from.
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
*/
|
||||
CSimpleTypeValueNode(const CSimpleTypeValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Default destructor
|
||||
* @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly.
|
||||
*
|
||||
*/
|
||||
virtual ~CSimpleTypeValueNode() override = default;
|
||||
|
||||
/**
|
||||
* @brief Create a copy of the value. Overload of CEntityValueNode::CreateCopy.
|
||||
* @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
* @return Returns a smart pointer of the copy of the value.
|
||||
*/
|
||||
virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const override;
|
||||
|
||||
/**
|
||||
* @brief Process the assignment. Overload of CEntityValueNode::ProcessValueAssignment.
|
||||
* @param[in] rlstExpression Reference to the expression token list.
|
||||
*/
|
||||
virtual void ProcessValueAssignment(const CTokenList& rlstExpression) override;
|
||||
|
||||
/**
|
||||
* @brief Set to a fixed value.
|
||||
* @remarks In case the entity is not a const entity, the value is considered to be a default value.
|
||||
* @param[in] rvarValue Reference to the fixed value.
|
||||
* @param[in] rlstExpression Reference to the expression list used to calculate the value.
|
||||
*/
|
||||
void SetFixedValue(const CConstVariant& rvarValue, const CTokenList& rlstExpression);
|
||||
|
||||
/**
|
||||
* @brief Set to a dynamic value
|
||||
* @remarks This function can only be called when the entity of any of the parent entities is not a const entity.
|
||||
* @param[in] rlstExpression Reference to the expression list used to calculate the value.
|
||||
*/
|
||||
void SetDynamicValue(const CTokenList& rlstExpression);
|
||||
|
||||
/**
|
||||
* @brief Is the value defined?
|
||||
* @return Returns 'true' when the value is defined; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsDefined() const { return m_eValueDef != EValueDef::not_defined; }
|
||||
|
||||
/**
|
||||
* @brief Is this value dynamic (will it be defined through a non-const variable definition)?
|
||||
* @return Returns 'true' when the value is dynamic; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsDynamic() const override { return m_eValueDef != EValueDef::dynamic; }
|
||||
|
||||
/**
|
||||
* @brief Get access to the underlying const variant.
|
||||
* @return The const variant storing the calculated value.
|
||||
*/
|
||||
const CConstVariant &Variant() const { return m_varValue; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief The definition of the size is either fixed or not fixed. When it is fixed, it could be derived from assigning its
|
||||
* values.
|
||||
*/
|
||||
enum class EValueDef
|
||||
{
|
||||
not_defined, ///< Currently not defined yet.
|
||||
fixed, ///< The value is fixed; could be used for const and declaration entities.
|
||||
dynamic, ///< The value is dependable on a variable declaration. Only to be used with a declaration entity.
|
||||
};
|
||||
|
||||
CConstVariant m_varValue; ///< The calculated value.
|
||||
CTokenList m_lstExpression; ///< List of tokens holding the value expression.
|
||||
EValueDef m_eValueDef = EValueDef::not_defined; ///< Dynamic value based on variables.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Entity array value (containing an array of value pointers).
|
||||
* @remarks When the array contains non-allocated value pointers, the array has been declared, but the values haven't been
|
||||
* assigned.
|
||||
*/
|
||||
class CArrayValueNode : public CEntityValueNode
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
*/
|
||||
CArrayValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor with new parent and entity.
|
||||
* @param[in] rValueNode Reference to the value node to copy from.
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
*/
|
||||
CArrayValueNode(const CArrayValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Default destructor
|
||||
* @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly.
|
||||
*
|
||||
*/
|
||||
virtual ~CArrayValueNode() override = default;
|
||||
|
||||
/**
|
||||
* @brief Create a copy of the value. Overload of CEntityValueNode::CreateCopy.
|
||||
* @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
* @return Returns a smart pointer of the copy of the value.
|
||||
*/
|
||||
virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const override;
|
||||
|
||||
/**
|
||||
* @brief Process the assignment. Overload of CEntityValueNode::ProcessValueAssignment.
|
||||
* @param[in] rlstExpression Reference to the expression token list.
|
||||
*/
|
||||
virtual void ProcessValueAssignment(const CTokenList& rlstExpression) override;
|
||||
|
||||
/**
|
||||
* @brief Process the child nodes. Overload of CEntityValueNode::ProcessChildNodes.
|
||||
* @param[in] rlstExpression Reference to the expression token list.
|
||||
*/
|
||||
void ProcessChildNodes(const CTokenList& rlstExpression) override;
|
||||
|
||||
/**
|
||||
* @brief Process the string nodes. This is an array processing function based on a string as character array.
|
||||
* @param[in] rToken Reference to the string literal token.
|
||||
*/
|
||||
void ProcessStringNode(const CToken& rToken);
|
||||
|
||||
/**
|
||||
* @brief Set the fixed size of the array when available during declaration.
|
||||
* @attention Must not be called after the value has been set to dynamic or set to a delayed fixed size.
|
||||
* @param[in] nSize The calculated size of the array.
|
||||
* @param[in] rlstExpression Reference to the expression list used to calculate the value.
|
||||
*/
|
||||
void SetFixedSize(size_t nSize, const CTokenList& rlstExpression);
|
||||
|
||||
/**
|
||||
* @brief Set the array to a dynamic size based on a variable declaration. This is only allowed for entities that are not
|
||||
* declared as const entity (where all the parent values are not defined as const).
|
||||
* @attention Must not be called after the value has been set to a fixed size (delayed or not).
|
||||
* @param[in] nSize The calculated size of the array.
|
||||
* @param[in] rlstExpression Reference to the expression list used to calculate the size.
|
||||
*/
|
||||
void SetDynamicSize(size_t nSize, const CTokenList& rlstExpression);
|
||||
|
||||
/**
|
||||
* @brief Set the array to a fixed size through its value assignment. This is only allowed for entities that are declared as
|
||||
* const entity (where one of the parents was defined as const).
|
||||
* @attention Must not be called after the value has been set to a fixed size (not delayed) or a dynamic size.
|
||||
*/
|
||||
void SetFixedSizeUnbound();
|
||||
|
||||
/**
|
||||
* @{
|
||||
* @brief Element access of the array.
|
||||
* @param[in] nIndex The index of the element. For dynamic arrays, only an index of 0 is allowed.
|
||||
* @return Returns a reference to the element.
|
||||
*/
|
||||
const CValueNodePtr& operator[](size_t nIndex) const;
|
||||
CValueNodePtr& operator[](size_t nIndex);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get the size of the array.
|
||||
* @return The size of the array.
|
||||
*/
|
||||
size_t GetSize() const;
|
||||
|
||||
/**
|
||||
* @brief This is an array entity.
|
||||
* @return Returns 'true'.
|
||||
*/
|
||||
virtual bool IsArray() const override;
|
||||
|
||||
/**
|
||||
* @brief Is the size of the array defined through the assignment?
|
||||
* @return Returns 'true' when the size of the array has to be defined through the assignment.
|
||||
*/
|
||||
virtual bool IsUnbound() const override;
|
||||
|
||||
/**
|
||||
* @brief Get the size expression.
|
||||
* @return The size expression string.
|
||||
*/
|
||||
std::string GetSizeExpression() const;
|
||||
|
||||
/**
|
||||
* @brief Get the declaration type build from the value chain. Overload of CEntityValueNode::GetDeclTypeStr.
|
||||
* @details The declaration type consists of "<base type> <type identifier> <arrays>".
|
||||
* @param[in] bResolveTypedef When set, resolve the typedef type into the base type.
|
||||
* @return Returns a string with entity type.
|
||||
*/
|
||||
virtual std::string GetDeclTypeStr(bool bResolveTypedef) const override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief The definition of the size is either fixed or not fixed. When it is fixed, it could be derived from assigning its
|
||||
* values.
|
||||
*/
|
||||
enum class ESizeDef
|
||||
{
|
||||
not_defined, ///< Currently not defined yet.
|
||||
fixed, ///< The size is fixed; could be used for const and declaration entities.
|
||||
dynamic, ///< The size is dependable on a variable declaration. Only to be used with a declaration entity.
|
||||
fixed_unbound, ///< The size is fixed, but gets defined during value assignment. Only to be used with a const
|
||||
///< entity.
|
||||
};
|
||||
|
||||
CTokenList m_lstArraySizeExpression; ///< List of tokens holding the array size expression.
|
||||
ESizeDef m_eSizeDef = ESizeDef::not_defined; ///< The size definition.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Entity struct value containing two arrays of value pointers, one array for the member const declarations and one array
|
||||
* for the member variable declarations.
|
||||
*/
|
||||
class CCompoundTypeValueNode : public CEntityValueNode
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Can only be nullptr when creating a value node for a definition
|
||||
* which will be copied in a larger declaration at a later stage.
|
||||
*/
|
||||
CCompoundTypeValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor with new parent and entity.
|
||||
* @param[in] rValueNode Reference to the value node to copy from.
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
*/
|
||||
CCompoundTypeValueNode(const CCompoundTypeValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Default destructor
|
||||
* @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly.
|
||||
*
|
||||
*/
|
||||
virtual ~CCompoundTypeValueNode() override = default;
|
||||
|
||||
/**
|
||||
* @brief Create a copy of the value. Overload of CEntityValueNode::CreateCopy.
|
||||
* @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
* @return Returns a smart pointer of the copy of the value.
|
||||
*/
|
||||
virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const override;
|
||||
|
||||
/**
|
||||
* @brief Process the assignment. Overload of CEntityValueNode::ProcessValueAssignment.
|
||||
* @param[in] rlstExpression Reference to the expression token list.
|
||||
*/
|
||||
virtual void ProcessValueAssignment(const CTokenList& rlstExpression) override;
|
||||
|
||||
/**
|
||||
* @brief Return the value for the supplied member.
|
||||
* @param[in] rssName Name Reference to the string object containing the name of the member.
|
||||
* @return Returns the value node smart pointer of the requested member, or nullptr when member doesn't have a value or
|
||||
* doesn't exist.
|
||||
*/
|
||||
CValueNodePtr Member(const std::string& rssName) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface value node.
|
||||
* @note The only assignable values of an interface are "null" and "0". No variable is allowed to be assigned and an interface
|
||||
* cannot be const.
|
||||
*/
|
||||
class CInterfaceValueNode : public CEntityValueNode
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Can only be nullptr for upper most value level.
|
||||
*/
|
||||
CInterfaceValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor with new parent and entity.
|
||||
* @param[in] rValueNode Reference to the value node to copy from.
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
*/
|
||||
CInterfaceValueNode(const CInterfaceValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Default destructor
|
||||
* @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly.
|
||||
*
|
||||
*/
|
||||
virtual ~CInterfaceValueNode() override = default;
|
||||
|
||||
/**
|
||||
* @brief Create a copy of the value. Overload of CEntityValueNode::CreateCopy.
|
||||
* @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
* @return Returns a smart pointer of the copy of the value.
|
||||
*/
|
||||
virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const override;
|
||||
|
||||
/**
|
||||
* @brief Process the assignment. Overload of CEntityValueNode::ProcessValueAssignment.
|
||||
* @param[in] rlstExpression Reference to the expression token list.
|
||||
*/
|
||||
virtual void ProcessValueAssignment(const CTokenList& rlstExpression) override;
|
||||
|
||||
/**
|
||||
* @brief Is this value dynamic (will it be defined through a non-const variable definition)? This is always the case.
|
||||
* @return Returns 'true' when the value is dynamic; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsDynamic() const override { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Enum entity declaration value.
|
||||
*/
|
||||
class CEnumValueNode : public CEntityValueNode
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Can only be nullptr for upper most value level.
|
||||
*/
|
||||
CEnumValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor with new parent and entity.
|
||||
* @param[in] rValueNode Reference to the value node to copy from.
|
||||
* @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
*/
|
||||
CEnumValueNode(const CEnumValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Default destructor
|
||||
* @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly.
|
||||
*
|
||||
*/
|
||||
virtual ~CEnumValueNode() override = default;
|
||||
|
||||
/**
|
||||
* @brief Create a copy of the value. Overload of CEntityValueNode::CreateCopy.
|
||||
* @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node.
|
||||
* @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr.
|
||||
* @return Returns a smart pointer of the copy of the value.
|
||||
*/
|
||||
virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const override;
|
||||
|
||||
/**
|
||||
* @brief Process the assignment. Overload of CEntityValueNode::ProcessValueAssignment.
|
||||
* @param[in] rlstExpression Reference to the expression token list.
|
||||
*/
|
||||
virtual void ProcessValueAssignment(const CTokenList& rlstExpression) override;
|
||||
|
||||
/**
|
||||
* @brief Is the value defined?
|
||||
* @return Returns 'true' when the value is defined; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsDefined() const { return m_ptrEntryVal ? true : false; }
|
||||
|
||||
/**
|
||||
* @brief Get access to the assigned const variant of the enum entry.
|
||||
* @return The const variant storing the value.
|
||||
*/
|
||||
const CConstVariant& Variant() const;
|
||||
|
||||
/**
|
||||
* @brief Get access to the assigned name string of the enum entry.
|
||||
* @return The name string of the enum entry.
|
||||
*/
|
||||
std::string String() const;
|
||||
|
||||
private:
|
||||
CEntityPtr m_ptrEntryVal; ///< The enum entry value when assigned.
|
||||
CTokenList m_lstExpression; ///< List of tokens holding the value expression.
|
||||
};
|
||||
|
||||
template <class TValue>
|
||||
TValue* CEntityValueNode::Get()
|
||||
{
|
||||
return dynamic_cast<TValue*>(this);
|
||||
}
|
||||
|
||||
template <class TValue>
|
||||
const TValue* CEntityValueNode::Get() const
|
||||
{
|
||||
return dynamic_cast<const TValue*>(this);
|
||||
}
|
||||
|
||||
#endif // !define(ENTITY_VALUE_H)
|
||||
213
sdv_executables/sdv_idl_compiler/entities/enum_entity.cpp
Normal file
213
sdv_executables/sdv_idl_compiler/entities/enum_entity.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
#include "enum_entity.h"
|
||||
#include "entity_value.h"
|
||||
#include "typedef_entity.h"
|
||||
#include "../exception.h"
|
||||
#include <set>
|
||||
|
||||
CEnumEntry::CEnumEntry(const CContextPtr& rptrContext, CEntityPtr ptrParent) :
|
||||
CDeclarationEntity(rptrContext, ptrParent)
|
||||
{}
|
||||
|
||||
std::string CEnumEntry::GetDeclTypeStr(bool /*bResolveTypedef*/) const
|
||||
{
|
||||
return GetScopedName();
|
||||
}
|
||||
|
||||
void CEnumEntry::Process()
|
||||
{
|
||||
// Get the base type of the enum entity and insert it in front of the declaration.
|
||||
const CEnumEntity* pEnumEntity = GetParentEntity()->Get<CEnumEntity>();
|
||||
if (!pEnumEntity) throw CCompileException("Internal error: expected an enum entity as parent.");
|
||||
CToken token(DeclTypeToString(pEnumEntity->GetEnumType()));
|
||||
PrependToken(token);
|
||||
|
||||
// Process as if normal declaration
|
||||
CDeclarationEntity::Process();
|
||||
}
|
||||
|
||||
CEnumEntity::CEnumEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent) :
|
||||
CDefinitionEntity(rptrContext, ptrParent)
|
||||
{
|
||||
m_typedecl.SetBaseType(sdv::idl::EDeclType::decltype_long);
|
||||
}
|
||||
|
||||
sdv::interface_t CEnumEntity::GetInterface(sdv::interface_id idInterface)
|
||||
{
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::IInterfaceAccess>())
|
||||
return static_cast<sdv::IInterfaceAccess*>(this);
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::idl::IEnumEntity>())
|
||||
return static_cast<sdv::idl::IEnumEntity*>(this);
|
||||
return CDefinitionEntity::GetInterface(idInterface);
|
||||
}
|
||||
|
||||
std::string CEnumEntity::GetDeclTypeStr(bool /*bResolveTypedef*/) const
|
||||
{
|
||||
return std::string("enum ") + GetScopedName();
|
||||
}
|
||||
|
||||
void CEnumEntity::GetBaseType(sdv::idl::EDeclType& reType, sdv::IInterfaceAccess*& rpType) const
|
||||
{
|
||||
reType = m_typedecl.GetBaseType();
|
||||
rpType = m_typedecl.GetTypeDefinition();
|
||||
}
|
||||
|
||||
void CEnumEntity::Process()
|
||||
{
|
||||
// The definition and declaration can be defined:
|
||||
// enum <enum_identifier>; --> forward declaration
|
||||
// enum <enum_identifier> {...}; --> enum definition
|
||||
// <enum_identifier> <decl_identifier>; --> enum variable declaration
|
||||
// <enum_identifier> <decl_identifier> = <enum_value>; --> enum variable declaration and assignment
|
||||
// enum <enum_identifier> <decl_identifier>; --> enum variable declaration
|
||||
// enum <enum_identifier> <decl_identifier> = <enum_value>; --> enum variable declaration and assignment
|
||||
// enum <enum_identifier> {...} <decl_identifier>; --> enum definition and variable declaration
|
||||
// enum <enum_identifier> {...} <decl_identifier> = <enum_value>; --> enum definition, variable declaration and assignment
|
||||
// enum {...} <decl_identifier>; --> anonymous enum definition and variable declaration
|
||||
// enum {...} <decl_identifier> = <enum_value>; --> anonymous enum definition, variable declaration and assignment
|
||||
// const enum <enum_identifier> <decl_identifier> = <enum_value>;
|
||||
// const <enum_identifier> <decl_identifier> = <enum_value>;
|
||||
// const enum {...} <decl_identifier> = <enum_value>;
|
||||
// typedef <enum_identifier> <type_identifier>;
|
||||
// typedef enum <enum_identifier> {...} <type_identifier>;
|
||||
// typedef <enum_identifier> <type_identifier>;
|
||||
// typedef enum <enum_identifier> {...} <type_identifier>;
|
||||
// typedef enum {...} <type_identifier>;
|
||||
|
||||
CDefinitionEntity::Process();
|
||||
|
||||
// If supported create the value node for the definition (this allows assignments of values to this entity).
|
||||
CreateValueNode();
|
||||
}
|
||||
|
||||
void CEnumEntity::ProcessDefinitionAddendum()
|
||||
{
|
||||
// Check for inheritance
|
||||
CToken token = GetToken();
|
||||
if (token != ":")
|
||||
{
|
||||
PrependToken(token);
|
||||
return;
|
||||
}
|
||||
|
||||
CLog log("Processing inheritance type...");
|
||||
|
||||
// Process the type
|
||||
m_typedecl = ProcessType();
|
||||
|
||||
// The base type must be an integral type and not an enum.
|
||||
if (!IsIntegralDeclType(m_typedecl.GetBaseType()) && m_typedecl.GetBaseType() != sdv::idl::EDeclType::decltype_enum)
|
||||
throw CCompileException("Expecting an integral type to inherit from.");
|
||||
}
|
||||
|
||||
void CEnumEntity::ProcessContent()
|
||||
{
|
||||
CLog log("Processing definition content...");
|
||||
|
||||
// An enum definition consists of one declaration statement with entries separated by a comma.
|
||||
CToken token = PeekToken();
|
||||
if (!token) return;
|
||||
if (token == "}") return;
|
||||
|
||||
// Expecting an enum entry
|
||||
CEntityPtr ptrEntry = CreateChild<CEnumEntry>(token.GetContext(), this);
|
||||
if (!ptrEntry) throw CCompileException("Internal error: could not create enum entry.");
|
||||
ptrEntry->Process();
|
||||
|
||||
// The entries should reside in the const members list
|
||||
// Check the values and create values where none is declared.
|
||||
// Separate between signed and unsigned.
|
||||
int64_t iSignedNext = 0;
|
||||
std::set<int64_t> setSigned;
|
||||
uint64_t uiUnsignedNext = 0;
|
||||
std::set<uint64_t> setUnsigned;
|
||||
for (CEntityPtr ptrMember : m_lstConstMembers)
|
||||
{
|
||||
CEnumEntry* pEntry = ptrMember->Get<CEnumEntry>();
|
||||
if (!pEntry) throw CCompileException("Internal error: expected only enum entries in an enumeration.");
|
||||
|
||||
// Do post processing
|
||||
pEntry->PostProcess();
|
||||
|
||||
// Get the value from the entity; if one was assigned.
|
||||
CSimpleTypeValueNode* pValue = pEntry->ValueRef() ? pEntry->ValueRef()->Get<CSimpleTypeValueNode>() : nullptr;
|
||||
if (!pValue)
|
||||
throw CCompileException("The value for '", ptrEntry->GetName(), "' must be a system type value.");
|
||||
|
||||
// Deal with signed and unsigned values
|
||||
if (IsSignedDeclType(m_typedecl.GetBaseType()))
|
||||
{
|
||||
// Is a value assigned?
|
||||
if (pValue->IsDefined())
|
||||
{
|
||||
// Check whether the value is already in use.
|
||||
int64_t iValue = pValue->Variant().Get<int64_t>();
|
||||
if (setSigned.find(iValue) != setSigned.end())
|
||||
throw CCompileException("The value for '", ptrEntry->GetName(), "' is already defined for another entry.");
|
||||
|
||||
// Store the value
|
||||
setSigned.insert(iValue);
|
||||
iSignedNext = iValue + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the next available value
|
||||
while (setSigned.find(iSignedNext) != setSigned.end())
|
||||
iSignedNext++;
|
||||
|
||||
// Create a value assignment
|
||||
CTokenList lstValueTokens;
|
||||
lstValueTokens.push_back(CToken(std::to_string(iSignedNext), ETokenLiteralType::token_literal_dec_integer));
|
||||
pValue->SetFixedValue(iSignedNext, lstValueTokens);
|
||||
|
||||
// Store the value
|
||||
setSigned.insert(iSignedNext);
|
||||
iSignedNext++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Is a value assigned?
|
||||
if (pValue->IsDefined())
|
||||
{
|
||||
// Check whether the value is already in use.
|
||||
uint64_t uiValue = pValue->Variant().Get<uint64_t>();
|
||||
if (setUnsigned.find(uiValue) != setUnsigned.end())
|
||||
throw CCompileException("The value for '", ptrEntry->GetName(), "' is already defined for another entry.");
|
||||
|
||||
// Store the value
|
||||
setUnsigned.insert(uiValue);
|
||||
uiUnsignedNext = uiValue + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the next available value
|
||||
while (setUnsigned.find(uiUnsignedNext) != setUnsigned.end())
|
||||
uiUnsignedNext++;
|
||||
|
||||
// Create a value assignment
|
||||
CTokenList lstValueTokens;
|
||||
lstValueTokens.push_back(CToken(std::to_string(uiUnsignedNext), ETokenLiteralType::token_literal_dec_integer));
|
||||
pValue->SetFixedValue(uiUnsignedNext, lstValueTokens);
|
||||
|
||||
// Store the value
|
||||
setUnsigned.insert(uiUnsignedNext);
|
||||
iSignedNext++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CEnumEntity::Supports(EDefinitionSupport eSupport) const
|
||||
{
|
||||
switch (eSupport)
|
||||
{
|
||||
case EDefinitionSupport::support_enum_entry: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CEnumEntity::CreateValueNode()
|
||||
{
|
||||
// Create a simple type value node for this definition.
|
||||
ValueRef() = std::make_shared<CEnumValueNode>(shared_from_this(), nullptr);
|
||||
}
|
||||
178
sdv_executables/sdv_idl_compiler/entities/enum_entity.h
Normal file
178
sdv_executables/sdv_idl_compiler/entities/enum_entity.h
Normal file
@@ -0,0 +1,178 @@
|
||||
#ifndef ENUM_ENTITY_H
|
||||
#define ENUM_ENTITY_H
|
||||
|
||||
#include "definition_entity.h"
|
||||
#include "declaration_entity.h"
|
||||
#include "variable_entity.h"
|
||||
|
||||
/**
|
||||
* @brief The enum entry declaration.
|
||||
*/
|
||||
class CEnumEntry : public CDeclarationEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
*/
|
||||
CEnumEntry(const CContextPtr& rptrContext, CEntityPtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CEnumEntry() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns enum entity type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_enum_entry; }
|
||||
|
||||
/**
|
||||
* @brief Get the declaration type of the entity as string. Overload of CEntity::GetDeclTypeStr.
|
||||
* @param[in] bResolveTypedef When set, resolve the typedef type into the base type.
|
||||
* @return Returns a string with enum type.
|
||||
*/
|
||||
virtual std::string GetDeclTypeStr(bool bResolveTypedef) const override;
|
||||
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support assignments? Overload of CDeclarationEntity::SupportAssignments.
|
||||
* @return Returns 'true' when the entity supports assignments; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportAssignments() const override { return true; }
|
||||
|
||||
// Suppress cppcheck warning of a useless override. The function is here for better understanding.
|
||||
// cppcheck-suppress uselessOverride
|
||||
/**
|
||||
* @brief Is the entity readonly? Overload of IEntityInfo::IsReadOnly.
|
||||
* @return Returns 'true' when the entity defined as readonly; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsReadOnly() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support multiple declarations on one line of code? Overload of
|
||||
* CDeclarationEntity::SupportMultipleDeclarations.
|
||||
* @return Returns 'true' when the entity supports multiple declarations; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportMultipleDeclarations() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Do not enforce next declaration after comma (enums do)? Overload of
|
||||
* CDeclarationEntity::DoNotEnfoceNextDeclarationAfterComma.
|
||||
* @return Returns 'true' when not enforcing the next declaration; 'false' otherwise.
|
||||
*/
|
||||
virtual bool DoNotEnfoceNextDeclarationAfterComma() const override { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The enum definition of an IDL file.
|
||||
* @details The enum section of the IDL file contains a list of enum value entries
|
||||
*/
|
||||
class CEnumEntity : public CDefinitionEntity, public sdv::idl::IEnumEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
*/
|
||||
CEnumEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CEnumEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get access to another interface. Overload of sdv::IInterfaceAccess::GetInterface.
|
||||
* @param[in] idInterface The interface id to get access to.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
virtual sdv::interface_t GetInterface(sdv::interface_id idInterface) override;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns enum entity type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_enum; }
|
||||
|
||||
/**
|
||||
* @brief Get the declaration type of the entity as string. Overload of CEntity::GetDeclTypeStr.
|
||||
* @param[in] bResolveTypedef When set, resolve the typedef type into the base type.
|
||||
* @return Returns a string with enum type.
|
||||
*/
|
||||
virtual std::string GetDeclTypeStr(bool bResolveTypedef) const override;
|
||||
|
||||
/**
|
||||
* @brief Get the enumerator base type. Overload of sdv::idl::IEnumEntity.
|
||||
* @param[out] reType Reference to the declaration type. The type if EEntityType::type_unknown if not available.
|
||||
* @param[out] rpType Reference to the interface pointer if the type is a complex type. Otherwise is NULL.
|
||||
*/
|
||||
virtual void GetBaseType(sdv::idl::EDeclType& reType, sdv::IInterfaceAccess*& rpType) const override;
|
||||
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Process the content of the definition.
|
||||
*/
|
||||
virtual void ProcessContent() override;
|
||||
|
||||
/**
|
||||
* @brief Process the definition addendum (following the definition statement before the content definition).
|
||||
*/
|
||||
virtual void ProcessDefinitionAddendum() override;
|
||||
|
||||
/**
|
||||
* @brief Get the enum type.
|
||||
* @return Returns the underlying enum type.
|
||||
*/
|
||||
sdv::idl::EDeclType GetEnumType() const { return m_typedecl.GetBaseType(); }
|
||||
|
||||
/**
|
||||
* @brief Request whether the definition supports the content. Overload of CDefintionEntity::Supports.
|
||||
* @param[in] eSupport The type of support that is requested.
|
||||
* @return Returns 'true' when the definition supports the content; 'false' otherwise.
|
||||
*/
|
||||
virtual bool Supports(EDefinitionSupport eSupport) const override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support children? Overload of CEntity::SupportsChildren.
|
||||
* @details The struct supports children.
|
||||
* @return Returns whether the entity supports children (which is supported).
|
||||
*/
|
||||
virtual bool SupportsChildren() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support anonymous naming?
|
||||
* @details The default implementation is that anonymous naming is not supported.
|
||||
* @return Returns whether the entity supports inheritance (which is supported).
|
||||
*/
|
||||
virtual bool SupportsAnonymous() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support inheritance?
|
||||
* @details The default implementation is that inheritance is not supported.
|
||||
* @return Returns whether the entity supports inheritance (which is supported).
|
||||
*/
|
||||
virtual bool SupportsInheritance() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Create the content value node. Overload of CDefinitionEntity::CreateValueNode.
|
||||
* @details Create the value node and assign the value node to the ValueRef() reference..
|
||||
*/
|
||||
virtual void CreateValueNode() override;
|
||||
|
||||
private:
|
||||
CTypeDeclaration m_typedecl; ///< The base type of the enum.
|
||||
};
|
||||
|
||||
#endif // !defined(ENUM_ENTITY_H)
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "exception_entity.h"
|
||||
#include "../exception.h"
|
||||
#include "../logger.h"
|
||||
#include "typedef_entity.h"
|
||||
#include "variable_entity.h"
|
||||
#include <iostream>
|
||||
|
||||
CExceptionEntity::CExceptionEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent) :
|
||||
CStructEntity(rptrContext, ptrParent)
|
||||
{}
|
||||
|
||||
std::string CExceptionEntity::GetDeclTypeStr(bool /*bResolveTypedef*/) const
|
||||
{
|
||||
return std::string("exception ") + GetScopedName();
|
||||
}
|
||||
|
||||
void CExceptionEntity::Process()
|
||||
{
|
||||
CStructEntity::Process();
|
||||
}
|
||||
|
||||
bool CExceptionEntity::Supports(EDefinitionSupport eSupport) const
|
||||
{
|
||||
switch (eSupport)
|
||||
{
|
||||
case EDefinitionSupport::support_variable: return true;
|
||||
case EDefinitionSupport::support_const_variable: return true;
|
||||
case EDefinitionSupport::support_typedef: return true;
|
||||
case EDefinitionSupport::support_struct: return true;
|
||||
case EDefinitionSupport::support_union: return true;
|
||||
case EDefinitionSupport::support_enum: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CExceptionEntity::CreateValueNode()
|
||||
{
|
||||
// Create a compound type value node for this definition.
|
||||
ValueRef() = std::make_shared<CCompoundTypeValueNode>(shared_from_this(), nullptr);
|
||||
}
|
||||
62
sdv_executables/sdv_idl_compiler/entities/exception_entity.h
Normal file
62
sdv_executables/sdv_idl_compiler/entities/exception_entity.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef EXCEPTION_ENTITY_H
|
||||
#define EXCEPTION_ENTITY_H
|
||||
|
||||
#include "definition_entity.h"
|
||||
#include "struct_entity.h"
|
||||
|
||||
/**
|
||||
* @brief The struct definition of an IDL file.
|
||||
* @details The struct section of the IDL file contains multiple declarations of members, as well as the definitions of structs
|
||||
* and unions.
|
||||
*/
|
||||
class CExceptionEntity : public CStructEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
*/
|
||||
CExceptionEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CExceptionEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return the exception entity type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_exception; }
|
||||
|
||||
/**
|
||||
* @brief Get the declaration type of the entity as string. Overload of CEntity::GetDeclTypeStr.
|
||||
* @param[in] bResolveTypedef When set, resolve the typedef type into the base type.
|
||||
* @return Returns a string with exception type.
|
||||
*/
|
||||
virtual std::string GetDeclTypeStr(bool bResolveTypedef) const override;
|
||||
|
||||
// Suppress cppcheck warning of a useless override. The function is here for better understanding.
|
||||
// cppcheck-suppress uselessOverride
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Request whether the definition supports the content. Overload of CDefintionEntity::Supports.
|
||||
* @param[in] eSupport The type of support that is requested.
|
||||
* @return Returns 'true' when the definition supports the content; 'false' otherwise.
|
||||
*/
|
||||
virtual bool Supports(EDefinitionSupport eSupport) const override;
|
||||
|
||||
/**
|
||||
* @brief Create the content value node. Overload of CDefinitionEntity::CreateValueNode.
|
||||
* @details Create the value node and assign the value node to the ValueRef() reference..
|
||||
*/
|
||||
virtual void CreateValueNode() override;
|
||||
};
|
||||
|
||||
|
||||
#endif // !defined(EXCEPTION_ENTITY_H)
|
||||
39
sdv_executables/sdv_idl_compiler/entities/hash_calc.cpp
Normal file
39
sdv_executables/sdv_idl_compiler/entities/hash_calc.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "hash_calc.h"
|
||||
|
||||
CHashObject::CHashObject()
|
||||
{
|
||||
// Create a xxHash state
|
||||
m_state = XXH64_createState();
|
||||
|
||||
/* Initialize state with selected seed */
|
||||
XXH64_hash_t seed = 0; /* or any other value */
|
||||
if (XXH64_reset(m_state, seed) == XXH_ERROR)
|
||||
{
|
||||
XXH64_freeState(m_state);
|
||||
m_state = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
CHashObject::~CHashObject()
|
||||
{
|
||||
if (m_state) XXH64_freeState(m_state);
|
||||
}
|
||||
|
||||
CHashObject& CHashObject::operator<<(const std::string& rssString)
|
||||
{
|
||||
if (!m_state) return *this;
|
||||
if (rssString.empty()) return *this;
|
||||
if (XXH64_update(m_state, rssString.c_str(), rssString.size()) == XXH_ERROR)
|
||||
{
|
||||
XXH64_freeState(m_state);
|
||||
m_state = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint64_t CHashObject::GetHash() const
|
||||
{
|
||||
if (!m_state) return 0;
|
||||
XXH64_hash_t hash = XXH64_digest(m_state);
|
||||
return hash;
|
||||
}
|
||||
52
sdv_executables/sdv_idl_compiler/entities/hash_calc.h
Normal file
52
sdv_executables/sdv_idl_compiler/entities/hash_calc.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef HASH_CALC_H
|
||||
#define HASH_CALC_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Prevent warnings for XXHash during static code analysis.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26812 26451)
|
||||
#endif
|
||||
|
||||
#define XXH_INLINE_ALL
|
||||
#include <xxhash.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @brief Calculate a hash value
|
||||
*/
|
||||
class CHashObject
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
CHashObject();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~CHashObject();
|
||||
|
||||
/**
|
||||
* @brief Shift operator adding a string to the hash.
|
||||
* @param[in] rssString Reference to the string.
|
||||
* @return
|
||||
*/
|
||||
CHashObject& operator<<(const std::string& rssString);
|
||||
|
||||
/**
|
||||
* @brief Get the current hash value.
|
||||
* @return The hash value.
|
||||
*/
|
||||
uint64_t GetHash() const;
|
||||
|
||||
private:
|
||||
XXH64_state_t* m_state = nullptr; ///< Hash state
|
||||
};
|
||||
|
||||
#endif // !defined(HASH_CALC_H)
|
||||
@@ -0,0 +1,85 @@
|
||||
#include "interface_entity.h"
|
||||
#include "../exception.h"
|
||||
#include "../logger.h"
|
||||
#include "typedef_entity.h"
|
||||
#include "variable_entity.h"
|
||||
#include <iostream>
|
||||
|
||||
CInterfaceEntity::CInterfaceEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, bool bIsLocal) :
|
||||
CDefinitionEntity(rptrContext, ptrParent), m_bIsLocal(bIsLocal)
|
||||
{}
|
||||
|
||||
sdv::interface_t CInterfaceEntity::GetInterface(sdv::interface_id idInterface)
|
||||
{
|
||||
// Expose interfaces
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::IInterfaceAccess>())
|
||||
return static_cast<sdv::idl::IInterfaceEntity*>(this);
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::idl::IInterfaceEntity>())
|
||||
return static_cast<sdv::idl::IInterfaceEntity*>(this);
|
||||
return CDefinitionEntity::GetInterface(idInterface);
|
||||
}
|
||||
|
||||
std::string CInterfaceEntity::GetDeclTypeStr(bool /*bResolveTypedef*/) const
|
||||
{
|
||||
return std::string("interface ") + GetScopedName();
|
||||
}
|
||||
|
||||
void CInterfaceEntity::Process()
|
||||
{
|
||||
// The definition and declaration can be defined:
|
||||
// struct <struct_identifier>; --> forward declaration
|
||||
// struct <struct_identifier> {...}; --> struct definition
|
||||
// struct <struct_identifier> : <base_struct,...> {...}; --> struct definition with inheritance
|
||||
// <struct_identifier> <decl_identifier>; --> struct variable declaration
|
||||
// <struct_identifier> <decl_identifier> = {...}; --> struct variable declaration and assignment
|
||||
// struct <struct_identifier> <decl_identifier>; --> struct variable declaration
|
||||
// struct <struct_identifier> <decl_identifier> = {...}; --> struct variable declaration and assignment
|
||||
// struct <struct_identifier> {...} <decl_identifier>; --> struct definition and variable declaration
|
||||
// struct <struct_identifier> : <base_struct,...> {...} <decl_identifier>; --> struct definition with inheritance and variable declaration
|
||||
// struct <struct_identifier> {...} <decl_identifier> = {...}; --> struct definition, variable declaration and assignment
|
||||
// struct <struct_identifier> : <base_struct,...> {...} <decl_identifier> = {...}; --> struct definition with inheritance, variable declaration and assignment
|
||||
// struct {...} <decl_identifier>; --> anonymous struct definition and variable declaration
|
||||
// struct : <base_struct,...> {...} <decl_identifier>; --> anonymous struct definition with inheritance and variable declaration
|
||||
// struct {...} <decl_identifier> = {...}; --> anonymous struct definition, variable declaration and assignment
|
||||
// struct : <base_struct,...> {...} <decl_identifier> = {...}; --> anonymous struct definition with inheritance, variable declaration and assignment
|
||||
|
||||
// typedef <struct_identifier> <type_identifier>;
|
||||
// typedef struct <struct_identifier> { ... } <type_identifier>;
|
||||
// typedef <struct_identifier> <type_identifier>;
|
||||
// typedef struct <struct_identifier> { ... } <type_identifier>;
|
||||
// typedef struct { ... } <type_identifier>;
|
||||
// const struct <struct_identifier> <decl_identifier> = {...};
|
||||
// const <struct_identifier> <decl_identifier> = {...};
|
||||
// const struct {...} <decl_identifier> = {...};
|
||||
|
||||
// The declaration is as follows:
|
||||
// <struct_identifier> <decl_identifier>;
|
||||
// struct <struct_identifier> <decl_identifier>;
|
||||
// struct <struct_identifier> { ... } <decl_identifier>;
|
||||
|
||||
|
||||
// TODO Enforce inheritance from sdv::IInterfaceAccess unless the interface is sdv::IInterfaceAccess.
|
||||
|
||||
CDefinitionEntity::Process();
|
||||
}
|
||||
|
||||
bool CInterfaceEntity::Supports(EDefinitionSupport eSupport) const
|
||||
{
|
||||
switch (eSupport)
|
||||
{
|
||||
case EDefinitionSupport::support_const_variable: return true;
|
||||
case EDefinitionSupport::support_typedef: return true;
|
||||
case EDefinitionSupport::support_struct: return true;
|
||||
case EDefinitionSupport::support_union: return true;
|
||||
case EDefinitionSupport::support_enum: return true;
|
||||
case EDefinitionSupport::support_attribute: return true;
|
||||
case EDefinitionSupport::support_operation: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CInterfaceEntity::CreateValueNode()
|
||||
{
|
||||
// Create a compound type value node for this definition.
|
||||
ValueRef() = std::make_shared<CInterfaceValueNode>(shared_from_this(), nullptr);
|
||||
}
|
||||
96
sdv_executables/sdv_idl_compiler/entities/interface_entity.h
Normal file
96
sdv_executables/sdv_idl_compiler/entities/interface_entity.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#ifndef INTERFACE_ENTITY_H
|
||||
#define INTERFACE_ENTITY_H
|
||||
|
||||
#include "definition_entity.h"
|
||||
|
||||
/**
|
||||
* @brief The interface definition of an IDL file.
|
||||
* @details The interface section of the IDL file contains multiple declarations of attributes and operations, as well as the
|
||||
* definitions of enums, structs and unions.
|
||||
*/
|
||||
class CInterfaceEntity : public CDefinitionEntity, public sdv::idl::IInterfaceEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
* @param[in] bIsLocal When set, the interface is defined as a local interface not intended to be marshalled.
|
||||
*/
|
||||
CInterfaceEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, bool bIsLocal);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CInterfaceEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get access to another interface. Overload of sdv::IInterfaceAccess::GetInterface.
|
||||
* @param[in] idInterface The interface id to get access to.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
virtual sdv::interface_t GetInterface(sdv::interface_id idInterface) override;
|
||||
|
||||
/**
|
||||
* @brief Is this interface local? Overload of sdv::idl::IInterfaceEntity::IsLocal.
|
||||
* @return Returns whether the interface is defined as local.
|
||||
*/
|
||||
virtual bool IsLocal() const override { return m_bIsLocal; }
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns the interface entity type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_interface; }
|
||||
|
||||
/**
|
||||
* @brief Get the declaration type of the entity as string. Overload of CEntity::GetDeclTypeStr.
|
||||
* @param[in] bResolveTypedef When set, resolve the typedef type into the base type.
|
||||
* @return Returns a string with interface type.
|
||||
*/
|
||||
virtual std::string GetDeclTypeStr(bool bResolveTypedef) const override;
|
||||
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Create the content value node. Overload of CDefinitionEntity::CreateValueNode.
|
||||
* @details Create the value node and assign the value node to the ValueRef() reference..
|
||||
*/
|
||||
virtual void CreateValueNode() override;
|
||||
|
||||
/**
|
||||
* @brief Request whether the definition supports the content. Overload of CDefintionEntity::Supports.
|
||||
* @param[in] eSupport The type of support that is requested.
|
||||
* @return Returns 'true' when the definition supports the content; 'false' otherwise.
|
||||
*/
|
||||
virtual bool Supports(EDefinitionSupport eSupport) const override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support inheritance? Overload of CDefinitionEntity::SupportsInheritance.
|
||||
* @details Returns whether the entity supports inheritance.
|
||||
* @return Returns whether inheritance is supported (which is the case).
|
||||
*/
|
||||
virtual bool SupportsInheritance() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the complex entity support attributes in its content? Overload of CDefinitionEntity::SupportContentAttributes.
|
||||
* @details The default implementation doesn't support attributes (they are specific to interfaces).
|
||||
* @return Returns whether the entity supports attributes (which is the case).
|
||||
*/
|
||||
virtual bool SupportContentAttributes() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the complex entity support operations in its content? Overload of CDefinitionEntity::SupportContentOperations.
|
||||
* @details The default implementation doesn't support operations (they are specific to interfaces).
|
||||
* @return Returns whether the entity supports operations (which is the case).
|
||||
*/
|
||||
virtual bool SupportContentOperations() const override { return true; }
|
||||
|
||||
private:
|
||||
bool m_bIsLocal = false; ///< Flag indicating that the interface is local and not intended to be marshalled.
|
||||
};
|
||||
|
||||
#endif // !defined(INTERFACE_ENTITY_H)
|
||||
65
sdv_executables/sdv_idl_compiler/entities/meta_entity.cpp
Normal file
65
sdv_executables/sdv_idl_compiler/entities/meta_entity.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "meta_entity.h"
|
||||
|
||||
CMetaEntity::CMetaEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, const CToken& rtokenMeta,
|
||||
const CTokenList lstComments) :
|
||||
CEntity(rptrContext, ptrParent)
|
||||
{
|
||||
std::string ssContent = rtokenMeta;
|
||||
|
||||
// Skip initial whitespace and store the content if not verbatim text.
|
||||
size_t nSkip = 0;
|
||||
if (rtokenMeta.GetMetaType() != ETokenMetaType::token_meta_verbatim)
|
||||
{
|
||||
while (nSkip < ssContent.size() && std::isspace(ssContent[nSkip]))
|
||||
++nSkip;
|
||||
}
|
||||
m_ssContent = ssContent.substr(nSkip);
|
||||
|
||||
// Store the type
|
||||
switch (rtokenMeta.GetMetaType())
|
||||
{
|
||||
case ETokenMetaType::token_meta_include_local:
|
||||
m_eType = sdv::idl::IMetaEntity::EType::include_local;
|
||||
break;
|
||||
case ETokenMetaType::token_meta_include_global:
|
||||
m_eType = sdv::idl::IMetaEntity::EType::include_global;
|
||||
break;
|
||||
case ETokenMetaType::token_meta_define:
|
||||
m_eType = sdv::idl::IMetaEntity::EType::define;
|
||||
break;
|
||||
case ETokenMetaType::token_meta_undef:
|
||||
m_eType = sdv::idl::IMetaEntity::EType::undef;
|
||||
break;
|
||||
case ETokenMetaType::token_meta_verbatim:
|
||||
m_eType = sdv::idl::IMetaEntity::EType::verbatim;
|
||||
break;
|
||||
default:
|
||||
throw CCompileException("Internal error: incomplete meta token received.");
|
||||
break;
|
||||
}
|
||||
|
||||
// Store comments
|
||||
SetCommentTokens(lstComments, true);
|
||||
|
||||
// Set the position in the source file
|
||||
SetBeginPosition(rtokenMeta.GetLine(), rtokenMeta.GetCol());
|
||||
}
|
||||
|
||||
sdv::interface_t CMetaEntity::GetInterface(sdv::interface_id idInterface)
|
||||
{
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::IInterfaceAccess>())
|
||||
return static_cast<sdv::IInterfaceAccess*>(this);
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::idl::IMetaEntity>())
|
||||
return static_cast<sdv::idl::IMetaEntity*>(this);
|
||||
return CEntity::GetInterface(idInterface);
|
||||
}
|
||||
|
||||
sdv::idl::IMetaEntity::EType CMetaEntity::GetMetaType() const
|
||||
{
|
||||
return m_eType;
|
||||
}
|
||||
|
||||
sdv::u8string CMetaEntity::GetContent() const
|
||||
{
|
||||
return m_ssContent;
|
||||
}
|
||||
68
sdv_executables/sdv_idl_compiler/entities/meta_entity.h
Normal file
68
sdv_executables/sdv_idl_compiler/entities/meta_entity.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef META_ENTITY_H
|
||||
#define META_ENTITY_H
|
||||
|
||||
#include "entity_base.h"
|
||||
|
||||
/**
|
||||
* @brief The meta data inserted into the code.
|
||||
*/
|
||||
class CMetaEntity : public CEntity, public sdv::idl::IMetaEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
* @param[in] rtokenMeta The meta data content
|
||||
* @param[in] lstComments Any preceding comments
|
||||
*/
|
||||
CMetaEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, const CToken& rtokenMeta,
|
||||
const CTokenList lstComments);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CMetaEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns the meta entity type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_meta; }
|
||||
|
||||
/**
|
||||
* @brief Get the name of the entity. Overload of CEntity::GetName.
|
||||
* @return The entity name.
|
||||
*/
|
||||
virtual sdv::u8string GetName() const override { return "meta"; }
|
||||
|
||||
/**
|
||||
* @brief Get access to another interface. Overload of sdv::IInterfaceAccess::GetInterface.
|
||||
* @param[in] idInterface The interface id to get access to.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
virtual sdv::interface_t GetInterface(sdv::interface_id idInterface) override;
|
||||
|
||||
/**
|
||||
* @brief Get the meta data type.
|
||||
* @return Returns meta entity type.
|
||||
*/
|
||||
virtual sdv::idl::IMetaEntity::EType GetMetaType() const override;
|
||||
|
||||
/**
|
||||
* @brief Get the meta data content.
|
||||
* @return Returns a string object.
|
||||
*/
|
||||
virtual sdv::u8string GetContent() const override;
|
||||
|
||||
/**
|
||||
* @brief Process the code. Since there is none... nothing to do. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override {};
|
||||
|
||||
private:
|
||||
sdv::idl::IMetaEntity::EType m_eType; ///< Type of meta data
|
||||
std::string m_ssContent; ///< The meta data string
|
||||
};
|
||||
|
||||
#endif ///defined(META_ENTITY_H)
|
||||
49
sdv_executables/sdv_idl_compiler/entities/module_entity.cpp
Normal file
49
sdv_executables/sdv_idl_compiler/entities/module_entity.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "module_entity.h"
|
||||
#include "typedef_entity.h"
|
||||
#include "struct_entity.h"
|
||||
#include "union_entity.h"
|
||||
#include "interface_entity.h"
|
||||
#include "exception_entity.h"
|
||||
#include "../exception.h"
|
||||
#include "../token.h"
|
||||
|
||||
CModuleEntity::CModuleEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent) :
|
||||
CDefinitionEntity(rptrContext, ptrParent)
|
||||
{}
|
||||
|
||||
CModuleEntity::CModuleEntity(CParser& rParser, const CContextPtr& rptrContext) :
|
||||
CDefinitionEntity(rParser, rptrContext)
|
||||
{}
|
||||
|
||||
void CModuleEntity::Process()
|
||||
{
|
||||
CDefinitionEntity::Process();
|
||||
}
|
||||
|
||||
bool CModuleEntity::Supports(EDefinitionSupport eSupport) const
|
||||
{
|
||||
switch (eSupport)
|
||||
{
|
||||
case EDefinitionSupport::support_module: return true;
|
||||
case EDefinitionSupport::support_const_variable: return true;
|
||||
case EDefinitionSupport::support_typedef: return true;
|
||||
case EDefinitionSupport::support_struct: return true;
|
||||
case EDefinitionSupport::support_union: return true;
|
||||
case EDefinitionSupport::support_enum: return true;
|
||||
case EDefinitionSupport::support_interface: return true;
|
||||
case EDefinitionSupport::support_exception: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CModuleEntity::IsExtendable() const
|
||||
{
|
||||
// Allow extending the module.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CModuleEntity::SupportsChildren() const
|
||||
{
|
||||
// Allow the support of children.
|
||||
return true;
|
||||
}
|
||||
86
sdv_executables/sdv_idl_compiler/entities/module_entity.h
Normal file
86
sdv_executables/sdv_idl_compiler/entities/module_entity.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#ifndef MODULE_ENTITY_H
|
||||
#define MODULE_ENTITY_H
|
||||
|
||||
#include "definition_entity.h"
|
||||
#include <map>
|
||||
#include "../constvariant.h"
|
||||
|
||||
/**
|
||||
* @brief The module definition of an IDL file.
|
||||
* @details The module section of the IDL file contains multiple definitions of nested modules, const definitions and type
|
||||
* definitions.
|
||||
*/
|
||||
class CModuleEntity : public CDefinitionEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
*/
|
||||
CModuleEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Root entity constructor (name is 'root' and no parent).
|
||||
* @param[in] rParser Reference to the parser.
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
*/
|
||||
CModuleEntity(CParser& rParser, const CContextPtr& rptrContext);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CModuleEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns the module entity type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_module; }
|
||||
|
||||
// Suppress cppcheck warning of a useless override. The function is here for better understanding.
|
||||
// cppcheck-suppress uselessOverride
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Request whether the definition supports the content. Overload of CDefintionEntity::Supports.
|
||||
* @param[in] eSupport The type of support that is requested.
|
||||
* @return Returns 'true' when the definition supports the content; 'false' otherwise.
|
||||
*/
|
||||
virtual bool Supports(EDefinitionSupport eSupport) const override;
|
||||
|
||||
// Suppress warning of cppcheck of a useless override. The function implementation improves readability.
|
||||
// cppcheck-suppress uselessOverride
|
||||
/**
|
||||
* @brief Is this definition a root entity? Overload of CDefinitionEntity::IsRootEntity.
|
||||
* @details The root entity is not expecting curly brackets '{...}'.
|
||||
* @return Returns whether this is a root entity (which is not the case).
|
||||
*/
|
||||
virtual bool IsRootEntity() const override { return false; }
|
||||
|
||||
/**
|
||||
* @brief Is the entity extendable? Overload of CEntity::IsExtendable.
|
||||
* @details Allow extendability of the module entity.
|
||||
* @return Returns whether the entity is extendable.
|
||||
*/
|
||||
virtual bool IsExtendable() const override;
|
||||
|
||||
// Suppress cppcheck warning of a useless override. The function is here for better understanding.
|
||||
// cppcheck-suppress uselessOverride
|
||||
/**
|
||||
* @brief Does the entity support children? Overload of CEntity::SupportsChildren.
|
||||
* @details The module supports children.
|
||||
* @return Return whether the entity support children.
|
||||
*/
|
||||
virtual bool SupportsChildren() const override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
#endif // !defined(MODULE_ENTITY_H)
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "operation_entity.h"
|
||||
#include "interface_entity.h"
|
||||
|
||||
COperationEntity::COperationEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent) :
|
||||
CDeclarationEntity(rptrContext, ptrParent), m_iteratorParameters(GetParamVector()),
|
||||
m_iteratorExceptions(GetExceptionVector())
|
||||
{}
|
||||
|
||||
sdv::interface_t COperationEntity::GetInterface(sdv::interface_id idInterface)
|
||||
{
|
||||
// Expose interfaces
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::IInterfaceAccess>())
|
||||
return static_cast<sdv::IInterfaceAccess*>(this);
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::idl::IOperationEntity>())
|
||||
return static_cast<sdv::idl::IOperationEntity*>(this);
|
||||
return CDeclarationEntity::GetInterface(idInterface);
|
||||
}
|
||||
|
||||
sdv::idl::IEntityIterator* COperationEntity::GetParameters()
|
||||
{
|
||||
if (!GetParamVector().empty()) return &m_iteratorParameters;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sdv::idl::IEntityIterator* COperationEntity::GetExceptions()
|
||||
{
|
||||
if (!GetExceptionVector().empty()) return &m_iteratorExceptions;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::pair<CEntityPtr, bool> COperationEntity::FindLocal(const std::string& rssName, bool /*bDeclaration*/) const
|
||||
{
|
||||
const CEntityVector& rvecParams = GetParamVector();
|
||||
for (const CEntityPtr& rptrEntity : rvecParams)
|
||||
{
|
||||
if (rptrEntity->GetName() == rssName)
|
||||
return std::make_pair(rptrEntity, false);
|
||||
}
|
||||
return std::make_pair(nullptr, false);
|
||||
}
|
||||
|
||||
bool COperationEntity::RequiresAssignment() const
|
||||
{
|
||||
const CInterfaceEntity* pInterface = GetParentEntity() ? GetParentEntity()->Get<CInterfaceEntity>() : nullptr;
|
||||
if (pInterface && pInterface->IsLocal()) return false;
|
||||
return CDeclarationEntity::RequiresAssignment();
|
||||
}
|
||||
128
sdv_executables/sdv_idl_compiler/entities/operation_entity.h
Normal file
128
sdv_executables/sdv_idl_compiler/entities/operation_entity.h
Normal file
@@ -0,0 +1,128 @@
|
||||
#ifndef OPERATION_ENTITY_H
|
||||
#define OPERATION_ENTITY_H
|
||||
|
||||
#include "declaration_entity.h"
|
||||
|
||||
/**
|
||||
* @brief The operation definition of an IDL file.
|
||||
* @details The operation section of the IDL file defines operations.
|
||||
*/
|
||||
class COperationEntity : public CDeclarationEntity, public sdv::idl::IOperationEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
*/
|
||||
COperationEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~COperationEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get access to another interface. Overload of sdv::IInterfaceAccess::GetInterface.
|
||||
* @param[in] idInterface The interface id to get access to.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
virtual sdv::interface_t GetInterface(sdv::interface_id idInterface) override;
|
||||
|
||||
/**
|
||||
* @brief Get parameter entity iterator if the definition has any parameters. Overload of
|
||||
* sdv::idl::IOperationEntity::GetParameters.
|
||||
* @return Returns a pointer to the parameter entity iterator or NULL when not available.
|
||||
*/
|
||||
virtual sdv::idl::IEntityIterator* GetParameters() override;
|
||||
|
||||
/**
|
||||
* @brief Get the list of possible exceptions that might be fired for this operation. Overload of
|
||||
* sdv::idl::IOperationEntity::GetExceptions.
|
||||
* @return Interface pointer to the exception iterator.
|
||||
*/
|
||||
virtual sdv::idl::IEntityIterator* GetExceptions() override;
|
||||
|
||||
/**
|
||||
* @brief Is the entity readonly (variable declarations and writable attributes aren't)? Overload of IDeclarationEntity::IsReadOnly.
|
||||
* @details Returns whether the entity is readonly by design or whether it is defined readonly by the code. Default value is
|
||||
* 'true'.
|
||||
* @return Returns 'true' when the entity defined as readonly; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsReadOnly() const override { return m_bOperationIsConst; }
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns the operation type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_operation; }
|
||||
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override { CDeclarationEntity::Process(); }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Does the entity support raising exceptions? Overload of CDeclarationEntity::SupportRaiseExceptions.
|
||||
* @return Returns 'true' when the entity defined as attribute; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportRaiseExceptions() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support arrays? Overload of CDeclarationEntity::SupportArrays.
|
||||
* @return Returns 'true' when the entity supports assignments; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportArrays() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support an interface as base type? Overload of CDeclarationEntity::SupportVoid.
|
||||
* @return Returns 'true' when the entity supports interfaces as base type; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportInterface() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support 'void' as base type? Overload of CDeclarationEntity::SupportVoid.
|
||||
* @details Returns whether the entity supports the 'void' base type. Default value is 'false'.
|
||||
* @return Returns 'true' when the entity supports void as base type; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportVoid() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support parameters? Overload of CDeclarationEntity::RequiresParameters.
|
||||
* @details Returns whether the entity supports parameters. Default value is 'false'.
|
||||
* @return Returns 'true' when the entity requires parameters; 'false' otherwise.
|
||||
*/
|
||||
virtual bool RequiresParameters() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Set operation as const. Overload of CDeclarationEntity::SetOperationAsConst.
|
||||
*/
|
||||
virtual void SetOperationAsConst() override { m_bOperationIsConst = true; }
|
||||
|
||||
/**
|
||||
* @brief Find the entity locally by looking in the parameter list. Overload of CEntity::FindLocal.
|
||||
* @param[in] rssName Reference to the string object containing the name of the entity to search for.
|
||||
* @param[in] bDeclaration When set, the name belongs to a declaration; otherwise it belongs to a definition. Needed to allow
|
||||
* the reuse of names between declarations and definitions.
|
||||
* @return Returns a pair object containing an entity pointer if the entity exists or a NULL pointer if not as well as a
|
||||
* boolean that indicates that the entity was from an inherited entity.
|
||||
*/
|
||||
virtual std::pair<CEntityPtr, bool> FindLocal(const std::string& rssName, bool bDeclaration) const override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity require an assignment (const declarations do)? Overload of CDeclarationEntity::RequiresAssignment.
|
||||
* @details Default processing is done by the declaration function (checking for unbound arrays). Exception: when the
|
||||
* parent interface is defined as local, assignment is not required.
|
||||
* @return Returns 'true' when the entity requires an assignment; 'false' otherwise.
|
||||
*/
|
||||
virtual bool RequiresAssignment() const override;
|
||||
|
||||
private:
|
||||
bool m_bOperationIsConst = false; ///< When set, the operation is defined as 'const' operation.
|
||||
CEntityIterator m_iteratorParameters; ///< Parameters iterator
|
||||
CEntityIterator m_iteratorExceptions; ///< Exceptions iterator
|
||||
};
|
||||
|
||||
|
||||
#endif // !defined(OPERATION_ENTITY_H)
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "parameter_entity.h"
|
||||
#include "interface_entity.h"
|
||||
#include "operation_entity.h"
|
||||
#include "../exception.h"
|
||||
|
||||
CParameterEntity::CParameterEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent,
|
||||
const CTokenList& rlstTokenList, bool bEnforceDirection /*= true*/) :
|
||||
CDeclarationEntity(rptrContext, ptrParent, rlstTokenList), m_bEnforceDirection(bEnforceDirection)
|
||||
{}
|
||||
|
||||
sdv::interface_t CParameterEntity::GetInterface(sdv::interface_id idInterface)
|
||||
{
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::idl::IParameterEntity>())
|
||||
return static_cast<sdv::idl::IParameterEntity*>(this);
|
||||
return CDeclarationEntity::GetInterface(idInterface);
|
||||
}
|
||||
|
||||
void CParameterEntity::Process()
|
||||
{
|
||||
// Check for direction indicators.
|
||||
CToken token = GetToken();
|
||||
if (token == "in") m_eDirection = sdv::idl::IParameterEntity::EParameterDirection::input;
|
||||
else if (token == "out") m_eDirection = sdv::idl::IParameterEntity::EParameterDirection::output;
|
||||
else if (token == "inout") m_eDirection = sdv::idl::IParameterEntity::EParameterDirection::in_out;
|
||||
else
|
||||
{
|
||||
PrependToken(token);
|
||||
|
||||
// Enforce the direction?
|
||||
if (m_bEnforceDirection) throw CCompileException(token, "Missing direction indicator.");
|
||||
}
|
||||
|
||||
// Let the basic type entity process further
|
||||
CDeclarationEntity::Process();
|
||||
}
|
||||
|
||||
bool CParameterEntity::RequiresAssignment() const
|
||||
{
|
||||
COperationEntity* pOperation = GetParentEntity() ? GetParentEntity()->Get<COperationEntity>() : nullptr;
|
||||
const CInterfaceEntity* pInterface = pOperation && pOperation->GetParentEntity() ? pOperation->GetParentEntity()->Get<CInterfaceEntity>() : nullptr;
|
||||
if (pInterface && pInterface->IsLocal()) return false;
|
||||
return CDeclarationEntity::RequiresAssignment();
|
||||
}
|
||||
|
||||
void CParameterEntity::CalcHash(CHashObject& rHash) const
|
||||
{
|
||||
// Call base class
|
||||
CDeclarationEntity::CalcHash(rHash);
|
||||
|
||||
// Add the direction
|
||||
switch (m_eDirection)
|
||||
{
|
||||
case sdv::idl::IParameterEntity::EParameterDirection::input:
|
||||
rHash << "in";
|
||||
break;
|
||||
case sdv::idl::IParameterEntity::EParameterDirection::output:
|
||||
rHash << "out";
|
||||
break;
|
||||
case sdv::idl::IParameterEntity::EParameterDirection::in_out:
|
||||
rHash << "inout";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
92
sdv_executables/sdv_idl_compiler/entities/parameter_entity.h
Normal file
92
sdv_executables/sdv_idl_compiler/entities/parameter_entity.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef PARAMETER_ENTITY_H
|
||||
#define PARAMETER_ENTITY_H
|
||||
|
||||
#include "declaration_entity.h"
|
||||
|
||||
/**
|
||||
* @brief The parameter definition of an operation and value type.
|
||||
* @details The parameter section contains the definition of the parameter for operations and value types.
|
||||
*/
|
||||
class CParameterEntity : public CDeclarationEntity, public sdv::idl::IParameterEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
* @param[in] rlstTokenList Reference to the token list holding the tokens to process.
|
||||
* @param[in] bEnforceDirection Enforce parameter direction.
|
||||
*/
|
||||
CParameterEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, const CTokenList& rlstTokenList,
|
||||
bool bEnforceDirection = true);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CParameterEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get access to another interface. Overload of IInterfaceAccess::GetInterface.
|
||||
* @param[in] idInterface The interface id to get access to.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
virtual sdv::interface_t GetInterface(sdv::interface_id idInterface) override;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns the parameter type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_parameter; }
|
||||
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support arrays? Overload of CDeclarationEntity::SupportArrays.
|
||||
* @return Returns 'true' when the entity supports assignments; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportArrays() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support an interface as base type? Overload of CDeclarationEntity::SupportVoid.
|
||||
* @return Returns 'true' when the entity supports interfaces as base type; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportInterface() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Get the parameter direction. Overload of sdv::idl::IParameterEntity::GetDirection.
|
||||
* @return Parameter direction.
|
||||
*/
|
||||
virtual sdv::idl::IParameterEntity::EParameterDirection GetDirection() const override { return m_eDirection; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity require an assignment (const declarations do)? Overload of CDeclarationEntity::RequiresAssignment.
|
||||
* @details Default processing is done by the declaration function (checking for unbound arrays). Exception: when the
|
||||
* parent interface is defined as local, assignment is not required.
|
||||
* @return Returns 'true' when the entity requires an assignment; 'false' otherwise.
|
||||
*/
|
||||
virtual bool RequiresAssignment() const override;
|
||||
|
||||
/**
|
||||
* @brief Is the entity readonly (variable declarations and writable attributes aren't)? Overload of IDeclarationEntity::IsReadOnly.
|
||||
* @details Returns whether the entity is readonly by design or whether it is defined readonly by the code. Default value is
|
||||
* 'true'.
|
||||
* @return Returns 'true' when the entity defined as readonly; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsReadOnly() const override { return false; }
|
||||
|
||||
/**
|
||||
* @brief Calculate the hash of this entity and all encapsulated entities. Overload of CBaseEntity::CalcHash.
|
||||
* @param[in, out] rHash Hash object to be filled with data.
|
||||
*/
|
||||
virtual void CalcHash(CHashObject& rHash) const override;
|
||||
|
||||
private:
|
||||
bool m_bEnforceDirection; ///< When set, the parameter enforces the direction indicator when processing.
|
||||
sdv::idl::IParameterEntity::EParameterDirection m_eDirection =
|
||||
sdv::idl::IParameterEntity::EParameterDirection::unknown; ///< The direction type of the parameter.
|
||||
};
|
||||
|
||||
#endif // !defined(PARAMETER_ENTITY_H)
|
||||
30
sdv_executables/sdv_idl_compiler/entities/root_entity.cpp
Normal file
30
sdv_executables/sdv_idl_compiler/entities/root_entity.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "root_entity.h"
|
||||
#include "module_entity.h"
|
||||
#include "../exception.h"
|
||||
#include "../token.h"
|
||||
|
||||
|
||||
CRootEntity::CRootEntity(CParser& rParser, const CContextPtr& rptrContext) :
|
||||
CModuleEntity(rParser, rptrContext)
|
||||
{}
|
||||
|
||||
void CRootEntity::Process()
|
||||
{
|
||||
// Skip the definition and process the content directly.
|
||||
ProcessContent();
|
||||
}
|
||||
|
||||
bool CRootEntity::IsExtendable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void CRootEntity::AddMeta(const CEntityPtr& ptrMeta)
|
||||
{
|
||||
m_lstMetaEntities.push_back(ptrMeta);
|
||||
}
|
||||
|
||||
const CEntityList& CRootEntity::GetMeta() const
|
||||
{
|
||||
return m_lstMetaEntities;
|
||||
}
|
||||
57
sdv_executables/sdv_idl_compiler/entities/root_entity.h
Normal file
57
sdv_executables/sdv_idl_compiler/entities/root_entity.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef ROOT_ENTITY_H
|
||||
#define ROOT_ENTITY_H
|
||||
|
||||
#include "module_entity.h"
|
||||
#include "meta_entity.h"
|
||||
|
||||
/**
|
||||
* @brief The root definition of an IDL file.
|
||||
* @details The root section of the IDL file contains multiple definitions of modules, constants and types.
|
||||
*/
|
||||
class CRootEntity : public CModuleEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rParser Reference to the parser used to parse the code.
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
*/
|
||||
CRootEntity(CParser& rParser, const CContextPtr& rptrContext);
|
||||
|
||||
/**
|
||||
* @brief Process the code. Overload of CModuleEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Is this definition a root entity? Overload of CDefinitionEntity::IsRootEntity.
|
||||
* @details The root entity is not expecting curly brackets '{...}'.
|
||||
* @return Returns whether this entity is the root entity.
|
||||
*/
|
||||
virtual bool IsRootEntity() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Is the entity extendable? Overload of CEntity::IsExtendable.
|
||||
* @details Prevents extending the root entity.
|
||||
* @return Returns whether the entity is extendable.
|
||||
*/
|
||||
virtual bool IsExtendable() const override;
|
||||
|
||||
/**
|
||||
* @brief Add meta data entity.
|
||||
* @param[in] ptrMeta Shared pointer to the meta data entity.
|
||||
*/
|
||||
void AddMeta(const CEntityPtr& ptrMeta);
|
||||
|
||||
/**
|
||||
* @brief Get the meta data entity list.
|
||||
* @return Reference to the meta data entity list.
|
||||
*/
|
||||
const CEntityList& GetMeta() const;
|
||||
|
||||
private:
|
||||
CEntityList m_lstMetaEntities; ///< List of meta entities.
|
||||
|
||||
};
|
||||
|
||||
#endif // !defined(ROOT_ENTITY_H)
|
||||
71
sdv_executables/sdv_idl_compiler/entities/struct_entity.cpp
Normal file
71
sdv_executables/sdv_idl_compiler/entities/struct_entity.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "struct_entity.h"
|
||||
#include "../exception.h"
|
||||
#include "../logger.h"
|
||||
#include "typedef_entity.h"
|
||||
#include "variable_entity.h"
|
||||
#include <iostream>
|
||||
|
||||
CStructEntity::CStructEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent) :
|
||||
CDefinitionEntity(rptrContext, ptrParent)
|
||||
{}
|
||||
|
||||
std::string CStructEntity::GetDeclTypeStr(bool /*bResolveTypedef*/) const
|
||||
{
|
||||
return std::string("struct ") + GetScopedName();
|
||||
}
|
||||
|
||||
void CStructEntity::Process()
|
||||
{
|
||||
// The definition and declaration can be defined:
|
||||
// struct <struct_identifier>; --> forward declaration
|
||||
// struct <struct_identifier> {...}; --> struct definition
|
||||
// struct <struct_identifier> : <base_struct,...> {...}; --> struct definition with inheritance
|
||||
// <struct_identifier> <decl_identifier>; --> struct variable declaration
|
||||
// <struct_identifier> <decl_identifier> = {...}; --> struct variable declaration and assignment
|
||||
// struct <struct_identifier> <decl_identifier>; --> struct variable declaration
|
||||
// struct <struct_identifier> <decl_identifier> = {...}; --> struct variable declaration and assignment
|
||||
// struct <struct_identifier> {...} <decl_identifier>; --> struct definition and variable declaration
|
||||
// struct <struct_identifier> : <base_struct,...> {...} <decl_identifier>; --> struct definition with inheritance and variable declaration
|
||||
// struct <struct_identifier> {...} <decl_identifier> = {...}; --> struct definition, variable declaration and assignment
|
||||
// struct <struct_identifier> : <base_struct,...> {...} <decl_identifier> = {...}; --> struct definition with inheritance, variable declaration and assignment
|
||||
// struct {...} <decl_identifier>; --> anonymous struct definition and variable declaration
|
||||
// struct : <base_struct,...> {...} <decl_identifier>; --> anonymous struct definition with inheritance and variable declaration
|
||||
// struct {...} <decl_identifier> = {...}; --> anonymous struct definition, variable declaration and assignment
|
||||
// struct : <base_struct,...> {...} <decl_identifier> = {...}; --> anonymous struct definition with inheritance, variable declaration and assignment
|
||||
|
||||
// typedef <struct_identifier> <type_identifier>;
|
||||
// typedef struct <struct_identifier> { ... } <type_identifier>;
|
||||
// typedef <struct_identifier> <type_identifier>;
|
||||
// typedef struct <struct_identifier> { ... } <type_identifier>;
|
||||
// typedef struct { ... } <type_identifier>;
|
||||
// const struct <struct_identifier> <decl_identifier> = {...};
|
||||
// const <struct_identifier> <decl_identifier> = {...};
|
||||
// const struct {...} <decl_identifier> = {...};
|
||||
|
||||
// The declaration is as follows:
|
||||
// <struct_identifier> <decl_identifier>;
|
||||
// struct <struct_identifier> <decl_identifier>;
|
||||
// struct <struct_identifier> { ... } <decl_identifier>;
|
||||
|
||||
CDefinitionEntity::Process();
|
||||
}
|
||||
|
||||
bool CStructEntity::Supports(EDefinitionSupport eSupport) const
|
||||
{
|
||||
switch (eSupport)
|
||||
{
|
||||
case EDefinitionSupport::support_variable: return true;
|
||||
case EDefinitionSupport::support_const_variable: return true;
|
||||
case EDefinitionSupport::support_typedef: return true;
|
||||
case EDefinitionSupport::support_struct: return true;
|
||||
case EDefinitionSupport::support_union: return true;
|
||||
case EDefinitionSupport::support_enum: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CStructEntity::CreateValueNode()
|
||||
{
|
||||
// Create a compound type value node for this definition.
|
||||
ValueRef() = std::make_shared<CCompoundTypeValueNode>(shared_from_this(), nullptr);
|
||||
}
|
||||
75
sdv_executables/sdv_idl_compiler/entities/struct_entity.h
Normal file
75
sdv_executables/sdv_idl_compiler/entities/struct_entity.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef STRUCT_ENTITY_H
|
||||
#define STRUCT_ENTITY_H
|
||||
|
||||
#include "definition_entity.h"
|
||||
|
||||
/**
|
||||
* @brief The struct definition of an IDL file.
|
||||
* @details The struct section of the IDL file contains multiple declarations of members, as well as the definitions of structs
|
||||
* and unions.
|
||||
*/
|
||||
class CStructEntity : public CDefinitionEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
*/
|
||||
CStructEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CStructEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns the struct type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_struct; }
|
||||
|
||||
/**
|
||||
* @brief Get the declaration type of the entity as string. Overload of CEntity::GetDeclTypeStr.
|
||||
* @param[in] bResolveTypedef When set, resolve the typedef type into the base type.
|
||||
* @return Returns a string with struct type.
|
||||
*/
|
||||
virtual std::string GetDeclTypeStr(bool bResolveTypedef) const override;
|
||||
|
||||
// Suppress cppcheck warning of a useless override. The function is here for better understanding.
|
||||
// cppcheck-suppress uselessOverride
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Request whether the definition supports the content. Overload of CDefintionEntity::Supports.
|
||||
* @param[in] eSupport The type of support that is requested.
|
||||
* @return Returns 'true' when the definition supports the content; 'false' otherwise.
|
||||
*/
|
||||
virtual bool Supports(EDefinitionSupport eSupport) const override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support inheritance? Overload of CDefinitionEntity::SupportsInheritance.
|
||||
* @return Returns whether the entity supports inheritance.
|
||||
*/
|
||||
virtual bool SupportsInheritance() const override { return true; }
|
||||
|
||||
// Suppress cppcheck warning of a useless override. The function is here for better understanding.
|
||||
// cppcheck-suppress uselessOverride
|
||||
/**
|
||||
* @brief Does the entity declaration support anonymous naming? Overload of CDefinitionEntity::SupportsAnonymous.
|
||||
* @remarks C11 supports anonymous structs. C++ not! Therefore, IDL does not support anonymous structs.
|
||||
* @return Returns whether the entity supports inheritance.
|
||||
*/
|
||||
virtual bool SupportsAnonymous() const override { return false; }
|
||||
|
||||
/**
|
||||
* @brief Create the content value node. Overload of CDefinitionEntity::CreateValueNode.
|
||||
* @details Create the value node and assign the value node to the ValueRef() reference..
|
||||
*/
|
||||
virtual void CreateValueNode() override;
|
||||
};
|
||||
|
||||
#endif // !defined(STRUCT_ENTITY_H)
|
||||
44
sdv_executables/sdv_idl_compiler/entities/typedef_entity.cpp
Normal file
44
sdv_executables/sdv_idl_compiler/entities/typedef_entity.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "typedef_entity.h"
|
||||
#include "../exception.h"
|
||||
|
||||
CTypedefEntity::CTypedefEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent) :
|
||||
CDeclarationEntity(rptrContext, ptrParent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CTypedefEntity::CTypedefEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent,
|
||||
const std::string& rssName) :
|
||||
CDeclarationEntity(rptrContext, ptrParent)
|
||||
{
|
||||
if (rssName.empty()) throw CCompileException("Internal error: trying to create a named type entity without valid name.");
|
||||
SetName(rssName, true, true);
|
||||
}
|
||||
|
||||
std::string CTypedefEntity::GetDeclTypeStr(bool bResolveTypedef) const
|
||||
{
|
||||
// When not resolving the typedef, return the default implementation ("typedef <name>").
|
||||
if (!bResolveTypedef) return std::string("typedef ") + GetScopedName();
|
||||
|
||||
// Otherwise resolve the typedef by taking the base type.
|
||||
if (GetTypeEntity())
|
||||
return GetTypeEntity()->GetDeclTypeStr(bResolveTypedef);
|
||||
else
|
||||
return DeclTypeToString(GetBaseType());
|
||||
}
|
||||
|
||||
void CTypedefEntity::Process()
|
||||
{
|
||||
CDeclarationEntity::Process();
|
||||
}
|
||||
|
||||
std::pair<CEntityPtr, bool> CTypedefEntity::FindLocal(const std::string& rssName, bool bDeclaration) const
|
||||
{
|
||||
// Call the find local function on the original type.
|
||||
if (!GetTypeEntity()) return std::pair<CEntityPtr, bool>();
|
||||
|
||||
return GetTypeEntity()->FindLocal(rssName, bDeclaration);
|
||||
}
|
||||
|
||||
|
||||
|
||||
79
sdv_executables/sdv_idl_compiler/entities/typedef_entity.h
Normal file
79
sdv_executables/sdv_idl_compiler/entities/typedef_entity.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#ifndef TYPEDEF_ENTITY_H
|
||||
#define TYPEDEF_ENTITY_H
|
||||
|
||||
#include "declaration_entity.h"
|
||||
|
||||
/**
|
||||
* @brief The const definition of an IDL file.
|
||||
* @details The const section of the IDL file defines const values.
|
||||
*/
|
||||
class CTypedefEntity : public CDeclarationEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
*/
|
||||
CTypedefEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Constructor for a local named type entity without parsing.
|
||||
* @attention This type entity is not attached as a child.
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
* @param[in] rssName Reference to the name.
|
||||
*/
|
||||
CTypedefEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, const std::string& rssName);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CTypedefEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return The typedef entity type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_typedef; }
|
||||
|
||||
/**
|
||||
* @brief Get the qualified type of the entity. Overload of CEntity::GetDeclTypeStr.
|
||||
* @attention To get the qualified type including array sizes, use the GetDeclTypeStr of the CEntityValueNode class.
|
||||
* @details The qualified type consists of "<base type> <type identifier>".
|
||||
* @param[in] bResolveTypedef When set, resolve the typedef type into the base type.
|
||||
* @return String with the typedef entity type.
|
||||
*/
|
||||
virtual std::string GetDeclTypeStr(bool bResolveTypedef) const override;
|
||||
|
||||
// Suppress cppcheck warning of a useless override. The function is here for better understanding.
|
||||
// cppcheck-suppress uselessOverride
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support arrays? Overload of CDeclarationEntity::SupportArrays.
|
||||
* @return Returns 'true' when the entity supports assignments; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportArrays() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity require an assignment? Overload of CDeclarationEntity::RequiresAssignment.
|
||||
* @return Returns 'true' when the entity requires an assignment; 'false' otherwise.
|
||||
*/
|
||||
virtual bool RequiresAssignment() const override { return false; }
|
||||
|
||||
/**
|
||||
* @brief Find the entity locally. Overload of CEntity::FindLocal.
|
||||
* @param[in] rssName Reference to the string object containing the name of the entity to search for.
|
||||
* @param[in] bDeclaration When set, the name belongs to a declaration; otherwise it belongs to a definition. Needed to allow
|
||||
* the reuse of names between declarations and definitions.
|
||||
* @return Returns a pair object containing an entity pointer if the entity exists or a NULL pointer if not as well as a
|
||||
* boolean that indicates that the entity was from an inherited entity.
|
||||
*/
|
||||
virtual std::pair<CEntityPtr, bool> FindLocal(const std::string& rssName, bool bDeclaration) const override;
|
||||
};
|
||||
|
||||
#endif // !defined(TYPEDEF_ENTITY_H)
|
||||
434
sdv_executables/sdv_idl_compiler/entities/union_entity.cpp
Normal file
434
sdv_executables/sdv_idl_compiler/entities/union_entity.cpp
Normal file
@@ -0,0 +1,434 @@
|
||||
#include "union_entity.h"
|
||||
#include "../exception.h"
|
||||
#include "../logger.h"
|
||||
#include "../parser.h"
|
||||
#include "typedef_entity.h"
|
||||
#include "variable_entity.h"
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
CCaseEntry::CCaseEntry(const CContextPtr& rptrContext, CEntityPtr ptrParent, bool bDefault) :
|
||||
CVariableEntity(rptrContext, ptrParent, false, false), m_bDefault(bDefault)
|
||||
{}
|
||||
|
||||
std::string CCaseEntry::GetDeclTypeStr(bool /*bResolveTypedef*/) const
|
||||
{
|
||||
return GetScopedName();
|
||||
}
|
||||
|
||||
sdv::interface_t CCaseEntry::GetInterface(sdv::interface_id idInterface)
|
||||
{
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::IInterfaceAccess>())
|
||||
return static_cast<sdv::IInterfaceAccess*>(this);
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::idl::ICaseEntity>())
|
||||
return static_cast<sdv::idl::ICaseEntity*>(this);
|
||||
return CVariableEntity::GetInterface(idInterface);
|
||||
}
|
||||
|
||||
sdv::u8string CCaseEntry::GetLabel() const
|
||||
{
|
||||
// The default case entry doesn#t have a label.
|
||||
if (m_bDefault) return sdv::u8string();
|
||||
|
||||
// Get the label string from the value of the case label entity.
|
||||
CVariableEntity* pLabelVariableEntity = m_ptrLabel->Get<CVariableEntity>();
|
||||
if (!pLabelVariableEntity)
|
||||
throw CCompileException("Internal error: expected a variable entity as case label.");
|
||||
if (!pLabelVariableEntity->ValueRef())
|
||||
throw CCompileException("Internal error: expected a value for the variable entity case label.");
|
||||
|
||||
// Enum value node?
|
||||
const CEnumValueNode* pEnumValueNode = pLabelVariableEntity->ValueRef()->Get<CEnumValueNode>();
|
||||
if (pEnumValueNode) return pEnumValueNode->String();
|
||||
|
||||
// Simple value node?
|
||||
const CSimpleTypeValueNode* pSimpleTypeValueNode = pLabelVariableEntity->ValueRef()->Get<CSimpleTypeValueNode>();
|
||||
if (pSimpleTypeValueNode) return pSimpleTypeValueNode->Variant().GetAsString();
|
||||
|
||||
// Otherwise error...
|
||||
throw CCompileException("Internal error: expected a value for the variable entity case label.");
|
||||
}
|
||||
|
||||
const CToken& CCaseEntry::GetLabelToken() const
|
||||
{
|
||||
return m_tokenLabel;
|
||||
}
|
||||
|
||||
void CCaseEntry::Process()
|
||||
{
|
||||
CLog log("Processing case label...");
|
||||
|
||||
// Peek for the label token (used for reporting parsing errors).
|
||||
m_tokenLabel = PeekToken();
|
||||
|
||||
// Processing of the case label value is done in post processing since the switch type might not be known yet.
|
||||
CToken token;
|
||||
std::string ssCaseLabel;
|
||||
while ((token = GetToken()) != ":")
|
||||
{
|
||||
if (!ssCaseLabel.empty())
|
||||
ssCaseLabel += ' ';
|
||||
ssCaseLabel += static_cast<std::string>(token);
|
||||
m_lstCaseValue.push_back(token);
|
||||
}
|
||||
log << "Case label name '" << ssCaseLabel << "'" << std::endl;
|
||||
|
||||
// Only unnamed nested struct and union definitions are not allowed. Furthermore, anonymous structs and unions (without
|
||||
// explicit declaration cannot be supported (also not part of the C++ standard). Varable based switch type unions are
|
||||
// also not supported since the variable for the switch needs to be part of the parent switch case and thus needs a struct to
|
||||
// hold it.
|
||||
token = PeekToken();
|
||||
if ((token == "struct" && (PeekToken(1) == "{" || PeekToken(2) == "{")) ||
|
||||
(token == "union" && (PeekToken(1) == "switch" || PeekToken(2) == "switch")))
|
||||
{
|
||||
// Get the struct/union from the code
|
||||
token = GetToken();
|
||||
|
||||
throw CCompileException(token, "Cannot make a definition inside an union.");
|
||||
}
|
||||
|
||||
// Stop processing if the case doesn't have any declaration (is followed by another case or a closing curled bracket).
|
||||
if (token == "case" || token == "}")
|
||||
{
|
||||
// Determine whether the comments are preceding the token (either on the same line or the line before).
|
||||
CTokenList lstPreComments = GetPreCommentTokenList();
|
||||
if (!lstPreComments.empty()) SetCommentTokens(lstPreComments);
|
||||
|
||||
// Assign any succeeding comments
|
||||
ProcessPostCommentTokenList(token.GetLine());
|
||||
|
||||
// Insert a semi-colon to identify that the statement is finished.
|
||||
CToken tokenSep(";", ETokenType::token_separator);
|
||||
PrependToken(tokenSep);
|
||||
SetName(GetParserRef().GenerateAnonymousEntityName("case"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Now let the variable process the declaration
|
||||
CVariableEntity::Process();
|
||||
}
|
||||
|
||||
void CCaseEntry::PostProcess()
|
||||
{
|
||||
CLog log("Post processing case label...");
|
||||
|
||||
// Get the base type of the enum entity and insert it in front of the declaration.
|
||||
CUnionEntity* pUnionEntity = GetParentEntity()->Get<CUnionEntity>();
|
||||
if (!pUnionEntity) throw CCompileException("Internal error: expected an union entity as parent.");
|
||||
|
||||
// Separate between case statement and default
|
||||
if (m_bDefault)
|
||||
{
|
||||
if (!m_lstCaseValue.empty())
|
||||
throw CCompileException("Default case label cannot have a value.");
|
||||
|
||||
|
||||
log << "Default case label" << std::endl;
|
||||
|
||||
} else
|
||||
{
|
||||
// Get the switch case type
|
||||
sdv::idl::EDeclType eSwitchCaseType = sdv::idl::EDeclType::decltype_unknown;
|
||||
CEntityPtr ptrSwitchCaseType;
|
||||
CValueNodePtr ptrSwitchCaseValue;
|
||||
pUnionEntity->GetSwitchCaseType(eSwitchCaseType, ptrSwitchCaseType, ptrSwitchCaseValue);
|
||||
|
||||
// Insert the switch type specific assignment to the token list
|
||||
m_lstCaseValue.push_front(CToken("="));
|
||||
m_lstCaseValue.push_front(CToken("label"));
|
||||
if (!ptrSwitchCaseType)
|
||||
{
|
||||
switch (eSwitchCaseType)
|
||||
{
|
||||
case sdv::idl::EDeclType::decltype_short: m_lstCaseValue.push_front(CToken("short")); break;
|
||||
case sdv::idl::EDeclType::decltype_long: m_lstCaseValue.push_front(CToken("long")); break;
|
||||
case sdv::idl::EDeclType::decltype_long_long: m_lstCaseValue.push_front(CToken("long long")); break;
|
||||
case sdv::idl::EDeclType::decltype_unsigned_short: m_lstCaseValue.push_front(CToken("unsigned short")); break;
|
||||
case sdv::idl::EDeclType::decltype_unsigned_long: m_lstCaseValue.push_front(CToken("unsigned long")); break;
|
||||
case sdv::idl::EDeclType::decltype_unsigned_long_long: m_lstCaseValue.push_front(CToken("unsigned long long")); break;
|
||||
case sdv::idl::EDeclType::decltype_octet: m_lstCaseValue.push_front(CToken("octet")); break;
|
||||
case sdv::idl::EDeclType::decltype_char: m_lstCaseValue.push_front(CToken("char")); break;
|
||||
case sdv::idl::EDeclType::decltype_char16: m_lstCaseValue.push_front(CToken("char16")); break;
|
||||
case sdv::idl::EDeclType::decltype_char32: m_lstCaseValue.push_front(CToken("char32")); break;
|
||||
case sdv::idl::EDeclType::decltype_wchar: m_lstCaseValue.push_front(CToken("wchar")); break;
|
||||
case sdv::idl::EDeclType::decltype_boolean: m_lstCaseValue.push_front(CToken("boolean")); break;
|
||||
case sdv::idl::EDeclType::decltype_native: m_lstCaseValue.push_front(CToken("native")); break;
|
||||
default: throw CCompileException(m_tokenLabel, "Internal error: invalid switch case data type.");
|
||||
}
|
||||
}
|
||||
else
|
||||
m_lstCaseValue.push_front(CToken(ptrSwitchCaseType->GetScopedName()));
|
||||
m_lstCaseValue.push_back(CToken(";", ETokenType::token_separator));
|
||||
|
||||
// Create the label value.
|
||||
m_ptrLabel = std::make_shared<CVariableEntity>(GetContext(), shared_from_this(), m_lstCaseValue, true, false);
|
||||
|
||||
// Process the label variable (this will resolve any assigned value and constant).
|
||||
m_ptrLabel->Process();
|
||||
CVariableEntity* pLabelVariableEntity = m_ptrLabel->Get<CVariableEntity>();
|
||||
if (!pLabelVariableEntity)
|
||||
throw CCompileException("Internal error: expected a variable entity as case label.");
|
||||
pLabelVariableEntity->PostProcess();
|
||||
|
||||
log << "Case label is: " << GetLabel() << std::endl;
|
||||
}
|
||||
|
||||
// Post process the assignment
|
||||
CVariableEntity::PostProcess();
|
||||
}
|
||||
|
||||
CUnionEntity::CUnionEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent) :
|
||||
CStructEntity(rptrContext, ptrParent)
|
||||
{}
|
||||
|
||||
sdv::interface_t CUnionEntity::GetInterface(sdv::interface_id idInterface)
|
||||
{
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::IInterfaceAccess>())
|
||||
return static_cast<sdv::IInterfaceAccess*>(this);
|
||||
if (idInterface == sdv::GetInterfaceId<sdv::idl::IUnionEntity>())
|
||||
return static_cast<sdv::idl::IUnionEntity*>(this);
|
||||
return CStructEntity::GetInterface(idInterface);
|
||||
}
|
||||
|
||||
sdv::idl::IUnionEntity::ESwitchInterpret CUnionEntity::GetSwitchInterpretation() const
|
||||
{
|
||||
return m_eSwitchInterpret;
|
||||
}
|
||||
|
||||
void CUnionEntity::GetSwitchType(/*out*/ sdv::idl::EDeclType& reType, /*out*/ sdv::IInterfaceAccess*& rpType) const
|
||||
{
|
||||
reType = m_typedeclSwitch.GetBaseType();
|
||||
rpType = m_typedeclSwitch.GetTypeDefinition();
|
||||
}
|
||||
|
||||
void CUnionEntity::GetSwitchVar(/*out*/ sdv::u8string& rssVarStr, /*out*/ sdv::IInterfaceAccess*& rpVarEntity,
|
||||
/*out*/ sdv::IInterfaceAccess*& rpVarContainer) const
|
||||
{
|
||||
rssVarStr.clear();
|
||||
rpVarEntity = nullptr;
|
||||
rpVarContainer = nullptr;
|
||||
if (m_eSwitchInterpret == sdv::idl::IUnionEntity::ESwitchInterpret::switch_type) return;
|
||||
rssVarStr = m_ssValueNode;
|
||||
rpVarEntity = m_ptrSwitchValueNode ? m_ptrSwitchValueNode->GetDeclEntity()->Get<sdv::IInterfaceAccess>() : nullptr;
|
||||
rpVarContainer = m_ptrContainer ? m_ptrContainer->Get<sdv::IInterfaceAccess>() : nullptr;
|
||||
}
|
||||
|
||||
std::string CUnionEntity::GetDeclTypeStr(bool /*bResolveTypedef*/) const
|
||||
{
|
||||
return std::string("union ") + GetScopedName();
|
||||
}
|
||||
|
||||
void CUnionEntity::Process()
|
||||
{
|
||||
// The definition and declaration can be defined:
|
||||
// union <union_identifier>; --> forward declaration
|
||||
// union <union_identifier> switch(<type>) {...}; --> union definition with type
|
||||
// struct { <type> <var>; union <union_identifier> switch(<var>) {...};}; --> union definition with varaiable
|
||||
// <union_identifier> <decl_identifier>; --> union variable declaration
|
||||
// <union_identifier> <decl_identifier> = {...}; --> union variable declaration and assignment
|
||||
// union <union_identifier> <decl_identifier>; --> union variable declaration
|
||||
// union <union_identifier> <decl_identifier> = {...}; --> union variable declaration and assignment
|
||||
// union <union_identifier> {...} <decl_identifier>; --> union definition and variable declaration
|
||||
// union <union_identifier> {...} <decl_identifier> = {...}; --> union definition, variable declaration and assignment
|
||||
// union {...} <decl_identifier>; --> anonymous union definition and variable declaration
|
||||
// union {...} <decl_identifier> = {...}; --> anonymous union definition, variable declaration and assignment
|
||||
|
||||
// typedef <union_identifier> <type_identifier>;
|
||||
// typedef union <union_identifier> { ... } <type_identifier>;
|
||||
// typedef <union_identifier> <type_identifier>;
|
||||
// typedef union <union_identifier> { ... } <type_identifier>;
|
||||
// typedef union { ... } <type_identifier>;
|
||||
// const union <union_identifier> <decl_identifier> = {...};
|
||||
// const <union_identifier> <decl_identifier> = {...};
|
||||
// const union {...} <decl_identifier> = {...};
|
||||
|
||||
// The declaration is as follows:
|
||||
// <union_identifier> <decl_identifier>;
|
||||
// union <union_identifier> <decl_identifier>;
|
||||
// union <union_identifier> { ... } <decl_identifier>;
|
||||
|
||||
CStructEntity::Process();
|
||||
}
|
||||
|
||||
void CUnionEntity::ProcessDefinitionAddendum()
|
||||
{
|
||||
//unions are defined as :
|
||||
//union <union_identifier> switch (<type>)-- > type is a integral or enum type or a typedef of this
|
||||
//{
|
||||
//case <value>: <type> <var_identifier> -- > case values need to be unique
|
||||
// ...
|
||||
//};
|
||||
//struct
|
||||
//{
|
||||
// <type> <var>;
|
||||
// union <union_identifier> switch (<var>)-- > var is an integral or enum value, which is part of the struct
|
||||
// {
|
||||
// case <value>: <type> <var_identifier> -- > case values need to be unique
|
||||
// ...
|
||||
// };
|
||||
//};
|
||||
|
||||
if (PeekToken() == ";") return; // Forward declaration
|
||||
CToken token = GetToken();
|
||||
if (token != "switch") throw CCompileException(token, "Expecting a switch statement following the union identifier.");
|
||||
token = GetToken();
|
||||
if (token != "(") throw CCompileException(token, "Expecting a left bracket '('.");
|
||||
size_t nIndex = 0;
|
||||
while (true)
|
||||
{
|
||||
token = PeekToken(nIndex++);
|
||||
if (!token || token == ")") break;
|
||||
m_ssSwitchVar += static_cast<std::string>(token);
|
||||
}
|
||||
m_typedeclSwitch = ProcessType(true);
|
||||
token = GetToken();
|
||||
while (token && token != ")")
|
||||
{
|
||||
m_ssValueNode += static_cast<std::string>(token);
|
||||
token = GetToken();
|
||||
}
|
||||
if (token != ")") throw CCompileException(token, "Expecting a right bracket ')'.");
|
||||
|
||||
// Was it possible to resolve the type for the switch case. If not, the switch case is a variable?
|
||||
if (m_typedeclSwitch.GetBaseType() == sdv::idl::EDeclType::decltype_unknown)
|
||||
m_eSwitchInterpret = sdv::idl::IUnionEntity::ESwitchInterpret::switch_variable;
|
||||
}
|
||||
|
||||
void CUnionEntity::PostProcess()
|
||||
{
|
||||
if (ForwardDeclaration()) return;
|
||||
|
||||
// Was the switch case type/variable found before? If not, check for a variable.
|
||||
if (m_eSwitchInterpret == sdv::idl::IUnionEntity::ESwitchInterpret::switch_variable)
|
||||
{
|
||||
// Get the switch type object
|
||||
CEntityPtr ptrSwitchVarBase = Find(m_typedeclSwitch.GetTypeString());
|
||||
if (!ptrSwitchVarBase)
|
||||
throw CCompileException(m_ssSwitchVar,
|
||||
"The switch case must be determined by a predefined type or a member variable.");
|
||||
|
||||
// Proper relative name (without global scope)
|
||||
std::string ssSwitchFullName = ptrSwitchVarBase->GetName() + m_ssValueNode;
|
||||
m_ssValueNode = ssSwitchFullName;
|
||||
|
||||
// The type must be a variable type
|
||||
CVariableEntity* pVarEntityBase = ptrSwitchVarBase->Get<CVariableEntity>();
|
||||
if (!pVarEntityBase)
|
||||
throw CCompileException(m_ssSwitchVar,
|
||||
"The switch case is not determined by a member variable nor a predefined type.");
|
||||
|
||||
// The parent of the base is the common parent of both the switch var and the union.
|
||||
m_ptrContainer = ptrSwitchVarBase->GetParentEntity();
|
||||
if (!m_ptrContainer)
|
||||
throw CCompileException(m_ssSwitchVar,
|
||||
"The switch case variable and the union do not share a common parent.");
|
||||
|
||||
// Find the value node of the switch variable (in case it is a child some layers deep).
|
||||
CValueNodePtr ptrSwitchValueNode;
|
||||
if (!m_ssValueNode.empty())
|
||||
m_ptrSwitchValueNode = pVarEntityBase->FindValue(m_ssValueNode);
|
||||
else
|
||||
m_ptrSwitchValueNode = pVarEntityBase->ValueRef();
|
||||
if (!m_ptrSwitchValueNode)
|
||||
throw CCompileException(m_ssSwitchVar, "Could not find the switch variable.");
|
||||
|
||||
// Change the variable type entity to a switch variable.
|
||||
m_ptrSwitchValueNode->GetDeclEntity()->Get<CVariableEntity>()->UseAsSwitchVariable();
|
||||
|
||||
// Assign the type of the variable.
|
||||
m_typedeclSwitch.SetTypeDefinitionEntityPtr(m_ptrSwitchValueNode->GetDeclEntity()->GetTypeEntity());
|
||||
m_typedeclSwitch.SetBaseType(m_ptrSwitchValueNode->GetDeclEntity()->GetBaseType());
|
||||
if (!IsIntegralDeclType(m_typedeclSwitch.GetBaseType()) &&
|
||||
m_typedeclSwitch.GetBaseType() != sdv::idl::EDeclType::decltype_enum)
|
||||
throw CCompileException(m_ssSwitchVar, "Expecting an integral or enum identifier type or variable.");
|
||||
|
||||
// Check whether one of the parents is a struct or a union and the variable is a struct member.
|
||||
CEntityPtr ptrParent = GetParentEntity();
|
||||
if (!ptrParent ||
|
||||
((ptrParent->GetType() != sdv::idl::EEntityType::type_struct) &&
|
||||
(ptrParent->GetType() != sdv::idl::EEntityType::type_exception)))
|
||||
throw CCompileException(m_ssSwitchVar,
|
||||
"The union needs to be part of a struct or an exception when used with a variable based switch case.");
|
||||
while (ptrSwitchVarBase)
|
||||
{
|
||||
if (!ptrParent ||
|
||||
((ptrParent->GetType() != sdv::idl::EEntityType::type_struct) &&
|
||||
(ptrParent->GetType() != sdv::idl::EEntityType::type_exception)))
|
||||
throw CCompileException(m_ssSwitchVar,
|
||||
"The variable used in the switch case must be a member of the same or parent struct or exception the union "
|
||||
"is declared in.");
|
||||
if (ptrParent->GetType() == sdv::idl::EEntityType::type_struct &&
|
||||
ptrParent == ptrSwitchVarBase->GetParentEntity())
|
||||
break;
|
||||
|
||||
ptrParent = ptrParent->GetParentEntity();
|
||||
}
|
||||
}
|
||||
|
||||
// Post process all the case statements
|
||||
std::set<std::string> setValues;
|
||||
bool bDefaultFound = false;
|
||||
for (CEntityPtr ptrEntity : m_lstDeclMembers)
|
||||
{
|
||||
CCaseEntry* pCaseEntry = ptrEntity->Get<CCaseEntry>();
|
||||
if (!pCaseEntry) throw CCompileException("Internal error: unexpected entity stored at union.");
|
||||
pCaseEntry->PostProcess();
|
||||
|
||||
// Differentiate between default and standard case label...
|
||||
if (pCaseEntry->IsDefault())
|
||||
{
|
||||
if (bDefaultFound)
|
||||
throw CCompileException(pCaseEntry->GetLabelToken(), "Duplicate default switch found.");
|
||||
bDefaultFound = true;
|
||||
} else
|
||||
{
|
||||
// Check for the existence of the label.
|
||||
std::string ssLabel = pCaseEntry->GetLabel();
|
||||
if (m_setValues.find(ssLabel) != m_setValues.end())
|
||||
throw CCompileException(pCaseEntry->GetLabelToken(), "Duplicate switch case label found.");
|
||||
m_setValues.insert(ssLabel);
|
||||
}
|
||||
}
|
||||
|
||||
// If supported create the value node for the definition (this allows assignments of values to this entity).
|
||||
CreateValueNode();
|
||||
}
|
||||
|
||||
bool CUnionEntity::Supports(EDefinitionSupport eSupport) const
|
||||
{
|
||||
switch (eSupport)
|
||||
{
|
||||
case EDefinitionSupport::support_case_declaration: return true;
|
||||
case EDefinitionSupport::support_variable: return false;
|
||||
case EDefinitionSupport::support_const_variable: return false;
|
||||
case EDefinitionSupport::support_typedef: return false;
|
||||
case EDefinitionSupport::support_struct: return false;
|
||||
case EDefinitionSupport::support_union: return false;
|
||||
case EDefinitionSupport::support_enum: return false;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CUnionEntity::CreateValueNode()
|
||||
{
|
||||
// Create a compound type value node for this definition.
|
||||
ValueRef() = std::make_shared<CCompoundTypeValueNode>(shared_from_this(), nullptr);
|
||||
}
|
||||
|
||||
bool CUnionEntity::RequireDeclaration() const
|
||||
{
|
||||
// Require a declaration when unnamed union.
|
||||
return !ForwardDeclaration() && IsUnnamed();
|
||||
}
|
||||
|
||||
bool CUnionEntity::AllowAutoTransparentDeclaration() const
|
||||
{
|
||||
return !ForwardDeclaration() && IsUnnamed();
|
||||
}
|
||||
|
||||
void CUnionEntity::GetSwitchCaseType(sdv::idl::EDeclType& reType, CEntityPtr& rptrType, CValueNodePtr& rptrValue)
|
||||
{
|
||||
reType = m_typedeclSwitch.GetBaseType();
|
||||
rptrType = m_typedeclSwitch.GetTypeDefinitionEntityPtr();
|
||||
if (m_ptrSwitchValueNode) rptrValue = m_ptrSwitchValueNode;
|
||||
}
|
||||
233
sdv_executables/sdv_idl_compiler/entities/union_entity.h
Normal file
233
sdv_executables/sdv_idl_compiler/entities/union_entity.h
Normal file
@@ -0,0 +1,233 @@
|
||||
#ifndef UNION_ENTITY_H
|
||||
#define UNION_ENTITY_H
|
||||
|
||||
#include "definition_entity.h"
|
||||
#include "struct_entity.h"
|
||||
#include "variable_entity.h"
|
||||
#include "entity_value.h"
|
||||
#include <set>
|
||||
|
||||
/**
|
||||
* @brief The enum entry declaration.
|
||||
*/
|
||||
class CCaseEntry : public CVariableEntity, public sdv::idl::ICaseEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
* @param[in] bDefault When set, the entry is the default case entry.
|
||||
*/
|
||||
CCaseEntry(const CContextPtr& rptrContext, CEntityPtr ptrParent, bool bDefault);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CCaseEntry() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get access to another interface. Overload of sdv::IInterfaceAccess::GetInterface.
|
||||
* @param[in] idInterface The interface id to get access to.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
virtual sdv::interface_t GetInterface(sdv::interface_id idInterface) override;
|
||||
|
||||
/**
|
||||
* @brief Get the case label string. Overload of sdv::idl::ICaseEntity::GetLabel.
|
||||
* @return The label string.
|
||||
*/
|
||||
virtual sdv::u8string GetLabel() const override;
|
||||
|
||||
/**
|
||||
* @brief Is the case a default cae entry. Overload of sdv::idl::ICaseEntity::IsDefault.
|
||||
* @return Returns whether this is the default case entry.
|
||||
*/
|
||||
virtual bool IsDefault() const override { return m_bDefault; }
|
||||
|
||||
/**
|
||||
* @brief Get the label token (used for error reporting).
|
||||
* @return Returns a reference to the variable containing the label token.
|
||||
*/
|
||||
const CToken& GetLabelToken() const;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns the union entity type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_case_entry; }
|
||||
|
||||
/**
|
||||
* @brief Get the declaration type of the entity as string. Overload of CEntity::GetDeclTypeStr.
|
||||
* @param[in] bResolveTypedef When set, resolve the typedef type into the base type.
|
||||
* @return Returns a string with union type.
|
||||
*/
|
||||
virtual std::string GetDeclTypeStr(bool bResolveTypedef) const override;
|
||||
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Post process the case entry.
|
||||
*/
|
||||
void PostProcess();
|
||||
|
||||
/**
|
||||
* @brief The entity doesn't support assignments. Overload of CDeclarationEntity::SupportAssignments.
|
||||
* @return Returns whether assignments are supported (which is not the case).
|
||||
*/
|
||||
virtual bool SupportAssignments() const override { return false; }
|
||||
|
||||
private:
|
||||
bool m_bDefault = false; ///< When set, the case entry is the default case entry.
|
||||
CToken m_tokenLabel; ///< Label token.
|
||||
CEntityPtr m_ptrLabel; ///< The case label entity.
|
||||
CTokenList m_lstCaseValue; ///< Case value token list parsed during post processing.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The struct definition of an IDL file.
|
||||
* @details The struct section of the IDL file contains multiple declarations of members, as well as the definitions of structs
|
||||
* and unions.
|
||||
*/
|
||||
class CUnionEntity : public CStructEntity, public sdv::idl::IUnionEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
*/
|
||||
CUnionEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CUnionEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get access to another interface. Overload of sdv::IInterfaceAccess::GetInterface.
|
||||
* @param[in] idInterface The interface id to get access to.
|
||||
* @return Returns a pointer to the interface or NULL when the interface is not supported.
|
||||
*/
|
||||
virtual sdv::interface_t GetInterface(sdv::interface_id idInterface) override;
|
||||
|
||||
/**
|
||||
* @brief Return the switch interpretation. Overload of sdv::idl::IUnionEntity::GetSwitchInterpretation.
|
||||
* @return The interpretation of the switch case of this union.
|
||||
*/
|
||||
virtual sdv::idl::IUnionEntity::ESwitchInterpret GetSwitchInterpretation() const override;
|
||||
|
||||
/**
|
||||
* @brief Return type information for the switch case. If the switch case is type base, this is the type information
|
||||
* that is used to select. If the switch case is variable based, this is the type of the variable. Overload of
|
||||
* sdv::idl::IUnionEntity::GetSwitchType.
|
||||
* @param[out] reType Reference to the declaration type (either enum or an integral type).
|
||||
* @param[out] rpType Reference to the type entity if existing.
|
||||
*/
|
||||
virtual void GetSwitchType(/*out*/ sdv::idl::EDeclType& reType, /*out*/ sdv::IInterfaceAccess*& rpType) const;
|
||||
|
||||
/**
|
||||
* @brief Get the switch variable information if the switch case is variable based. Will be empty/NULL when the switch
|
||||
* case is type based. Overload of sdv::idl::IUnionEntity::GetSwitchVar.
|
||||
* @param[out] rssVarStr Reference to the string receiving the exact scoped declaration name of the switch variable if
|
||||
* the interpretation is variable based. The variable name uses the scope separator '::' to define the common parent
|
||||
* definition and the member separator '.' to define the variable declaration as member from the common parent.
|
||||
* @param[out] rpVarEntity Reference to the variable entity if the interpretation is variable based.
|
||||
* @param[out] rpVarContainer Reference to the variable entity of the container of both the switch variable and the
|
||||
* union.
|
||||
*/
|
||||
virtual void GetSwitchVar(/*out*/ sdv::u8string& rssVarStr, /*out*/ sdv::IInterfaceAccess*& rpVarEntity,
|
||||
/*out*/ sdv::IInterfaceAccess*& rpVarContainer) const;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns the union type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override { return sdv::idl::EEntityType::type_union; }
|
||||
|
||||
/**
|
||||
* @brief Get the declaration type of the entity as string. Overload of CEntity::GetDeclTypeStr.
|
||||
* @param[in] bResolveTypedef When set, resolve the typedef type into the base type.
|
||||
* @return Returns the declaration type string.
|
||||
*/
|
||||
virtual std::string GetDeclTypeStr(bool bResolveTypedef) const override;
|
||||
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Process the definition addendum.
|
||||
* @details Process the definition addendum following the definition statement before the content definition. The default
|
||||
* implementation checks for an inheritance list.
|
||||
*/
|
||||
virtual void ProcessDefinitionAddendum() override;
|
||||
|
||||
/**
|
||||
* @brief Postprocess the switch/case assignments.
|
||||
*/
|
||||
void PostProcess();
|
||||
|
||||
/**
|
||||
* @brief Request whether the definition supports the content. Overload of CDefintionEntity::Supports.
|
||||
* @param[in] eSupport The type of support that is requested.
|
||||
* @return Returns 'true' when the definition supports the content; 'false' otherwise.
|
||||
*/
|
||||
virtual bool Supports(EDefinitionSupport eSupport) const override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support anonymous naming?
|
||||
* @details The default implementation is that anonymous naming is not supported.
|
||||
* @details Returns whether the entity supports inheritance.
|
||||
* @return Returns whether anonymous naming is supported.
|
||||
*/
|
||||
virtual bool SupportsAnonymous() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Create the content value node. Overload of CDefinitionEntity::CreateValueNode.
|
||||
* @details Create the value node and assign the value node to the ValueRef() reference..
|
||||
*/
|
||||
virtual void CreateValueNode() override;
|
||||
|
||||
/**
|
||||
* @brief Does the definition require a declaration? Overload of CDefinitionEntity::RequireDeclaration.
|
||||
* @return Returns whether a declaration is required.
|
||||
*/
|
||||
virtual bool RequireDeclaration() const override;
|
||||
|
||||
/**
|
||||
* @brief Does the definition allow automatic transparent declaration if not present? Overload of
|
||||
* CDefinitionEntity::AllowAutoTransparentDeclaration.
|
||||
* @details When set an automatic transparent declaration is allowed without an explicit variable declaration. Currently this
|
||||
* is only the case with unions with a variable based switch type.
|
||||
* @return Returns whether the definition allows an automatic transparent declaration.
|
||||
*/
|
||||
virtual bool AllowAutoTransparentDeclaration() const override;
|
||||
|
||||
/**
|
||||
* @brief Get switch case type.
|
||||
* @param[out] reType Reference to the base type of the switch variable.
|
||||
* @param[out] rptrType Reference to the type definition of the switch variable. Can be null if the switch uses a basic type.
|
||||
* @param[out] rptrValue Reference to the value node of the switch variable. Can be null if the switch is determined by a type.
|
||||
*/
|
||||
void GetSwitchCaseType(sdv::idl::EDeclType& reType, CEntityPtr& rptrType, CValueNodePtr& rptrValue);
|
||||
|
||||
private:
|
||||
/// Switch case interpretation.
|
||||
sdv::idl::IUnionEntity::ESwitchInterpret m_eSwitchInterpret = sdv::idl::IUnionEntity::ESwitchInterpret::switch_type;
|
||||
std::string m_ssSwitchVar; ///< Switch name
|
||||
CTypeDeclaration m_typedeclSwitch; ///< The identifier within the switch case.
|
||||
std::string m_ssValueNode; ///< Value node of the variable. If not existing the switch could either be
|
||||
///< a type or a variable entity.
|
||||
CEntityPtr m_ptrContainer; ///< The common container of both the switch variable and the union if the
|
||||
///< switch case is variable based.
|
||||
std::set<std::string> m_setValues; ///< Case entry values.
|
||||
CValueNodePtr m_ptrSwitchValueNode; ///< Value node of the switch entity of a variable based switch.
|
||||
|
||||
};
|
||||
|
||||
#endif // !defined(UNION_ENTITY_H)
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "variable_entity.h"
|
||||
#include "typedef_entity.h"
|
||||
#include "../exception.h"
|
||||
|
||||
CVariableEntity::CVariableEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, bool bConst, bool bAnonymous) :
|
||||
CDeclarationEntity(rptrContext, ptrParent), m_bConst(bConst), m_bAnonymous(bAnonymous)
|
||||
{}
|
||||
|
||||
CVariableEntity::CVariableEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, const CTokenList& rlstTokenList,
|
||||
bool bConst, bool bAnonymous) :
|
||||
CDeclarationEntity(rptrContext, ptrParent, rlstTokenList), m_bConst(bConst), m_bAnonymous(bAnonymous)
|
||||
{}
|
||||
|
||||
std::string CVariableEntity::GetDeclTypeStr(bool bResolveTypedef) const
|
||||
{
|
||||
if (GetTypeEntity())
|
||||
return GetTypeEntity()->GetDeclTypeStr(bResolveTypedef);
|
||||
else
|
||||
return DeclTypeToString(GetBaseType());
|
||||
}
|
||||
|
||||
void CVariableEntity::Process()
|
||||
{
|
||||
CDeclarationEntity::Process();
|
||||
|
||||
// TODO: Const variables cannot contain:
|
||||
// - dynamic arrays when no assignment is there
|
||||
// - interfaces
|
||||
// - structure or unions with unassigned dynamic arrays or interfaces
|
||||
}
|
||||
|
||||
135
sdv_executables/sdv_idl_compiler/entities/variable_entity.h
Normal file
135
sdv_executables/sdv_idl_compiler/entities/variable_entity.h
Normal file
@@ -0,0 +1,135 @@
|
||||
#ifndef DECLARATOR_ENTITY_H
|
||||
#define DECLARATOR_ENTITY_H
|
||||
|
||||
#include "declaration_entity.h"
|
||||
|
||||
/**
|
||||
* @brief The variable declaration.
|
||||
*/
|
||||
class CVariableEntity : public CDeclarationEntity
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
* @param[in] bConst When set, the variable is defined as const.
|
||||
* @param[in] bAnonymous When set, the variable is part of a struct and anonymous (unnamed and not declared) so its members are
|
||||
* seen as members of the struct. For example, used with unions.
|
||||
*/
|
||||
CVariableEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, bool bConst, bool bAnonymous);
|
||||
|
||||
/**
|
||||
* @brief Constructor using the provided token-list to process the code.
|
||||
* @param[in] rptrContext Reference to the smart pointer holding the parse context. Must not be NULL.
|
||||
* @param[in] ptrParent Pointer to the parent class holding this entity. This must not be NULL.
|
||||
* @param[in] rlstTokenList Reference to the token list holding the tokens to process.
|
||||
* @param[in] bConst When set, the variable is defined as const.
|
||||
* @param[in] bAnonymous When set, the variable is part of a struct and anonymous (unnamed and not declared) so its members are
|
||||
* seen as members of the struct. For example, used with unions.
|
||||
*/
|
||||
CVariableEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent, const CTokenList& rlstTokenList, bool bConst,
|
||||
bool bAnonymous);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~CVariableEntity() override = default;
|
||||
|
||||
/**
|
||||
* @brief Get the type of the entity. Overload of CEntity::GetType.
|
||||
* @return Returns the entity type.
|
||||
*/
|
||||
virtual sdv::idl::EEntityType GetType() const override
|
||||
{
|
||||
return m_bPartOfSwitch ? sdv::idl::EEntityType::type_switch_variable : sdv::idl::EEntityType::type_variable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the qualified type of the entity. Overload of CEntity::GetDeclTypeStr.
|
||||
* @attention To get the qualified type including array sizes, use the GetDeclTypeStr of the CEntityValueNode class.
|
||||
* @details The qualified type consists of "<base type> <type identifier>".
|
||||
* @param[in] bResolveTypedef When set, resolve the typedef type into the base type.
|
||||
* @return Returns the type string.
|
||||
*/
|
||||
virtual std::string GetDeclTypeStr(bool bResolveTypedef) const override;
|
||||
|
||||
// Suppress cppcheck warning of a useless override. The function is here for better understanding.
|
||||
// cppcheck-suppress uselessOverride
|
||||
/**
|
||||
* @brief Process the code. Overload of CEntity::Process.
|
||||
*/
|
||||
virtual void Process() override;
|
||||
|
||||
/**
|
||||
* @brief Does the entity support assignments? Overload of CDeclarationEntity::SupportAssignments.
|
||||
* @return Returns 'true' when the entity supports assignments; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportAssignments() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Can the entity be used for assignments of complex types? Overload of
|
||||
* CDeclarationEntity::CanSupportComplexTypeAssignments.
|
||||
* @return Returns 'true' when the entity defined as declaration; 'false' otherwise.
|
||||
*/
|
||||
virtual bool CanSupportComplexTypeAssignments() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support arrays? Overload of CDeclarationEntity::SupportArrays.
|
||||
* @return Returns 'true' when the entity supports assignments; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportArrays() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Is the entity readonly? Overload of IEntityInfo::IsReadOnly.
|
||||
* @return Returns 'true' when the entity defined as readonly; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsReadOnly() const override { return m_bConst; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity require an assignment? Overload of CDeclarationEntity::RequiresAssignment.
|
||||
* @return Returns 'true' when the entity requires an assignment; 'false' otherwise.
|
||||
*/
|
||||
virtual bool RequiresAssignment() const override { return m_bConst; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support multiple declarations on one line of code? Overload of
|
||||
* CDeclarationEntity::SupportMultipleDeclarations.
|
||||
* @return Returns 'true' when the entity supports multiple declarations; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportMultipleDeclarations() const override { return true; }
|
||||
|
||||
/**
|
||||
* @brief Is the entity anonymous when used in a struct/union (unnamed and not declared)? Overload of
|
||||
* IDeclarationEntity::IsAnonymous.
|
||||
* @return Returns 'true' when the entity is anonymous; 'false' otherwise.
|
||||
*/
|
||||
virtual bool IsAnonymous() const override { return m_bAnonymous; }
|
||||
|
||||
/**
|
||||
* @brief Enable the variable to be used in a union switch.
|
||||
*/
|
||||
void UseAsSwitchVariable() { m_bPartOfSwitch = true; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Set the variable as anonymous variable (unnamed and not declared).
|
||||
*/
|
||||
void SetAnonymous() { m_bAnonymous = true; }
|
||||
|
||||
/**
|
||||
* @brief Does the entity support an interface as base type (non-const variables, operations and parameters do)?
|
||||
* @details Returns whether the entity supports the an interface as base type base type. Default value is 'false'.
|
||||
* @return Returns 'true' when the entity supports interfaces as base type; 'false' otherwise.
|
||||
*/
|
||||
virtual bool SupportInterface() const override { return !m_bConst; }
|
||||
|
||||
private:
|
||||
bool m_bConst = false; ///< When set, the variable is defined as const.
|
||||
bool m_bAnonymous = false; ///< When set, the variable declared anonymous (unnamed and not declared) so its members
|
||||
///< are directly part of the parent struct.
|
||||
bool m_bPartOfSwitch = false; ///< When set, the variable is used in a union switch.
|
||||
};
|
||||
|
||||
|
||||
#endif // !defined(DECLARATOR_ENTITY_H)
|
||||
Reference in New Issue
Block a user