Some random CBotProgram and CBotToken refactoring
parent
9b4a6e0131
commit
fbdc071659
|
@ -623,7 +623,7 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars
|
||||||
{
|
{
|
||||||
if ( !pt->m_MasterClass.empty() )
|
if ( !pt->m_MasterClass.empty() )
|
||||||
{
|
{
|
||||||
CBotVar* pInstance = m_pProg->m_pInstance;
|
CBotVar* pInstance = m_pProg->m_thisVar;
|
||||||
// make "this" known
|
// make "this" known
|
||||||
CBotVar* pThis ;
|
CBotVar* pThis ;
|
||||||
if ( pInstance == nullptr )
|
if ( pInstance == nullptr )
|
||||||
|
@ -702,7 +702,7 @@ void CBotFunction::RestoreCall(long& nIdent, const std::string& name, CBotVar**
|
||||||
{
|
{
|
||||||
if ( !pt->m_MasterClass.empty() )
|
if ( !pt->m_MasterClass.empty() )
|
||||||
{
|
{
|
||||||
// CBotVar* pInstance = m_pProg->m_pInstance;
|
// CBotVar* pInstance = m_pProg->m_thisVar;
|
||||||
// make "this" known
|
// make "this" known
|
||||||
CBotVar* pThis = pStk1->FindVar("this");
|
CBotVar* pThis = pStk1->FindVar("this");
|
||||||
pThis->SetInit(CBotVar::InitType::IS_POINTER);
|
pThis->SetInit(CBotVar::InitType::IS_POINTER);
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
#include "CBot/CBotKeywordStrings.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
//! \brief Keeps the string corresponding to keyword ID
|
|
||||||
// Map is filled with id-string pars that are needed for CBot language parsing
|
|
||||||
static const std::map<TokenId, const std::string> s_keywordString = {
|
|
||||||
{ID_IF, "if"},
|
|
||||||
{ID_ELSE, "else"},
|
|
||||||
{ID_WHILE, "while"},
|
|
||||||
{ID_DO, "do"},
|
|
||||||
{ID_FOR, "for"},
|
|
||||||
{ID_BREAK, "break"},
|
|
||||||
{ID_CONTINUE, "continue"},
|
|
||||||
{ID_SWITCH, "switch"},
|
|
||||||
{ID_CASE, "case"},
|
|
||||||
{ID_DEFAULT, "default"},
|
|
||||||
{ID_TRY, "try"},
|
|
||||||
{ID_THROW, "throw"},
|
|
||||||
{ID_CATCH, "catch"},
|
|
||||||
{ID_FINALLY, "finally"},
|
|
||||||
{ID_TXT_AND, "and"},
|
|
||||||
{ID_TXT_OR, "or"},
|
|
||||||
{ID_TXT_NOT, "not"},
|
|
||||||
{ID_RETURN, "return"},
|
|
||||||
{ID_CLASS, "class"},
|
|
||||||
{ID_EXTENDS, "extends"},
|
|
||||||
{ID_SYNCHO, "synchronized"},
|
|
||||||
{ID_NEW, "new"},
|
|
||||||
{ID_PUBLIC, "public"},
|
|
||||||
{ID_EXTERN, "extern"},
|
|
||||||
{ID_STATIC, "static"},
|
|
||||||
{ID_PROTECTED, "protected"},
|
|
||||||
{ID_PRIVATE, "private"},
|
|
||||||
{ID_INT, "int"},
|
|
||||||
{ID_FLOAT, "float"},
|
|
||||||
{ID_BOOLEAN, "boolean"},
|
|
||||||
{ID_STRING, "string"},
|
|
||||||
{ID_VOID, "void"},
|
|
||||||
{ID_BOOL, "bool"},
|
|
||||||
{ID_TRUE, "true"},
|
|
||||||
{ID_FALSE, "false"},
|
|
||||||
{ID_NULL, "null"},
|
|
||||||
{ID_NAN, "nan"},
|
|
||||||
{ID_OPENPAR, "("},
|
|
||||||
{ID_CLOSEPAR, ")"},
|
|
||||||
{ID_OPBLK, "{"},
|
|
||||||
{ID_CLBLK, "}"},
|
|
||||||
{ID_SEP, ";"},
|
|
||||||
{ID_COMMA, ","},
|
|
||||||
{ID_DOTS, ":"},
|
|
||||||
{ID_DOT, "."},
|
|
||||||
{ID_OPBRK, "["},
|
|
||||||
{ID_CLBRK, "]"},
|
|
||||||
{ID_DBLDOTS, "::"},
|
|
||||||
{ID_LOGIC, "?"},
|
|
||||||
{ID_ADD, "+"},
|
|
||||||
{ID_SUB, "-"},
|
|
||||||
{ID_MUL, "*"},
|
|
||||||
{ID_DIV, "/"},
|
|
||||||
{ID_ASS, "="},
|
|
||||||
{ID_ASSADD, "+="},
|
|
||||||
{ID_ASSSUB, "-="},
|
|
||||||
{ID_ASSMUL, "*="},
|
|
||||||
{ID_ASSDIV, "/="},
|
|
||||||
{ID_ASSOR, "|="},
|
|
||||||
{ID_ASSAND, "&="},
|
|
||||||
{ID_ASSXOR, "^="},
|
|
||||||
{ID_ASSSL, "<<="},
|
|
||||||
{ID_ASSSR, ">>>="},
|
|
||||||
{ID_ASSASR, ">>="},
|
|
||||||
{ID_SL, "<<"},
|
|
||||||
{ID_SR, ">>"},
|
|
||||||
{ID_ASR, ">>"},
|
|
||||||
{ID_INC, "++"},
|
|
||||||
{ID_DEC, "--"},
|
|
||||||
{ID_LO, "<"},
|
|
||||||
{ID_HI, ">"},
|
|
||||||
{ID_LS, "<="},
|
|
||||||
{ID_HS, ">="},
|
|
||||||
{ID_EQ, "=="},
|
|
||||||
{ID_NE, "!="},
|
|
||||||
{ID_AND, "&"},
|
|
||||||
{ID_XOR, "^"},
|
|
||||||
{ID_OR, "|"},
|
|
||||||
{ID_LOG_AND, "&&"},
|
|
||||||
{ID_LOG_OR, "||"},
|
|
||||||
{ID_LOG_NOT, "!"},
|
|
||||||
{ID_NOT, "~"},
|
|
||||||
{ID_MODULO, "%"},
|
|
||||||
{ID_POWER, "**"},
|
|
||||||
{ID_ASSMODULO, "%="},
|
|
||||||
{TX_UNDEF, "undefined"},
|
|
||||||
{TX_NAN, "not a number"}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const std::string emptyString = "";
|
|
||||||
const std::string& LoadString(TokenId id)
|
|
||||||
{
|
|
||||||
if (s_keywordString.find(id) != s_keywordString.end())
|
|
||||||
{
|
|
||||||
return s_keywordString.at(id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return emptyString;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CBotEnums.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief LoadString Maps given ID to its string equivalent.
|
|
||||||
* \param id Provided identifier.
|
|
||||||
* \return String if found, else NullString.
|
|
||||||
*/
|
|
||||||
const std::string& LoadString(TokenId id);
|
|
|
@ -17,7 +17,6 @@
|
||||||
* along with this program. If not, see http://gnu.org/licenses
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Modules inlcude
|
|
||||||
#include "CBot/CBotVar/CBotVar.h"
|
#include "CBot/CBotVar/CBotVar.h"
|
||||||
|
|
||||||
#include "CBot/CBotCall.h"
|
#include "CBot/CBotCall.h"
|
||||||
|
@ -29,51 +28,26 @@
|
||||||
|
|
||||||
#include "CBot/CBotInstr/CBotFunction.h"
|
#include "CBot/CBotInstr/CBotFunction.h"
|
||||||
|
|
||||||
#include "CBotKeywordStrings.h"
|
|
||||||
|
|
||||||
#include "CBot/stdlib/stdlib.h"
|
#include "CBot/stdlib/stdlib.h"
|
||||||
|
|
||||||
// Local include
|
|
||||||
|
|
||||||
// Global include
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
CBotProgram::CBotProgram()
|
CBotProgram::CBotProgram()
|
||||||
{
|
{
|
||||||
m_Prog = nullptr;
|
|
||||||
m_pRun = nullptr;
|
|
||||||
m_pClass = nullptr;
|
|
||||||
m_pStack = nullptr;
|
|
||||||
m_pInstance = nullptr;
|
|
||||||
|
|
||||||
m_ErrorCode = CBotNoErr;
|
|
||||||
m_Ident = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
CBotProgram::CBotProgram(CBotVar* thisVar)
|
||||||
CBotProgram::CBotProgram(CBotVar* pInstance)
|
: m_thisVar(thisVar)
|
||||||
{
|
{
|
||||||
m_Prog = nullptr;
|
|
||||||
m_pRun = nullptr;
|
|
||||||
m_pClass = nullptr;
|
|
||||||
m_pStack = nullptr;
|
|
||||||
m_pInstance = pInstance;
|
|
||||||
|
|
||||||
m_ErrorCode = CBotNoErr;
|
|
||||||
m_Ident = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
CBotProgram::~CBotProgram()
|
CBotProgram::~CBotProgram()
|
||||||
{
|
{
|
||||||
// delete m_pClass;
|
// delete m_classes;
|
||||||
m_pClass->Purge();
|
m_classes->Purge();
|
||||||
m_pClass = nullptr;
|
m_classes = nullptr;
|
||||||
|
|
||||||
CBotClass::FreeLock(this);
|
CBotClass::FreeLock(this);
|
||||||
|
|
||||||
delete m_Prog;
|
delete m_functions;
|
||||||
#if STACKMEM
|
#if STACKMEM
|
||||||
m_pStack->Delete();
|
m_pStack->Delete();
|
||||||
#else
|
#else
|
||||||
|
@ -81,33 +55,31 @@ CBotProgram::~CBotProgram()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
bool CBotProgram::Compile(const std::string& program, std::vector<std::string>& functions, void* pUser)
|
bool CBotProgram::Compile(const std::string& program, std::vector<std::string>& functions, void* pUser)
|
||||||
{
|
{
|
||||||
int error = 0;
|
// Cleanup the previously compiled program
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
// delete m_pClass;
|
// delete m_classes;
|
||||||
m_pClass->Purge(); // purge the old definitions of classes
|
m_classes->Purge(); // purge the old definitions of classes
|
||||||
// but without destroying the object
|
// but without destroying the object
|
||||||
m_pClass = nullptr;
|
m_classes = nullptr;
|
||||||
delete m_Prog; m_Prog= nullptr;
|
delete m_functions; m_functions = nullptr;
|
||||||
|
|
||||||
functions.clear();
|
functions.clear();
|
||||||
m_ErrorCode = CBotNoErr;
|
m_error = CBotNoErr;
|
||||||
|
|
||||||
// transforms the program in Tokens
|
// Step 1. Process the code into tokens
|
||||||
CBotToken* pBaseToken = CBotToken::CompileTokens(program, error);
|
CBotToken* pBaseToken = CBotToken::CompileTokens(program);
|
||||||
if ( pBaseToken == nullptr ) return false;
|
if ( pBaseToken == nullptr ) return false;
|
||||||
|
|
||||||
|
|
||||||
CBotCStack* pStack = new CBotCStack(nullptr);
|
CBotCStack* pStack = new CBotCStack(nullptr);
|
||||||
CBotToken* p = pBaseToken->GetNext(); // skips the first token (separator)
|
CBotToken* p = pBaseToken->GetNext(); // skips the first token (separator)
|
||||||
|
|
||||||
pStack->SetBotCall(this); // defined used routines
|
pStack->SetBotCall(this); // defined used routines
|
||||||
CBotCall::SetPUser(pUser);
|
CBotCall::SetPUser(pUser);
|
||||||
|
|
||||||
// first made a quick pass just to take the headers of routines and classes
|
// Step 2. Find all function and class definitions
|
||||||
while ( pStack->IsOk() && p != nullptr && p->GetType() != 0)
|
while ( pStack->IsOk() && p != nullptr && p->GetType() != 0)
|
||||||
{
|
{
|
||||||
if ( IsOfType(p, ID_SEP) ) continue; // semicolons lurking
|
if ( IsOfType(p, ID_SEP) ) continue; // semicolons lurking
|
||||||
|
@ -116,27 +88,28 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
|
||||||
( p->GetType() == ID_PUBLIC && p->GetNext()->GetType() == ID_CLASS ))
|
( p->GetType() == ID_PUBLIC && p->GetNext()->GetType() == ID_CLASS ))
|
||||||
{
|
{
|
||||||
CBotClass* nxt = CBotClass::Compile1(p, pStack);
|
CBotClass* nxt = CBotClass::Compile1(p, pStack);
|
||||||
if (m_pClass == nullptr ) m_pClass = nxt;
|
if (m_classes == nullptr ) m_classes = nxt;
|
||||||
else m_pClass->AddNext(nxt);
|
else m_classes->AddNext(nxt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CBotFunction* next = CBotFunction::Compile1(p, pStack, nullptr);
|
CBotFunction* next = CBotFunction::Compile1(p, pStack, nullptr);
|
||||||
if (m_Prog == nullptr ) m_Prog = next;
|
if (m_functions == nullptr ) m_functions = next;
|
||||||
else m_Prog->AddNext(next);
|
else m_functions->AddNext(next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( !pStack->IsOk() )
|
if ( !pStack->IsOk() )
|
||||||
{
|
{
|
||||||
m_ErrorCode = pStack->GetError(m_ErrorStart, m_ErrorEnd);
|
m_error = pStack->GetError(m_errorStart, m_errorEnd);
|
||||||
delete m_Prog;
|
delete m_functions;
|
||||||
m_Prog = nullptr;
|
m_functions = nullptr;
|
||||||
delete pBaseToken;
|
delete pBaseToken;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 3. Real compilation
|
||||||
// CBotFunction* temp = nullptr;
|
// CBotFunction* temp = nullptr;
|
||||||
CBotFunction* next = m_Prog; // rewind the list
|
CBotFunction* next = m_functions; // rewind the list
|
||||||
|
|
||||||
p = pBaseToken->GetNext(); // returns to the beginning
|
p = pBaseToken->GetNext(); // returns to the beginning
|
||||||
|
|
||||||
|
@ -165,15 +138,15 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
|
||||||
|
|
||||||
if ( !pStack->IsOk() )
|
if ( !pStack->IsOk() )
|
||||||
{
|
{
|
||||||
m_ErrorCode = pStack->GetError(m_ErrorStart, m_ErrorEnd);
|
m_error = pStack->GetError(m_errorStart, m_errorEnd);
|
||||||
delete m_Prog;
|
delete m_functions;
|
||||||
m_Prog = nullptr;
|
m_functions = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete pBaseToken;
|
delete pBaseToken;
|
||||||
delete pStack;
|
delete pStack;
|
||||||
|
|
||||||
return (m_Prog != nullptr);
|
return (m_functions != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -186,16 +159,16 @@ bool CBotProgram::Start(const std::string& name)
|
||||||
#endif
|
#endif
|
||||||
m_pStack = nullptr;
|
m_pStack = nullptr;
|
||||||
|
|
||||||
m_pRun = m_Prog;
|
m_entryPoint = m_functions;
|
||||||
while (m_pRun != nullptr)
|
while (m_entryPoint != nullptr)
|
||||||
{
|
{
|
||||||
if ( m_pRun->GetName() == name ) break;
|
if (m_entryPoint->GetName() == name ) break;
|
||||||
m_pRun = m_pRun->m_next;
|
m_entryPoint = m_entryPoint->m_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( m_pRun == nullptr )
|
if (m_entryPoint == nullptr )
|
||||||
{
|
{
|
||||||
m_ErrorCode = CBotErrNoRun;
|
m_error = CBotErrNoRun;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +186,7 @@ bool CBotProgram::Start(const std::string& name)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotProgram::GetPosition(const std::string& name, int& start, int& stop, CBotGet modestart, CBotGet modestop)
|
bool CBotProgram::GetPosition(const std::string& name, int& start, int& stop, CBotGet modestart, CBotGet modestop)
|
||||||
{
|
{
|
||||||
CBotFunction* p = m_Prog;
|
CBotFunction* p = m_functions;
|
||||||
while (p != nullptr)
|
while (p != nullptr)
|
||||||
{
|
{
|
||||||
if ( p->GetName() == name ) break;
|
if ( p->GetName() == name ) break;
|
||||||
|
@ -231,9 +204,9 @@ bool CBotProgram::Run(void* pUser, int timer)
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
if (m_pStack == nullptr || m_pRun == nullptr) goto error;
|
if (m_pStack == nullptr || m_entryPoint == nullptr) goto error;
|
||||||
|
|
||||||
m_ErrorCode = CBotNoErr;
|
m_error = CBotNoErr;
|
||||||
|
|
||||||
m_pStack->Reset(pUser); // empty the possible previous error, and resets the timer
|
m_pStack->Reset(pUser); // empty the possible previous error, and resets the timer
|
||||||
if ( timer >= 0 ) m_pStack->SetTimer(timer);
|
if ( timer >= 0 ) m_pStack->SetTimer(timer);
|
||||||
|
@ -246,16 +219,16 @@ bool CBotProgram::Run(void* pUser, int timer)
|
||||||
if ( ok )
|
if ( ok )
|
||||||
{
|
{
|
||||||
// returns to normal execution
|
// returns to normal execution
|
||||||
ok = m_pRun->Execute(nullptr, m_pStack, m_pInstance);
|
ok = m_entryPoint->Execute(nullptr, m_pStack, m_thisVar);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ok = m_pRun->Execute(nullptr, m_pStack, m_pInstance);
|
ok = m_pRun->Execute(nullptr, m_pStack, m_thisVar);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// completed on a mistake?
|
// completed on a mistake?
|
||||||
if (!ok && !m_pStack->IsOk())
|
if (!ok && !m_pStack->IsOk())
|
||||||
{
|
{
|
||||||
m_ErrorCode = m_pStack->GetError(m_ErrorStart, m_ErrorEnd);
|
m_error = m_pStack->GetError(m_errorStart, m_errorEnd);
|
||||||
#if STACKMEM
|
#if STACKMEM
|
||||||
m_pStack->Delete();
|
m_pStack->Delete();
|
||||||
#else
|
#else
|
||||||
|
@ -265,11 +238,11 @@ bool CBotProgram::Run(void* pUser, int timer)
|
||||||
return true; // execution is finished!
|
return true; // execution is finished!
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ok ) m_pRun = nullptr; // more function in execution
|
if ( ok ) m_entryPoint = nullptr; // more function in execution
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
m_ErrorCode = CBotErrNoRun;
|
m_error = CBotErrNoRun;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +255,7 @@ void CBotProgram::Stop()
|
||||||
delete m_pStack;
|
delete m_pStack;
|
||||||
#endif
|
#endif
|
||||||
m_pStack = nullptr;
|
m_pStack = nullptr;
|
||||||
m_pRun = nullptr;
|
m_entryPoint = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -314,36 +287,24 @@ void CBotProgram::SetTimer(int n)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotError CBotProgram::GetError()
|
CBotError CBotProgram::GetError()
|
||||||
{
|
{
|
||||||
return m_ErrorCode;
|
return m_error;
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
void CBotProgram::SetIdent(long n)
|
|
||||||
{
|
|
||||||
m_Ident = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
long CBotProgram::GetIdent()
|
|
||||||
{
|
|
||||||
return m_Ident;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotProgram::GetError(CBotError& code, int& start, int& end)
|
bool CBotProgram::GetError(CBotError& code, int& start, int& end)
|
||||||
{
|
{
|
||||||
code = m_ErrorCode;
|
code = m_error;
|
||||||
start = m_ErrorStart;
|
start = m_errorStart;
|
||||||
end = m_ErrorEnd;
|
end = m_errorEnd;
|
||||||
return code > 0;
|
return code > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotProgram::GetError(CBotError& code, int& start, int& end, CBotProgram*& pProg)
|
bool CBotProgram::GetError(CBotError& code, int& start, int& end, CBotProgram*& pProg)
|
||||||
{
|
{
|
||||||
code = m_ErrorCode;
|
code = m_error;
|
||||||
start = m_ErrorStart;
|
start = m_errorStart;
|
||||||
end = m_ErrorEnd;
|
end = m_errorEnd;
|
||||||
pProg = this;
|
pProg = this;
|
||||||
return code > 0;
|
return code > 0;
|
||||||
}
|
}
|
||||||
|
@ -351,7 +312,7 @@ bool CBotProgram::GetError(CBotError& code, int& start, int& end, CBotProgram*&
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotFunction* CBotProgram::GetFunctions()
|
CBotFunction* CBotProgram::GetFunctions()
|
||||||
{
|
{
|
||||||
return m_Prog;
|
return m_functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -393,7 +354,8 @@ CBotTypResult cSizeOf( CBotVar* &pVar, void* pUser )
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotProgram::DefineNum(const std::string& name, long val)
|
bool CBotProgram::DefineNum(const std::string& name, long val)
|
||||||
{
|
{
|
||||||
return CBotToken::DefineNum(name, val);
|
CBotToken::DefineNum(name, val);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -405,7 +367,7 @@ bool CBotProgram::SaveState(FILE* pf)
|
||||||
if ( m_pStack != nullptr )
|
if ( m_pStack != nullptr )
|
||||||
{
|
{
|
||||||
if (!WriteWord( pf, 1)) return false;
|
if (!WriteWord( pf, 1)) return false;
|
||||||
if (!WriteString( pf, m_pRun->GetName() )) return false;
|
if (!WriteString( pf, m_entryPoint->GetName() )) return false;
|
||||||
if (!m_pStack->SaveState(pf)) return false;
|
if (!m_pStack->SaveState(pf)) return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -445,7 +407,7 @@ bool CBotProgram::RestoreState(FILE* pf)
|
||||||
m_pStack->SetBotCall(this); // bases for routines
|
m_pStack->SetBotCall(this); // bases for routines
|
||||||
|
|
||||||
// restored some states in the stack according to the structure
|
// restored some states in the stack according to the structure
|
||||||
m_pRun->RestoreState(nullptr, m_pStack, m_pInstance);
|
m_entryPoint->RestoreState(nullptr, m_pStack, m_thisVar);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,18 +420,18 @@ int CBotProgram::GetVersion()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotProgram::Init()
|
void CBotProgram::Init()
|
||||||
{
|
{
|
||||||
CBotToken::DefineNum("CBotErrZeroDiv", CBotErrZeroDiv); // division by zero
|
CBotProgram::DefineNum("CBotErrZeroDiv", CBotErrZeroDiv); // division by zero
|
||||||
CBotToken::DefineNum("CBotErrNotInit", CBotErrNotInit); // uninitialized variable
|
CBotProgram::DefineNum("CBotErrNotInit", CBotErrNotInit); // uninitialized variable
|
||||||
CBotToken::DefineNum("CBotErrBadThrow", CBotErrBadThrow); // throw a negative value
|
CBotProgram::DefineNum("CBotErrBadThrow", CBotErrBadThrow); // throw a negative value
|
||||||
CBotToken::DefineNum("CBotErrNoRetVal", CBotErrNoRetVal); // function did not return results
|
CBotProgram::DefineNum("CBotErrNoRetVal", CBotErrNoRetVal); // function did not return results
|
||||||
CBotToken::DefineNum("CBotErrNoRun", CBotErrNoRun); // active Run () without a function // TODO: Is this actually a runtime error?
|
CBotProgram::DefineNum("CBotErrNoRun", CBotErrNoRun); // active Run () without a function // TODO: Is this actually a runtime error?
|
||||||
CBotToken::DefineNum("CBotErrUndefFunc", CBotErrUndefFunc); // Calling a function that no longer exists
|
CBotProgram::DefineNum("CBotErrUndefFunc", CBotErrUndefFunc); // Calling a function that no longer exists
|
||||||
CBotToken::DefineNum("CBotErrNotClass", CBotErrNotClass); // Class no longer exists
|
CBotProgram::DefineNum("CBotErrNotClass", CBotErrNotClass); // Class no longer exists
|
||||||
CBotToken::DefineNum("CBotErrNull", CBotErrNull); // Attempted to use a null pointer
|
CBotProgram::DefineNum("CBotErrNull", CBotErrNull); // Attempted to use a null pointer
|
||||||
CBotToken::DefineNum("CBotErrNan", CBotErrNan); // Can't do operations on nan
|
CBotProgram::DefineNum("CBotErrNan", CBotErrNan); // Can't do operations on nan
|
||||||
CBotToken::DefineNum("CBotErrOutArray", CBotErrOutArray); // Attempted access out of bounds of an array
|
CBotProgram::DefineNum("CBotErrOutArray", CBotErrOutArray); // Attempted access out of bounds of an array
|
||||||
CBotToken::DefineNum("CBotErrStackOver", CBotErrStackOver); // Stack overflow
|
CBotProgram::DefineNum("CBotErrStackOver", CBotErrStackOver); // Stack overflow
|
||||||
CBotToken::DefineNum("CBotErrDeletedPtr", CBotErrDeletedPtr); // Attempted to use deleted object
|
CBotProgram::DefineNum("CBotErrDeletedPtr", CBotErrDeletedPtr); // Attempted to use deleted object
|
||||||
|
|
||||||
CBotProgram::AddFunction("sizeof", rSizeOf, cSizeOf );
|
CBotProgram::AddFunction("sizeof", rSizeOf, cSizeOf );
|
||||||
|
|
||||||
|
@ -484,4 +446,4 @@ void CBotProgram::Free()
|
||||||
CBotToken::Free() ;
|
CBotToken::Free() ;
|
||||||
CBotCall ::Free() ;
|
CBotCall ::Free() ;
|
||||||
CBotClass::Free() ;
|
CBotClass::Free() ;
|
||||||
}
|
}
|
|
@ -86,9 +86,9 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Constructor
|
* \brief Constructor
|
||||||
* \param pInstance Variable to pass to the program as "this"
|
* \param thisVar Variable to pass to the program as "this"
|
||||||
*/
|
*/
|
||||||
CBotProgram(CBotVar* pInstance);
|
CBotProgram(CBotVar* thisVar);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Destructor
|
* \brief Destructor
|
||||||
|
@ -113,6 +113,12 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Compile compiles the program given as string
|
* \brief Compile compiles the program given as string
|
||||||
|
*
|
||||||
|
* Compilation is done in a few steps:
|
||||||
|
* 1. Convert the code into "tokens" - see CBotToken::CompileTokens()
|
||||||
|
* 2. First pass - getting declarations of all functions an classes for use later
|
||||||
|
* 3. Second pass - compiling definitions of all functions and classes
|
||||||
|
*
|
||||||
* \param program Code to compile
|
* \param program Code to compile
|
||||||
* \param[out] functions Returns the names of functions declared as extern
|
* \param[out] functions Returns the names of functions declared as extern
|
||||||
* \param pUser Optional pointer to be passed to compile function (see AddFunction())
|
* \param pUser Optional pointer to be passed to compile function (see AddFunction())
|
||||||
|
@ -121,17 +127,6 @@ public:
|
||||||
*/
|
*/
|
||||||
bool Compile(const std::string& program, std::vector<std::string>& functions, void* pUser = nullptr);
|
bool Compile(const std::string& program, std::vector<std::string>& functions, void* pUser = nullptr);
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Associates an unique identifier with this instance of CBotProgram
|
|
||||||
*/
|
|
||||||
void SetIdent(long n);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Returns the unique identifier
|
|
||||||
* \see SetIdent
|
|
||||||
*/
|
|
||||||
long GetIdent();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Returns the last error
|
* \brief Returns the last error
|
||||||
* \return Error code
|
* \return Error code
|
||||||
|
@ -344,20 +339,18 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! All user-defined functions
|
//! All user-defined functions
|
||||||
CBotFunction* m_Prog;
|
CBotFunction* m_functions = nullptr;
|
||||||
//! The entry point function
|
//! The entry point function
|
||||||
CBotFunction* m_pRun;
|
CBotFunction* m_entryPoint = nullptr;
|
||||||
//! Classes defined in this program
|
//! Classes defined in this program
|
||||||
CBotClass* m_pClass;
|
CBotClass* m_classes = nullptr;
|
||||||
//! Execution stack
|
//! Execution stack
|
||||||
CBotStack* m_pStack;
|
CBotStack* m_pStack = nullptr;
|
||||||
//! "this" variable
|
//! "this" variable
|
||||||
CBotVar* m_pInstance;
|
CBotVar* m_thisVar = nullptr;
|
||||||
friend class CBotFunction;
|
friend class CBotFunction;
|
||||||
|
|
||||||
CBotError m_ErrorCode;
|
CBotError m_error = CBotNoErr;
|
||||||
int m_ErrorStart;
|
int m_errorStart = 0;
|
||||||
int m_ErrorEnd;
|
int m_errorEnd = 0;
|
||||||
//! Associated identifier
|
|
||||||
long m_Ident;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,21 +17,120 @@
|
||||||
* along with this program. If not, see http://gnu.org/licenses
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Modules inlcude
|
|
||||||
#include "CBot/CBotToken.h"
|
#include "CBot/CBotToken.h"
|
||||||
#include "CBotKeywordStrings.h"
|
|
||||||
|
|
||||||
// Local include
|
|
||||||
|
|
||||||
// Global include
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
//! \brief Keeps the string corresponding to keyword ID
|
||||||
|
//! Map is filled with id-string pars that are needed for CBot language parsing
|
||||||
|
static const std::map<TokenId, const std::string> KEYWORDS = {
|
||||||
|
{ID_IF, "if"},
|
||||||
|
{ID_ELSE, "else"},
|
||||||
|
{ID_WHILE, "while"},
|
||||||
|
{ID_DO, "do"},
|
||||||
|
{ID_FOR, "for"},
|
||||||
|
{ID_BREAK, "break"},
|
||||||
|
{ID_CONTINUE, "continue"},
|
||||||
|
{ID_SWITCH, "switch"},
|
||||||
|
{ID_CASE, "case"},
|
||||||
|
{ID_DEFAULT, "default"},
|
||||||
|
{ID_TRY, "try"},
|
||||||
|
{ID_THROW, "throw"},
|
||||||
|
{ID_CATCH, "catch"},
|
||||||
|
{ID_FINALLY, "finally"},
|
||||||
|
{ID_TXT_AND, "and"},
|
||||||
|
{ID_TXT_OR, "or"},
|
||||||
|
{ID_TXT_NOT, "not"},
|
||||||
|
{ID_RETURN, "return"},
|
||||||
|
{ID_CLASS, "class"},
|
||||||
|
{ID_EXTENDS, "extends"},
|
||||||
|
{ID_SYNCHO, "synchronized"},
|
||||||
|
{ID_NEW, "new"},
|
||||||
|
{ID_PUBLIC, "public"},
|
||||||
|
{ID_EXTERN, "extern"},
|
||||||
|
{ID_STATIC, "static"},
|
||||||
|
{ID_PROTECTED, "protected"},
|
||||||
|
{ID_PRIVATE, "private"},
|
||||||
|
{ID_INT, "int"},
|
||||||
|
{ID_FLOAT, "float"},
|
||||||
|
{ID_BOOLEAN, "boolean"},
|
||||||
|
{ID_STRING, "string"},
|
||||||
|
{ID_VOID, "void"},
|
||||||
|
{ID_BOOL, "bool"},
|
||||||
|
{ID_TRUE, "true"},
|
||||||
|
{ID_FALSE, "false"},
|
||||||
|
{ID_NULL, "null"},
|
||||||
|
{ID_NAN, "nan"},
|
||||||
|
{ID_OPENPAR, "("},
|
||||||
|
{ID_CLOSEPAR, ")"},
|
||||||
|
{ID_OPBLK, "{"},
|
||||||
|
{ID_CLBLK, "}"},
|
||||||
|
{ID_SEP, ";"},
|
||||||
|
{ID_COMMA, ","},
|
||||||
|
{ID_DOTS, ":"},
|
||||||
|
{ID_DOT, "."},
|
||||||
|
{ID_OPBRK, "["},
|
||||||
|
{ID_CLBRK, "]"},
|
||||||
|
{ID_DBLDOTS, "::"},
|
||||||
|
{ID_LOGIC, "?"},
|
||||||
|
{ID_ADD, "+"},
|
||||||
|
{ID_SUB, "-"},
|
||||||
|
{ID_MUL, "*"},
|
||||||
|
{ID_DIV, "/"},
|
||||||
|
{ID_ASS, "="},
|
||||||
|
{ID_ASSADD, "+="},
|
||||||
|
{ID_ASSSUB, "-="},
|
||||||
|
{ID_ASSMUL, "*="},
|
||||||
|
{ID_ASSDIV, "/="},
|
||||||
|
{ID_ASSOR, "|="},
|
||||||
|
{ID_ASSAND, "&="},
|
||||||
|
{ID_ASSXOR, "^="},
|
||||||
|
{ID_ASSSL, "<<="},
|
||||||
|
{ID_ASSSR, ">>>="},
|
||||||
|
{ID_ASSASR, ">>="},
|
||||||
|
{ID_SL, "<<"},
|
||||||
|
{ID_SR, ">>"},
|
||||||
|
{ID_ASR, ">>"},
|
||||||
|
{ID_INC, "++"},
|
||||||
|
{ID_DEC, "--"},
|
||||||
|
{ID_LO, "<"},
|
||||||
|
{ID_HI, ">"},
|
||||||
|
{ID_LS, "<="},
|
||||||
|
{ID_HS, ">="},
|
||||||
|
{ID_EQ, "=="},
|
||||||
|
{ID_NE, "!="},
|
||||||
|
{ID_AND, "&"},
|
||||||
|
{ID_XOR, "^"},
|
||||||
|
{ID_OR, "|"},
|
||||||
|
{ID_LOG_AND, "&&"},
|
||||||
|
{ID_LOG_OR, "||"},
|
||||||
|
{ID_LOG_NOT, "!"},
|
||||||
|
{ID_NOT, "~"},
|
||||||
|
{ID_MODULO, "%"},
|
||||||
|
{ID_POWER, "**"},
|
||||||
|
{ID_ASSMODULO, "%="},
|
||||||
|
{TX_UNDEF, "undefined"},
|
||||||
|
{TX_NAN, "not a number"}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const std::string emptyString = "";
|
||||||
|
}
|
||||||
|
const std::string& LoadString(TokenId id)
|
||||||
|
{
|
||||||
|
if (KEYWORDS.find(id) != KEYWORDS.end())
|
||||||
|
{
|
||||||
|
return KEYWORDS.at(id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return emptyString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
std::vector<std::string> CBotToken::m_ListKeyWords;
|
std::map<std::string, long> CBotToken::m_defineNum;
|
||||||
int CBotToken::m_ListIdKeyWords[200];
|
|
||||||
std::vector<std::string> CBotToken::m_ListKeyDefine;
|
|
||||||
long CBotToken::m_ListKeyNums[MAXDEFNUM];
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotToken::CBotToken()
|
CBotToken::CBotToken()
|
||||||
{
|
{
|
||||||
|
@ -94,7 +193,7 @@ CBotToken::~CBotToken()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotToken::Free()
|
void CBotToken::Free()
|
||||||
{
|
{
|
||||||
m_ListKeyDefine.clear();
|
m_defineNum.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -194,20 +293,6 @@ bool CharInList(const char c, const char* list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
bool Char2InList(const char c, const char cc, const char* list)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (c == list[i++] &&
|
|
||||||
cc == list[i++]) return true;
|
|
||||||
|
|
||||||
if (list[i] == 0) return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static char sep1[] = " \r\n\t,:()[]{}-+*/=;><!~^|&%.";
|
static char sep1[] = " \r\n\t,:()[]{}-+*/=;><!~^|&%.";
|
||||||
static char sep2[] = " \r\n\t"; // only separators
|
static char sep2[] = " \r\n\t"; // only separators
|
||||||
static char sep3[] = ",:()[]{}-+*/=;<>!~^|&%."; // operational separators
|
static char sep3[] = ",:()[]{}-+*/=;<>!~^|&%."; // operational separators
|
||||||
|
@ -216,24 +301,23 @@ static char hexnum[] = "0123456789ABCDEFabcdef";
|
||||||
static char nch[] = "\"\r\n\t"; // forbidden in chains
|
static char nch[] = "\"\r\n\t"; // forbidden in chains
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotToken* CBotToken::NextToken(char* &program, int& error, bool first)
|
CBotToken* CBotToken::NextToken(const char*& program, bool first)
|
||||||
{
|
{
|
||||||
std::string mot; // the word which is found
|
std::string token; // found token
|
||||||
std::string sep; // separators that are after
|
std::string sep; // separators after the token
|
||||||
char c;
|
bool stop = first;
|
||||||
bool stop = first;
|
|
||||||
|
|
||||||
if (*program == 0) return nullptr;
|
if (*program == 0) return nullptr;
|
||||||
|
|
||||||
c = *(program++); // next character
|
char c = *(program++); // next character
|
||||||
|
|
||||||
if (!first)
|
if (!first)
|
||||||
{
|
{
|
||||||
mot = c; // built the word
|
token = c; // built the word
|
||||||
c = *(program++); // next character
|
c = *(program++); // next character
|
||||||
|
|
||||||
// special case for strings
|
// special case for strings
|
||||||
if ( mot[0] == '\"' )
|
if (token[0] == '\"' )
|
||||||
{
|
{
|
||||||
while (c != 0 && !CharInList(c, nch))
|
while (c != 0 && !CharInList(c, nch))
|
||||||
{
|
{
|
||||||
|
@ -244,34 +328,34 @@ CBotToken* CBotToken::NextToken(char* &program, int& error, bool first)
|
||||||
if ( c == 'r' ) c = '\r';
|
if ( c == 'r' ) c = '\r';
|
||||||
if ( c == 't' ) c = '\t';
|
if ( c == 't' ) c = '\t';
|
||||||
}
|
}
|
||||||
mot += c;
|
token += c;
|
||||||
c = *(program++);
|
c = *(program++);
|
||||||
}
|
}
|
||||||
if ( c == '\"' )
|
if ( c == '\"' )
|
||||||
{
|
{
|
||||||
mot += c; // string is complete
|
token += c; // string is complete
|
||||||
c = *(program++); // next character
|
c = *(program++); // next character
|
||||||
}
|
}
|
||||||
stop = true;
|
stop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// special case for numbers
|
// special case for numbers
|
||||||
if ( CharInList(mot[0], num ))
|
if ( CharInList(token[0], num ))
|
||||||
{
|
{
|
||||||
bool bdot = false; // found a point?
|
bool bdot = false; // found a point?
|
||||||
bool bexp = false; // found an exponent?
|
bool bexp = false; // found an exponent?
|
||||||
|
|
||||||
char* liste = num;
|
char* liste = num;
|
||||||
if (mot[0] == '0' && c == 'x') // hexadecimal value?
|
if (token[0] == '0' && c == 'x') // hexadecimal value?
|
||||||
{
|
{
|
||||||
mot += c;
|
token += c;
|
||||||
c = *(program++); // next character
|
c = *(program++); // next character
|
||||||
liste = hexnum;
|
liste = hexnum;
|
||||||
}
|
}
|
||||||
cw:
|
cw:
|
||||||
while (c != 0 && CharInList(c, liste))
|
while (c != 0 && CharInList(c, liste))
|
||||||
{
|
{
|
||||||
cc: mot += c;
|
cc: token += c;
|
||||||
c = *(program++); // next character
|
c = *(program++); // next character
|
||||||
}
|
}
|
||||||
if ( liste == num ) // not for hexadecimal
|
if ( liste == num ) // not for hexadecimal
|
||||||
|
@ -280,7 +364,7 @@ cc: mot += c;
|
||||||
if ( !bexp && ( c == 'e' || c == 'E' ) )
|
if ( !bexp && ( c == 'e' || c == 'E' ) )
|
||||||
{
|
{
|
||||||
bexp = true;
|
bexp = true;
|
||||||
mot += c;
|
token += c;
|
||||||
c = *(program++); // next character
|
c = *(program++); // next character
|
||||||
if ( c == '-' ||
|
if ( c == '-' ||
|
||||||
c == '+' ) goto cc;
|
c == '+' ) goto cc;
|
||||||
|
@ -291,12 +375,12 @@ cc: mot += c;
|
||||||
stop = true;
|
stop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CharInList(mot[0], sep3)) // an operational separator?
|
if (CharInList(token[0], sep3)) // an operational separator?
|
||||||
{
|
{
|
||||||
std::string motc = mot;
|
std::string motc = token;
|
||||||
while (motc += c, c != 0 && GetKeyWords(motc)>0) // operand seeks the longest possible
|
while (motc += c, c != 0 && GetKeyWord(motc) > 0) // operand seeks the longest possible
|
||||||
{
|
{
|
||||||
mot += c; // build the word
|
token += c; // build the word
|
||||||
c = *(program++); // next character
|
c = *(program++); // next character
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +394,7 @@ cc: mot += c;
|
||||||
{
|
{
|
||||||
if (stop || c == 0 || CharInList(c, sep1))
|
if (stop || c == 0 || CharInList(c, sep1))
|
||||||
{
|
{
|
||||||
if (!first && mot.empty()) return nullptr; // end of the analysis
|
if (!first && token.empty()) return nullptr; // end of the analysis
|
||||||
bis:
|
bis:
|
||||||
while (CharInList(c, sep2))
|
while (CharInList(c, sep2))
|
||||||
{
|
{
|
||||||
|
@ -346,33 +430,32 @@ bis:
|
||||||
|
|
||||||
program--;
|
program--;
|
||||||
|
|
||||||
CBotToken* token = new CBotToken(mot, sep);
|
CBotToken* t = new CBotToken(token, sep);
|
||||||
|
|
||||||
if (CharInList( mot[0], num )) token->m_type = TokenTypNum;
|
if (CharInList(token[0], num )) t->m_type = TokenTypNum;
|
||||||
if (mot[0] == '\"') token->m_type = TokenTypString;
|
if (token[0] == '\"') t->m_type = TokenTypString;
|
||||||
if (first) token->m_type = TokenTypNone;
|
if (first) t->m_type = TokenTypNone;
|
||||||
|
|
||||||
token->m_IdKeyWord = GetKeyWords(mot);
|
t->m_IdKeyWord = GetKeyWord(token);
|
||||||
if (token->m_IdKeyWord > 0) token->m_type = TokenTypKeyWord;
|
if (t->m_IdKeyWord > 0) t->m_type = TokenTypKeyWord;
|
||||||
else GetKeyDefNum(mot, token) ; // treats DefineNum
|
else GetKeyDefNum(token, t) ; // treats DefineNum
|
||||||
|
|
||||||
return token;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
mot += c; // built the word
|
token += c; // built the word
|
||||||
c = *(program++); // next character
|
c = *(program++); // next character
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotToken* CBotToken::CompileTokens(const std::string& program, int& error)
|
CBotToken* CBotToken::CompileTokens(const std::string& program)
|
||||||
{
|
{
|
||||||
CBotToken *nxt, *prv, *tokenbase;
|
CBotToken *nxt, *prv, *tokenbase;
|
||||||
char* p = const_cast<char*> (program.c_str());
|
const char* p = program.c_str();
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
||||||
error = 0;
|
prv = tokenbase = NextToken(p, true);
|
||||||
prv = tokenbase = NextToken(p, error, true);
|
|
||||||
|
|
||||||
if (tokenbase == nullptr) return nullptr;
|
if (tokenbase == nullptr) return nullptr;
|
||||||
|
|
||||||
|
@ -381,29 +464,19 @@ CBotToken* CBotToken::CompileTokens(const std::string& program, int& error)
|
||||||
tokenbase->m_end = pos;
|
tokenbase->m_end = pos;
|
||||||
pos += tokenbase->m_Sep.length();
|
pos += tokenbase->m_Sep.length();
|
||||||
|
|
||||||
char* pp = p;
|
const char* pp = p;
|
||||||
while (nullptr != (nxt = NextToken(p, error)))
|
while (nullptr != (nxt = NextToken(p, false)))
|
||||||
{
|
{
|
||||||
prv->m_next = nxt; // added after
|
prv->m_next = nxt; // added after
|
||||||
nxt->m_prev = prv;
|
nxt->m_prev = prv;
|
||||||
prv = nxt; // advance
|
prv = nxt; // advance
|
||||||
|
|
||||||
nxt->m_start = pos;
|
nxt->m_start = pos;
|
||||||
/* pos += nxt->m_Text.GetLength(); // chain may be shorter (BOA deleted)
|
|
||||||
nxt->m_end = pos;
|
|
||||||
pos += nxt->m_Sep.GetLength();*/
|
|
||||||
pos += (p - pp); // total size
|
pos += (p - pp); // total size
|
||||||
nxt->m_end = pos - nxt->m_Sep.length();
|
nxt->m_end = pos - nxt->m_Sep.length();
|
||||||
pp = p;
|
pp = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds a token as a terminator
|
|
||||||
// ( useful for the previous )
|
|
||||||
nxt = new CBotToken();
|
|
||||||
nxt->m_type = TokenTypNone;
|
|
||||||
prv->m_next = nxt; // added after
|
|
||||||
nxt->m_prev = prv;
|
|
||||||
|
|
||||||
return tokenbase;
|
return tokenbase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,87 +487,38 @@ void CBotToken::Delete(CBotToken* pToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int CBotToken::GetKeyWords(const std::string& w)
|
int CBotToken::GetKeyWord(const std::string& w)
|
||||||
{
|
{
|
||||||
int i;
|
for (const auto& it : KEYWORDS)
|
||||||
int l = m_ListKeyWords.size();
|
|
||||||
|
|
||||||
if (l == 0)
|
|
||||||
{
|
{
|
||||||
LoadKeyWords(); // takes the list for the first time
|
if (it.second == w) return it.first;
|
||||||
l = m_ListKeyWords.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < l; i++)
|
|
||||||
{
|
|
||||||
if (m_ListKeyWords[i] == w) return m_ListIdKeyWords[ i ];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotToken::GetKeyDefNum(const std::string& w, CBotToken*& token)
|
bool CBotToken::GetKeyDefNum(const std::string& name, CBotToken* token)
|
||||||
{
|
{
|
||||||
int i;
|
if (m_defineNum.count(name) == 0)
|
||||||
int l = m_ListKeyDefine.size();
|
return false;
|
||||||
|
|
||||||
for (i = 0; i < l; i++)
|
token->m_type = TokenTypDef;
|
||||||
{
|
token->m_IdKeyWord = m_defineNum[name];
|
||||||
if (m_ListKeyDefine[i] == w)
|
return true;
|
||||||
{
|
|
||||||
token->m_IdKeyWord = m_ListKeyNums[i];
|
|
||||||
token->m_type = TokenTypDef;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
void CBotToken::LoadKeyWords()
|
|
||||||
{
|
|
||||||
std::string s;
|
|
||||||
int i, n = 0;
|
|
||||||
|
|
||||||
i = TokenKeyWord; //start with keywords of the language
|
|
||||||
while (!(s = LoadString(static_cast<TokenId>(i))).empty())
|
|
||||||
{
|
|
||||||
m_ListKeyWords.push_back(s);
|
|
||||||
m_ListIdKeyWords[n++] = i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
i = TokenKeyVal; //keywords of values
|
|
||||||
while (!(s = LoadString(static_cast<TokenId>(i))).empty())
|
|
||||||
{
|
|
||||||
m_ListKeyWords.push_back(s);
|
|
||||||
m_ListIdKeyWords[n++] = i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = TokenKeyOp; //operators
|
|
||||||
while (!(s = LoadString(static_cast<TokenId>(i))).empty())
|
|
||||||
{
|
|
||||||
m_ListKeyWords.push_back(s);
|
|
||||||
m_ListIdKeyWords[n++] = i++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotToken::DefineNum(const std::string& name, long val)
|
bool CBotToken::DefineNum(const std::string& name, long val)
|
||||||
{
|
{
|
||||||
int i;
|
if (m_defineNum.count(name) > 0)
|
||||||
int l = m_ListKeyDefine.size();
|
|
||||||
|
|
||||||
for (i = 0; i < l; i++)
|
|
||||||
{
|
{
|
||||||
if (m_ListKeyDefine[i] == name) return false;
|
// TODO: No access to the logger from CBot library :(
|
||||||
|
printf("CBOT WARNING: %s redefined\n", name.c_str());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if ( i == MAXDEFNUM ) return false;
|
|
||||||
|
|
||||||
m_ListKeyDefine.push_back( name );
|
m_defineNum[name] = val;
|
||||||
m_ListKeyNums[i] = val;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,10 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "CBot/CBotEnums.h"
|
#include "CBot/CBotEnums.h"
|
||||||
|
|
||||||
#define MAXDEFNUM 1000 // limited number of DefineNum
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Class representing one token of a program.
|
* \brief Class representing one token of a program.
|
||||||
*
|
*
|
||||||
|
@ -166,17 +165,7 @@ public:
|
||||||
* \return The first token of the linked liste.
|
* \return The first token of the linked liste.
|
||||||
* \todo Replace the error code by an enum.
|
* \todo Replace the error code by an enum.
|
||||||
*/
|
*/
|
||||||
static CBotToken* CompileTokens(const std::string& p, int& error);
|
static CBotToken* CompileTokens(const std::string& p);
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief NextToken Looking for the next token in the string. The string must
|
|
||||||
* not start with separators. The separator is part of the previous token.
|
|
||||||
* \param [in] program The program string.
|
|
||||||
* \param [out] error The error code.
|
|
||||||
* \param [in] first True if this is the first call false othewise.
|
|
||||||
* \return A CBotTOken.
|
|
||||||
*/
|
|
||||||
static CBotToken* NextToken(char* &program, int& error, bool first = false);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Delete Releases the CBotToken linked list.
|
* \brief Delete Releases the CBotToken linked list.
|
||||||
|
@ -200,6 +189,17 @@ public:
|
||||||
*/
|
*/
|
||||||
static void Free();
|
static void Free();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*!
|
||||||
|
* \brief NextToken Looking for the next token in the string. The string must
|
||||||
|
* not start with separators. The separator is part of the previous token.
|
||||||
|
* \param [in] program The program string.
|
||||||
|
* \param [out] error The error code.
|
||||||
|
* \param [in] first True if this is the first call false othewise.
|
||||||
|
* \return A CBotTOken.
|
||||||
|
*/
|
||||||
|
static CBotToken* NextToken(const char*& program, bool first);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//! The next token in the linked list
|
//! The next token in the linked list
|
||||||
|
@ -221,42 +221,23 @@ private:
|
||||||
//! The end position of the token in the CBotProgram
|
//! The end position of the token in the CBotProgram
|
||||||
int m_end;
|
int m_end;
|
||||||
|
|
||||||
/*!
|
//! Map of all predefined constants (see DefineNum())
|
||||||
* \brief GetKeyWords Check if the word is a keyword.
|
static std::map<std::string, long> m_defineNum;
|
||||||
* \param w The word to compare.
|
|
||||||
* \return -1 if this is not a keyword the keyword number otherwise.
|
|
||||||
*/
|
|
||||||
static int GetKeyWords(const std::string& w); // is it a keyword?
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief GetKeyDefNum Check if this is a defined word and set the defined
|
* \brief Check if the word is a keyword
|
||||||
* word type in a CBotToken.
|
* \param w The word to check
|
||||||
* \param [in] w The word to compaire.
|
* \return the keyword ID, or -1 if this is not a keyword
|
||||||
* \param [out] token The token in which the type will be set.
|
|
||||||
* \return True if the defined word is found false otherwise.
|
|
||||||
*/
|
*/
|
||||||
static bool GetKeyDefNum(const std::string& w, CBotToken*& token);
|
static int GetKeyWord(const std::string& w);
|
||||||
|
|
||||||
/*!
|
/**
|
||||||
* \brief LoadKeyWords Loads the list of keywords. The list of keyword is
|
* \brief Resolve a constant defined with DefineNum()
|
||||||
* std::string::s_keywordString. This keywords are keywords languages (if, +,
|
* \param name Constant name
|
||||||
* for, while, case, extern ...)
|
* \param token Token that we are working on, will be filled with data about found constant
|
||||||
* \todo Fixme Figure out how this should work.
|
* \return true if the constant was found, false otherwise
|
||||||
*/
|
*/
|
||||||
static void LoadKeyWords();
|
static bool GetKeyDefNum(const std::string& name, CBotToken* token);
|
||||||
|
|
||||||
//! List of keywords of the CBot language (if, +, for, while, case, extern ...)
|
|
||||||
static std::vector<std::string> m_ListKeyWords;
|
|
||||||
//! List of id correponding to the keywords of the CBot language
|
|
||||||
static int m_ListIdKeyWords[200];
|
|
||||||
|
|
||||||
//! List of CBot language error and list of colobot specific keywords
|
|
||||||
//! This keywords are defined in :
|
|
||||||
//! - void CScriptFunctions::Init()
|
|
||||||
//! - void CBotProgram::Init()
|
|
||||||
static std::vector<std::string> m_ListKeyDefine;
|
|
||||||
//! List of id correponding to the defined words
|
|
||||||
static long m_ListKeyNums[MAXDEFNUM];
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -276,3 +257,13 @@ extern bool IsOfType(CBotToken* &p, int type1, int type2 = -1);
|
||||||
* \return True if the type of the token match one of a parameter.
|
* \return True if the type of the token match one of a parameter.
|
||||||
*/
|
*/
|
||||||
extern bool IsOfTypeList(CBotToken* &p, int type1, ...);
|
extern bool IsOfTypeList(CBotToken* &p, int type1, ...);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief LoadString Maps given ID to its string equivalent.
|
||||||
|
* \param id Provided identifier.
|
||||||
|
* \return String if found, else NullString.
|
||||||
|
*/
|
||||||
|
const std::string& LoadString(TokenId id);
|
||||||
|
|
|
@ -355,7 +355,7 @@ void CBotVar::SetInit(CBotVar::InitType initType)
|
||||||
if ( instance == nullptr )
|
if ( instance == nullptr )
|
||||||
{
|
{
|
||||||
instance = new CBotVarClass(nullptr, m_type);
|
instance = new CBotVarClass(nullptr, m_type);
|
||||||
// instance->SetClass((static_cast<CBotVarPointer*>(this))->m_pClass);
|
// instance->SetClass((static_cast<CBotVarPointer*>(this))->m_classes);
|
||||||
SetPointer(instance);
|
SetPointer(instance);
|
||||||
}
|
}
|
||||||
instance->SetInit(CBotVar::InitType::DEF);
|
instance->SetInit(CBotVar::InitType::DEF);
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
#include "CBot/CBotEnums.h"
|
#include "CBot/CBotEnums.h"
|
||||||
#include "CBot/CBotUtils.h"
|
#include "CBot/CBotUtils.h"
|
||||||
#include "CBot/CBotKeywordStrings.h"
|
|
||||||
|
|
||||||
#include "CBot/CBotToken.h"
|
#include "CBot/CBotToken.h"
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
#include "CBot/CBotEnums.h"
|
#include "CBot/CBotEnums.h"
|
||||||
#include "CBot/CBotToken.h"
|
#include "CBot/CBotToken.h"
|
||||||
#include "CBot/CBotKeywordStrings.h"
|
|
||||||
|
|
||||||
#include "CBot/CBotUtils.h"
|
#include "CBot/CBotUtils.h"
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include "CBot/CBotEnums.h"
|
#include "CBot/CBotEnums.h"
|
||||||
#include "CBot/CBotToken.h"
|
#include "CBot/CBotToken.h"
|
||||||
#include "CBot/CBotUtils.h"
|
#include "CBot/CBotUtils.h"
|
||||||
#include "CBot/CBotKeywordStrings.h"
|
|
||||||
|
|
||||||
// Local include
|
// Local include
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include "CBot/CBotEnums.h"
|
#include "CBot/CBotEnums.h"
|
||||||
#include "CBot/CBotToken.h"
|
#include "CBot/CBotToken.h"
|
||||||
#include "CBot/CBotUtils.h"
|
#include "CBot/CBotUtils.h"
|
||||||
#include "CBot/CBotKeywordStrings.h"
|
|
||||||
|
|
||||||
// Local include
|
// Local include
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ set(SOURCES
|
||||||
CBotDefParam.cpp
|
CBotDefParam.cpp
|
||||||
CBotCallMethode.cpp
|
CBotCallMethode.cpp
|
||||||
CBotTypResult.cpp
|
CBotTypResult.cpp
|
||||||
CBotKeywordStrings.cpp
|
|
||||||
CBotInstr/CBotInstr.cpp
|
CBotInstr/CBotInstr.cpp
|
||||||
CBotInstr/CBotInstrUtils.cpp
|
CBotInstr/CBotInstrUtils.cpp
|
||||||
CBotInstr/CBotWhile.cpp
|
CBotInstr/CBotWhile.cpp
|
||||||
|
|
|
@ -160,7 +160,7 @@ bool CScript::CheckToken()
|
||||||
CBotToken* allBt;
|
CBotToken* allBt;
|
||||||
std::string bs;
|
std::string bs;
|
||||||
std::string token;
|
std::string token;
|
||||||
int error, cursor1, cursor2, i;
|
int cursor1, cursor2, i;
|
||||||
char used[100];
|
char used[100];
|
||||||
|
|
||||||
if ( !m_object->GetCheckToken() ) return true;
|
if ( !m_object->GetCheckToken() ) return true;
|
||||||
|
@ -176,7 +176,7 @@ bool CScript::CheckToken()
|
||||||
used[i] = 0; // token not used
|
used[i] = 0; // token not used
|
||||||
}
|
}
|
||||||
|
|
||||||
allBt = CBotToken::CompileTokens(m_script.get(), error);
|
allBt = CBotToken::CompileTokens(m_script.get());
|
||||||
bt = allBt;
|
bt = allBt;
|
||||||
while ( bt != nullptr )
|
while ( bt != nullptr )
|
||||||
{
|
{
|
||||||
|
@ -635,8 +635,7 @@ void CScript::ColorizeScript(Ui::CEdit* edit, int rangeStart, int rangeEnd)
|
||||||
std::string text = std::string(edit->GetText(), edit->GetMaxChar());
|
std::string text = std::string(edit->GetText(), edit->GetMaxChar());
|
||||||
text = text.substr(rangeStart, rangeEnd-rangeStart);
|
text = text.substr(rangeStart, rangeEnd-rangeStart);
|
||||||
|
|
||||||
int error;
|
CBotToken* bt = CBotToken::CompileTokens(text.c_str());
|
||||||
CBotToken* bt = CBotToken::CompileTokens(text.c_str(), error);
|
|
||||||
while ( bt != nullptr )
|
while ( bt != nullptr )
|
||||||
{
|
{
|
||||||
std::string token = bt->GetString();
|
std::string token = bt->GetString();
|
||||||
|
|
Loading…
Reference in New Issue