khanat-opennel-code/code/ryzom/tools/pd_parser/parse_node.h
2012-12-08 11:24:43 +01:00

1485 lines
30 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef RY_PD_PARSE_NODE_H
#define RY_PD_PARSE_NODE_H
#include "tokenizer.h"
#include "cpp_output.h"
#include "templatizer.h"
extern CTokenizer Tokenizer;
extern std::string getFunctionPrefix;
extern std::string setFunctionPrefix;
extern std::string newFunction;
extern std::string deleteFunction;
extern std::string indexVariable;
extern std::string valueVariable;
extern std::string keyVariable;
extern std::string objectVariable;
extern std::string staticCreateFunction;
extern std::string staticRemoveFunction;
extern std::string staticSetUserFactoryFunction;
extern std::string staticLoadFunction;
extern std::string staticUnloadFunction;
extern std::string staticGetFunction;
extern std::string initFunction;
extern std::string destroyFunction;
extern std::string registerFunction;
extern std::string registerAttributesFunction;
extern std::string unregisterFunction;
extern std::string unregisterAttributesFunction;
extern std::string fetchFunction;
extern std::string setParentFunction;
extern std::string setUnnotifiedParentFunction;
extern std::string getTableFunction;
extern std::string unlinkFunction;
extern std::string staticInitFactoryFunction;
extern std::string staticFactoryFunction;
extern std::string staticFetchFunction;
extern std::string staticInitFunction;
extern std::string logStartFunction;
extern std::string logStopFunction;
class CFileNode;
class CDbNode;
class CTypeNode;
class CClassNode;
class CIndexNode;
class CEnumNode;
class CDimensionNode;
class CLogMsgNode;
//
class CParseNode
{
public:
CParseNode() : Parent(NULL), FileNode(NULL), DbNode(NULL), Env(NULL) {}
virtual ~CParseNode()
{
uint i;
for (i=0; i<Nodes.size(); ++i)
delete Nodes[i];
}
CParseNode* Parent;
std::vector<CParseNode*> Nodes;
CTokenizer::CToken StartToken;
std::string Name;
std::string Description;
///
virtual bool prolog() { return true; }
virtual bool epilog() { return true; }
///
bool execute()
{
if (!prolog())
return false;
uint i;
for (i=0; i<Nodes.size(); ++i)
if (!Nodes[i]->execute())
return false;
return epilog();
}
/// Issue error
void error(const std::string &errMsg, const char *errType = "semantic")
{
Tokenizer.error(StartToken, errType, errMsg.c_str() );
}
///
CParseNode* getNode(const std::string &name)
{
uint i;
for (i=0; i<Nodes.size(); ++i)
if (Nodes[i]->Name == name)
return Nodes[i];
return NULL;
}
///
void getFileLine(uint &line, uint &col, std::string &file)
{
Tokenizer.getFileLine(StartToken, line, col, file);
}
///
CFileNode* getFileNode();
CDbNode* getDbNode();
CFileNode* FileNode;
CDbNode* DbNode;
CCppOutput& hOutput();
CCppOutput& cppOutput();
CCppOutput& inlineOutput();
CTypeNode* getTypeNode(const std::string &name, bool genError = true);
CEnumNode* getEnumNode(const std::string &name, bool genError = true);
CDimensionNode* getDimensionNode(const std::string &name, bool genError = true);
CIndexNode* getIndexNode(const std::string &name, bool genError = true);
CClassNode* getClassNode(const std::string &name, bool genError = true);
CTemplatizerEnv* Env;
template<typename T>
void setEnv(const std::string& var, const T& val)
{
nlassert(Env != NULL);
Env->set(var, val);
}
void define(const std::string& var)
{
nlassert(Env != NULL);
Env->set(var, 1);
}
void define(bool isdef, const std::string& var)
{
nlassert(Env != NULL);
if (isdef)
Env->set(var, 1);
}
};
//
//
//
class CDbNode : public CParseNode
{
public:
CDbNode() : DbXml(false), DbSummary(false) {}
//
bool addTypeNode(const std::string &name, const std::string &displayName = std::string(""), const std::string &defaultValue = std::string(""));
//
std::vector<CFileNode*> FileNodes;
std::vector<CTypeNode*> TypeNodes;
std::vector<CClassNode*> ClassNodes;
std::vector<CLogMsgNode*> LogNodes;
CCppOutput DbXml;
CCppOutput DbHpp;
CCppOutput DbHppInline;
CCppOutput DbCpp;
CCppOutput DbSummary;
std::string MainFile;
std::string Pch;
std::vector<std::string> xmlDescription;
CFunctionGenerator initDb;
CFunctionGenerator readyDb;
CFunctionGenerator updateDb;
CFunctionGenerator releaseDb;
CFunctionGenerator logChatDb;
CFunctionGenerator logTellDb;
std::set<std::string> Implemented;
///
virtual bool prolog();
virtual bool epilog();
void pass1();
void pass2();
void pass3();
void pass4();
void buildClassOrder(std::vector<CClassNode*>& classesOrder, std::vector<CFileNode*>& filesOrder);
void generateClassesDeclaration();
void generateIncludes(std::vector<CFileNode*>& filesOrder);
void generateClassesContent(std::vector<CClassNode*>& classesOrder);
void generateLogContent();
std::string getDbFile() { return MainFile.empty() ? Name : MainFile; }
// get file path from this file
std::string getFileNoExtPath(const std::string& file);
};
//
//
//
class CIncludeNode;
class CFileNode : public CParseNode
{
public:
CFileNode() : SeparatedFlag(false), IncludeStandard(false), IncludePDSLib(false), IncludeDbFile(false), Generate(true) { }
std::string IncludeAs;
bool SeparatedFlag;
CCppOutput Hpp;
CCppOutput HppInline;
CCppOutput Cpp;
bool IncludeStandard;
bool IncludePDSLib;
bool IncludeDbFile;
std::vector<CIncludeNode*> IncludeNodes;
bool Generate;
std::set<CFileNode*> Dependencies;
void checkDependencies(std::set<CFileNode*> &beingChecked,
std::set<CFileNode*> &checkedFiles,
std::vector<CFileNode*> &filesOrder);
///
virtual bool prolog();
virtual bool epilog();
//
virtual bool generateProlog();
virtual bool generateEpilog();
//
void writeFile();
// get file path from this file
std::string getFileNoExtPath(const std::string& file);
};
//
//
//
class CIncludeNode : public CParseNode
{
public:
///
virtual bool prolog();
};
//
//
//
class CUsePchNode : public CParseNode
{
public:
///
virtual bool prolog();
};
//
//
//
class CCppCodeNode : public CParseNode
{
public:
std::string RawCode;
///
virtual bool prolog();
};
//
//
//
class CTypeNode : public CParseNode
{
public:
CTypeNode() :
ToCppType(NULL),
ToStorageType(NULL),
ExternFlag(false),
InternFlag(false),
Id(0)
{
}
std::string CppType;
std::string StorageType;
std::string DisplayName;
CParseNode* ToCppType;
CParseNode* ToStorageType;
bool ExternFlag;
bool InternFlag;
std::string Temp;
uint32 Size;
uint Id;
std::string DefaultValue;
virtual bool isEnum() { return false; }
virtual bool isDimension() { return false; }
virtual bool isIndex() { return false; }
virtual std::string checkCode(const std::string& var) { return ""; }
std::string storageToCpp()
{
if (ToCppType != NULL)
return "__pds_cnv_type_"+NLMISC::toString(Id)+"_s2c";
else
return "("+CppType+")";
}
std::string cppToStorage()
{
if (ToStorageType != NULL)
return "__pds_cnv_type_"+NLMISC::toString(Id)+"_c2s";
else
return "("+StorageType+")";
}
std::string castToCpp(const std::string& var)
{
if (CppType != StorageType)
{
return storageToCpp()+"("+var+")";
}
else
{
return var;
}
}
std::string castToStorage(const std::string& var)
{
if (CppType != StorageType)
{
return cppToStorage()+"("+var+")";
}
else
{
return var;
}
}
std::string getCppType()
{
if (CppType == "CEntityId")
return "NLMISC::CEntityId";
else if (CppType == "CSheetId")
return "NLMISC::CSheetId";
else
return CppType;
}
std::string castToPDS(const std::string& var)
{
if (isEnum())
{
return "(uint32)"+var;
}
else if (ExternFlag)
{
return "("+StorageType+")"+var;
}
else
{
//return "("+getName()+")";
return castToStorage(var);
}
}
std::string castFromUser(const std::string& var)
{
return "("+getName()+")"+var;
}
virtual std::string getName() { return DisplayName.empty() ? Name : DisplayName; }
std::string getDefaultValue()
{
if (DefaultValue.empty())
{
if (CppType == "CEntityId") return "NLMISC::CEntityId::Unknown";
if (CppType == "CSheetId") return "NLMISC::CSheetId::Unknown";
return castFromUser("0");
}
else
{
return DefaultValue;
}
}
virtual std::string getPrintfFmt()
{
if (CppType == "CEntityId" || CppType == "CSheetId")
return "%s";
if (CppType == "double" || CppType == "float")
return "%f";
if (CppType == "sint64")
return "%\"NL_I64\"d";
if (CppType == "uint64")
return "%\"NL_I64\"u";
if (CppType == "sint32" || CppType == "sint16" || CppType == "sint8")
return "%d";
if (CppType == "uint32" || CppType == "uint16" || CppType == "uint8")
return "%u";
if (CppType == "char" || CppType == "ucchar")
return "%c";
if (CppType == "bool")
return "%s";
return "%d";
}
virtual std::string getPrintfVal(const std::string& var)
{
if (CppType == "CEntityId" || CppType == "CSheetId")
return var+".toString()";
if (CppType == "double" || CppType == "float" ||
CppType == "sint64" || CppType == "uint64" ||
CppType == "sint32" || CppType == "sint16" || CppType == "sint8" ||
CppType == "uint32" || CppType == "uint16" || CppType == "uint8" ||
CppType == "char" || CppType == "ucchar")
return var;
if (CppType == "bool")
return "("+var+" ? \"true\" : \"false\")";
return "(uint32)"+var;
}
///
virtual bool prolog();
///
virtual bool generateContent();
virtual void generateApplyCode(CClassGenerator::SMethodId& method, const std::string& token, const std::string& value)
{
method.add("__pdr.pop("+token+", "+value+");");
}
virtual void generateStoreCode(CClassGenerator::SMethodId& method, const std::string& token, const std::string& value)
{
method.add("__pdr.push("+token+", "+value+");");
}
};
//
//
//
class CDeclarationNode;
class CCallContext;
enum TDeclarationType
{
SimpleType,
SimpleClass,
ForwardRef,
BackRef,
ArrayType,
ArrayClass,
ArrayRef,
Set
};
struct CColumn
{
std::string Name;
uint32 ByteSize;
TDeclarationType Type;
std::string TypeStr;
uint TypeId;
};
class CClassNode : public CParseNode
{
public:
CClassNode() :
IsBackReferenced(false),
HasInheritance(false),
IsInSet(false),
IsInArray(false),
IsInArrayRef(false),
MappedFlag(false),
DerivatedFlag(false),
HasParent(false),
ParentIsHidden(false),
ForceReference(false),
PDSMapped(false),
MapClass(NULL),
Columns(-1),
Id(0),
HasRowAccess(false),
HasTableAccess(false),
indexUsedInInit(false),
indexUsedInDestroy(false),
indexUsedInFetch(false),
tableAndRowIndicesUsedInFetch(false),
indexUsedInRegister(false),
indexUsedInUnregister(false),
indexUsedInNotifyInit(false),
indexUsedInNotifyRelease(false)
{
}
std::string Inherited;
std::string ClassKey;
std::string Implements;
std::set<CClassNode*> Dependencies;
std::vector<std::string> ChildrenClasses;
bool IsBackReferenced;
bool HasInheritance;
bool IsInSet;
bool IsInArray;
bool IsInArrayRef;
bool MappedFlag;
bool DerivatedFlag;
bool HasParent;
bool ParentIsHidden;
bool ForceReference;
std::string ParentClass;
std::string Reserve;
bool PDSMapped;
CClassNode *MapClass;
std::vector<CDeclarationNode*> Init;
std::string InitProto;
std::string InitCallArgs;
sint Columns;
uint Id;
std::vector<CDeclarationNode*> Attributes;
bool HasRowAccess;
bool HasTableAccess;
std::set<std::string> Friends;
std::set<std::string> ForwardFriends;
std::set<CClassNode*> Legacy;
///
virtual bool prolog();
virtual bool epilog();
CDeclarationNode* getDeclarationNode(const std::string &name);
CDeclarationNode* getKey();
CDeclarationNode* getClassKey();
CDeclarationNode* getDeclaration(const std::string& name);
bool useEntityId();
void checkClassReferences();
void fillAttributes();
void fillRefs();
void computeFriends();
void checkDependencies(std::set<CClassNode*> &beingChecked,
std::set<CClassNode*> &checkedClasses,
std::vector<CClassNode*> &classesOrder);
void buildInit();
void computeAttributesColumns();
std::string getId() { return (HasInheritance ? NLMISC::toString("__BaseTable") : NLMISC::toString(Id)); }
std::string getUserCode(const std::string& name);
//
CClassGenerator Gen;
CClassGenerator::SMethodId InitId;
CClassGenerator::SMethodId DestroyId;
CClassGenerator::SMethodId FetchId;
CClassGenerator::SMethodId RegisterId;
CClassGenerator::SMethodId RegisterAttributesId;
CClassGenerator::SMethodId UnregisterId;
CClassGenerator::SMethodId UnregisterAttributesId;
CClassGenerator::SMethodId SetParentId;
CClassGenerator::SMethodId SetUnnotifiedParentId;
CClassGenerator::SMethodId NotifyInitId;
CClassGenerator::SMethodId NotifyReleaseId;
CClassGenerator::SMethodId UserInitId;
CClassGenerator::SMethodId UserReleaseId;
//
CClassGenerator::SMethodId ClearId;
CClassGenerator::SMethodId StoreId;
CClassGenerator::SMethodId ApplyId;
bool indexUsedInInit;
bool indexUsedInDestroy;
bool indexUsedInFetch;
bool tableAndRowIndicesUsedInFetch;
bool indexUsedInRegister;
bool indexUsedInUnregister;
bool indexUsedInNotifyInit;
bool indexUsedInNotifyRelease;
bool generateContent();
void generateContentInCall(CCallContext *context);
};
class CDeclarationNode : public CParseNode
{
public:
CDeclarationNode() :
InitFillFlag(false),
WriteTriggerFlag(false),
ParentFlag(false),
HiddenFlag(false),
MirroredFlag(false),
ArrayFlag(false),
SetFlag(false),
IsRef(false),
IsType(false),
IsKey(false),
Id(0),
Column(-1),
Columns(-1)
{
}
bool InitFillFlag;
bool WriteTriggerFlag;
bool ParentFlag;
bool HiddenFlag;
bool MirroredFlag;
std::string ParentClass;
std::string ParentField;
std::string Type;
bool ArrayFlag;
std::string ArrayIndex;
bool SetFlag;
std::string ForwardRefAttribute;
bool IsRef;
bool IsType;
bool IsKey;
std::string DefaultValue;
struct CUserCode
{
std::string Event;
std::string CodeSpecializer;
std::string UserCode;
};
std::vector<CUserCode> UserCodes;
std::string getUserCode(const std::string &name, const std::string &specialize = std::string(""))
{
uint i;
// first look for a specialized code
for (i=0; i<UserCodes.size(); ++i)
if (UserCodes[i].Event == name && UserCodes[i].CodeSpecializer == specialize)
return UserCodes[i].UserCode;
// then look for a default code
for (i=0; i<UserCodes.size(); ++i)
if (UserCodes[i].Event == name && UserCodes[i].CodeSpecializer == "")
return UserCodes[i].UserCode;
return "";
}
TDeclarationType DeclarationType;
std::string XmlNode;
std::vector<CColumn> ColumnList;
uint Id;
sint Column;
sint Columns;
CClassNode* ClassNode;
CClassNode* getParentClass() { return dynamic_cast<CClassNode*>(Parent); }
///
virtual bool prolog();
virtual bool epilog();
//
std::string getFunc() const { return lcFirst(getFunctionPrefix+Name); }
std::string setFunc() const { return lcFirst(setFunctionPrefix+Name); }
std::string newFunc() const { return lcFirst(newFunction+Name); }
std::string deleteFunc() const { return lcFirst(deleteFunction+Name); }
std::string unlinkFunc() const { return lcFirst(unlinkFunction+Name); }
std::string cppName() const { return "_"+Name; }
std::string tokenName() const { return "__Tok"+Name; }
//
std::string displayPrintfPrefix();
std::string displayCppCode(std::string replVar = "");
std::string toUint64(std::string replVar = "");
//
void generateContent(CCallContext *context = NULL);
void generateTypeContent(CCallContext *context = NULL);
void generateClassContent(CCallContext *context = NULL);
void generateBackRefContent();
void generateForwardRefContent();
void generateArrayTypeContent(CCallContext *context = NULL);
void generateArrayClassContent(CCallContext *context = NULL);
void generateArrayRefContent(CCallContext *context = NULL);
void generateSetContent(CCallContext *context = NULL);
void generateArrayApplyCode();
void generateArrayStoreCode();
void generateArrayEndCode();
void generateClassPtrApplyCode(const std::string& value);
void generateClassPtrStoreCode(const std::string& value);
std::string getAccessorName(CCallContext *context, const std::string& accessortype, const std::string& sep = "::");
};
//
//
//
class CIndexNode : public CTypeNode
{
public:
CIndexNode()
{
CppType = "uint32";
StorageType = "uint32";
}
virtual bool isIndex() { return true; }
virtual std::string getSizeName() { return Name+"Size"; }
virtual uint getSize() = 0;
virtual std::string getIndexName(uint32 value) const
{
return NLMISC::toString(value);
}
virtual std::string getToStringCode(const std::string& var) const
{
return "NLMISC::toString("+var+")";
}
virtual std::string getFromStringCode(const std::string& var) const
{
return "atoi("+var+")";
}
virtual std::string checkCode(const std::string& var) { return "nlassert("+var+"<"+getSizeName()+");"; }
};
//
//
//
class CEnumNode : public CIndexNode
{
public:
CEnumNode() :
CurrentValue(0),
MinValue(0),
MaxValue(0)
{
}
uint32 CurrentValue;
uint32 MinValue;
uint32 MaxValue;
std::vector<std::pair<std::string, uint32> > Values;
std::string EndRange;
virtual bool isEnum() { return true; }
virtual std::string getName()
{
std::string trunc = Name.substr(1);
return "C"+trunc+"::"+(DisplayName.empty() ? Name : DisplayName);
}
virtual uint getSize() { return MaxValue-MinValue; }
bool prolog();
bool epilog();
///
virtual bool generateContent();
std::string getIndexName(uint32 value) const
{
std::string result;
uint i;
for (i=0; i<Values.size(); ++i)
if (Values[i].second == value)
result = Values[i].first;
return result;
}
std::string getUnscopedUseSize() const
{
return "___"+Name+"_useSize";
}
std::string getUnknownValue() const
{
return "Unknown";
}
std::string getUseSize() const
{
std::string trunc = Name.substr(1);
return "C"+trunc+"::"+getUnscopedUseSize();
}
std::string getSizeName()
{
std::string trunc = Name.substr(1);
return "C"+trunc+"::"+getUnscopedUseSize();
}
virtual std::string getToStringCode(const std::string& var) const
{
std::string trunc = Name.substr(1);
return "C"+trunc+"::toString("+var+")";
}
virtual std::string getFromStringCode(const std::string& var) const
{
std::string trunc = Name.substr(1);
return "C"+trunc+"::fromString("+var+")";
}
virtual void generateApplyCode(CClassGenerator::SMethodId& method, const std::string& token, const std::string& value)
{
method.add("{");
method.add("std::string\tvaluename;");
method.add("__pdr.pop("+token+", valuename);");
method.add(value+" = "+getFromStringCode("valuename")+";");
method.add("}");
}
virtual void generateStoreCode(CClassGenerator::SMethodId& method, const std::string& token, const std::string& value)
{
method.add("{");
method.add("std::string\tvaluename = "+getToStringCode(value)+";");
method.add("__pdr.push("+token+", valuename);");
method.add("}");
}
};
class CEnumSimpleValueNode : public CEnumNode
{
public:
std::vector<std::string> Names;
bool prolog();
bool epilog();
};
class CEnumRangeNode : public CEnumNode
{
public:
bool prolog();
bool epilog();
};
//
//
//
class CDimensionNode : public CIndexNode
{
public:
public:
CDimensionNode()
{
}
virtual bool isDimension() { return true; }
std::string getSizeName() { return Name+"Size"; }
bool prolog();
bool epilog();
sint Dimension;
virtual uint getSize() { return Dimension; }
///
virtual bool generateContent();
};
//
//
//
class CLogMsgNode : public CParseNode
{
public:
CLogMsgNode() : Context(false)
{
}
bool prolog();
bool epilog()
{
return true;
}
std::vector<std::pair<std::string, std::string> > Params;
std::vector<std::string> Logs;
bool Context;
uint Id;
void generateContent();
};
class CExtLogTypeNode : public CParseNode
{
public:
std::string ExtLogType;
};
//
//
//
class CCallContext
{
public:
std::vector<CDeclarationNode*> Context;
std::string RootTable;
std::string RootRow;
uint Column;
CCallContext(CDeclarationNode* decl = NULL)
{
if (decl != NULL)
Context.push_back(decl);
}
bool hasRootEntityIdKey()
{
CDeclarationNode* k = getRootCaller()->getClassKey();
if (k != NULL)
{
return (getRootCaller()->getTypeNode(getRootCaller()->getKey()->Type)->CppType == "CEntityId");
}
return false;
}
/**
* Generates the name of the pointed variable
* For instance: PhysicalScoresBase, where PhysicalScores is an array and Base is an attribute in this array
* Actually concats all fields names
*/
std::string getCallString()
{
uint i;
std::string res;
for (i=0; i<Context.size(); ++i)
res += Context[i]->Name;
return res;
}
CClassNode* getRootCaller()
{
return (CClassNode*)Context[0]->Parent;
}
CDeclarationNode* getRootDeclaration()
{
return Context[0];
}
/**
* Generates the access prototype argument list
* Actually only generates indexes for arrays
*/
std::string getDebugCallStringFmt()
{
uint i, idx=0;
std::string res;
for (i=0; i<Context.size(); ++i)
{
CDeclarationNode* decl = Context[i];
if (decl->DeclarationType == ArrayClass || decl->DeclarationType == ArrayType)
{
if (!res.empty())
res += ", ";
CTypeNode* tnd = decl->getTypeNode(decl->ArrayIndex);
res += indexVariable+NLMISC::toString(idx++)+"="+tnd->getPrintfFmt();
}
}
return res;
}
/**
* Generates the access prototype argument list
* Actually only generates indexes for arrays
*/
std::string getDebugCallStringVal()
{
uint i, idx=0;
std::string res;
for (i=0; i<Context.size(); ++i)
{
CDeclarationNode* decl = Context[i];
if (decl->DeclarationType == ArrayClass || decl->DeclarationType == ArrayType)
{
if (!res.empty())
res += ", ";
CTypeNode* tnd = decl->getTypeNode(decl->ArrayIndex);
res += tnd->getPrintfVal(indexVariable+NLMISC::toString(idx++));
}
}
return res;
}
/**
* Generates the access prototype argument list
* Actually only generates indexes for arrays
*/
std::string getCallArgList()
{
std::string res;
uint i, idx=0;
for (i=0; i<Context.size(); ++i)
{
CDeclarationNode* decl = Context[i];
if (decl->DeclarationType == ArrayClass || decl->DeclarationType == ArrayType)
{
if (!res.empty())
res += ", ";
CTypeNode* tnd = decl->getTypeNode(decl->ArrayIndex);
res += tnd->getName()+ " "+indexVariable+NLMISC::toString(idx++);
}
}
return res;
}
/**
* Generates the c++ path to the variable
* For instance: _PhysicalScores[__i0].Base, where PhysicalScores is an array and Base is an attribute in this array
*/
std::string getCallPath()
{
std::string res;
uint i, idx=0;
for (i=0; i<Context.size(); ++i)
{
CDeclarationNode* decl = Context[i];
if (!res.empty())
res += ".";
res += decl->cppName();
if (decl->DeclarationType == ArrayClass || decl->DeclarationType == ArrayType)
{
res += "["+indexVariable+NLMISC::toString(idx++)+"]";
}
}
return res;
}
/**
* Generates the c++ path to the variable
* For instance: _PhysicalScores[__i0].Base, where PhysicalScores is an array and Base is an attribute in this array
*/
std::string getUserCodeContext()
{
std::string res;
uint i;
if (Context.empty())
return res;
res = Context[0]->getParentClass()->Name;
for (i=0; i<Context.size(); ++i)
res += "."+Context[i]->Name;
return res;
}
/**
* Generates check code for all types accessors
*/
std::vector<std::string> getCheckCode()
{
std::vector<std::string> res;
uint i, idx=0;
for (i=0; i<Context.size(); ++i)
{
CDeclarationNode* decl = Context[i];
if (decl->DeclarationType == ArrayType || decl->DeclarationType == ArrayRef || decl->DeclarationType == ArrayClass)
{
CIndexNode* ind = decl->getIndexNode(decl->ArrayIndex);
std::string code = ind->checkCode(indexVariable+NLMISC::toString(idx++));
if (!code.empty())
res.push_back(code);
}
}
return res;
}
/**
* Get current context index
*/
uint getContextIndex()
{
uint i, idx=0;
for (i=0; i<Context.size(); ++i)
{
CDeclarationNode* decl = Context[i];
if (decl->DeclarationType == ArrayClass || decl->DeclarationType == ArrayType)
idx++;
}
return idx-1;
}
CCallContext getSubContext(CDeclarationNode* decl)
{
CCallContext ctx = *this;
ctx.Context.push_back(decl);
return ctx;
}
std::string getColumn()
{
std::string res;
uint i, idx=0;
for (i=0; i<Context.size(); ++i)
{
CDeclarationNode* decl = Context[i];
if (decl->Column != 0)
{
if (!res.empty())
res += "+";
res += NLMISC::toString(decl->Column);
}
if (decl->DeclarationType == ArrayType || decl->DeclarationType == ArrayRef)
{
if (!res.empty())
res += "+";
res += indexVariable+NLMISC::toString(idx++);
}
else if (decl->DeclarationType == ArrayClass)
{
if (!res.empty())
res += "+";
CClassNode* sub = decl->getClassNode(decl->Type);
res += indexVariable+NLMISC::toString(idx++)+"*"+NLMISC::toString(sub->Columns);
}
}
if (res.empty())
res = "0";
return res;
}
};
//
// INLINES
//
inline CFileNode* CParseNode::getFileNode()
{
if (FileNode != NULL)
return FileNode;
CParseNode* node = this;
CFileNode* fnode = NULL;
while (node != NULL && (fnode = dynamic_cast<CFileNode*>(node)) == NULL)
node = node->Parent;
if (fnode == NULL)
error("Can't find file node", "internal");
FileNode = fnode;
return fnode;
}
inline CDbNode* CParseNode::getDbNode()
{
if (DbNode != NULL)
return DbNode;
CParseNode* node = this;
CDbNode* fnode = NULL;
while (node != NULL && (fnode = dynamic_cast<CDbNode*>(node)) == NULL)
node = node->Parent;
if (fnode == NULL)
error("Can't find db node", "internal");
DbNode = fnode;
return fnode;
}
inline CCppOutput& CParseNode::hOutput()
{
CFileNode *fnode = getFileNode();
return fnode->Hpp;
}
inline CCppOutput& CParseNode::cppOutput()
{
CFileNode *fnode = getFileNode();
return fnode->Cpp;
}
inline CCppOutput& CParseNode::inlineOutput()
{
CFileNode *fnode = getFileNode();
return fnode->HppInline;
}
inline CTypeNode *CParseNode::getTypeNode(const std::string &name, bool genError)
{
CDbNode* db = getDbNode();
uint i;
for (i=0; i<db->TypeNodes.size(); ++i)
if (db->TypeNodes[i]->Name == name)
return db->TypeNodes[i];
if (genError)
error("Can't find type '"+name+"'");
return NULL;
}
inline CEnumNode *CParseNode::getEnumNode(const std::string &name, bool genError)
{
CEnumNode* node = dynamic_cast<CEnumNode*>(getTypeNode(name, genError));
if (node == NULL && genError)
error("Can't find enum '"+name+"'");
return node;
}
inline CDimensionNode *CParseNode::getDimensionNode(const std::string &name, bool genError)
{
CDimensionNode* node = dynamic_cast<CDimensionNode*>(getTypeNode(name, genError));
if (node == NULL && genError)
error("Can't find dimension '"+name+"'");
return node;
}
inline CIndexNode *CParseNode::getIndexNode(const std::string &name, bool genError)
{
CIndexNode* node = dynamic_cast<CIndexNode*>(getTypeNode(name, genError));
if (node == NULL && genError)
error("Can't find index type '"+name+"' (neither enum nor dimension)");
return node;
}
inline CClassNode *CParseNode::getClassNode(const std::string &name, bool genError)
{
CDbNode* db = getDbNode();
uint i;
for (i=0; i<db->ClassNodes.size(); ++i)
if (db->ClassNodes[i]->Name == name)
return db->ClassNodes[i];
if (genError)
error("Can't find class '"+name+"'");
return NULL;
}
inline bool CDbNode::addTypeNode(const std::string &name, const std::string &displayName, const std::string &defaultValue)
{
CTypeNode *node = new CTypeNode();
node->Name = name;
node->DisplayName = displayName;
node->CppType = name;
node->StorageType = name;
node->ToCppType = NULL;
node->ToStorageType = NULL;
node->DefaultValue = defaultValue;
node->ExternFlag = false;
node->InternFlag = true;
node->Parent = this;
Nodes.insert(Nodes.begin(), node);
return true;
}
inline CDeclarationNode* CClassNode::getDeclarationNode(const std::string &name)
{
CDeclarationNode *node;
if ((node = dynamic_cast<CDeclarationNode*>(getNode(name))) == NULL)
error("declaration '"+name+"' not found");
return node;
}
inline bool CClassNode::useEntityId()
{
//return !ClassKey.empty() && getTypeNode(getKey()->Type)->CppType == "CEntityId";
CDeclarationNode* k = getClassKey();
return k!=NULL && getTypeNode(k->Type)->CppType == "CEntityId";
}
inline CDeclarationNode* CClassNode::getClassKey()
{
if (ClassKey.empty())
{
if (Inherited.empty())
return NULL;
CClassNode* p = getClassNode(Inherited);
return p->getClassKey();
}
else
{
return getKey();
}
}
inline CDeclarationNode* CClassNode::getKey()
{
CDeclarationNode* key = NULL;
CClassNode* classNode = this;
while (classNode != NULL)
{
key = dynamic_cast<CDeclarationNode*>(classNode->getNode(classNode->ClassKey));
if (key != NULL)
return key;
classNode = getClassNode(Inherited, false);
}
error("key declaration '"+ClassKey+"' not found");
return NULL;
//return getDeclarationNode(ClassKey);
}
inline CDeclarationNode* CClassNode::getDeclaration(const std::string& name)
{
CDeclarationNode* decl = NULL;
CClassNode* classNode = this;
while (classNode != NULL)
{
decl = dynamic_cast<CDeclarationNode*>(classNode->getNode(name));
if (decl != NULL)
return decl;
classNode = getClassNode(classNode->Inherited, false);
}
error("declaration '"+name+"' not found");
return NULL;
}
#endif