[colobot] 177/377: Some random CBotProgram and CBotToken refactoring
Didier Raboud
odyx at moszumanska.debian.org
Wed Mar 30 13:34:13 UTC 2016
This is an automated email from the git hooks/post-receive script.
odyx pushed a commit to branch debian/master
in repository colobot.
commit fbdc071659b14e2d71307e9b48da7f24c89ded55
Author: krzys-h <krzys_h at interia.pl>
Date: Wed Dec 23 15:36:55 2015 +0100
Some random CBotProgram and CBotToken refactoring
---
src/CBot/CBotInstr/CBotFunction.cpp | 4 +-
src/CBot/CBotKeywordStrings.cpp | 108 --------------
src/CBot/CBotKeywordStrings.h | 12 --
src/CBot/CBotProgram.cpp | 174 +++++++++-------------
src/CBot/CBotProgram.h | 39 ++---
src/CBot/CBotToken.cpp | 290 +++++++++++++++++++-----------------
src/CBot/CBotToken.h | 79 +++++-----
src/CBot/CBotVar/CBotVar.cpp | 2 +-
src/CBot/CBotVar/CBotVarBoolean.cpp | 1 -
src/CBot/CBotVar/CBotVarFloat.cpp | 1 -
src/CBot/CBotVar/CBotVarInt.cpp | 1 -
src/CBot/CBotVar/CBotVarString.cpp | 1 -
src/CBot/CMakeLists.txt | 1 -
src/script/script.cpp | 7 +-
14 files changed, 282 insertions(+), 438 deletions(-)
diff --git a/src/CBot/CBotInstr/CBotFunction.cpp b/src/CBot/CBotInstr/CBotFunction.cpp
index 7b4f1f9..e1a9398 100644
--- a/src/CBot/CBotInstr/CBotFunction.cpp
+++ b/src/CBot/CBotInstr/CBotFunction.cpp
@@ -623,7 +623,7 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars
{
if ( !pt->m_MasterClass.empty() )
{
- CBotVar* pInstance = m_pProg->m_pInstance;
+ CBotVar* pInstance = m_pProg->m_thisVar;
// make "this" known
CBotVar* pThis ;
if ( pInstance == nullptr )
@@ -702,7 +702,7 @@ void CBotFunction::RestoreCall(long& nIdent, const std::string& name, CBotVar**
{
if ( !pt->m_MasterClass.empty() )
{
-// CBotVar* pInstance = m_pProg->m_pInstance;
+// CBotVar* pInstance = m_pProg->m_thisVar;
// make "this" known
CBotVar* pThis = pStk1->FindVar("this");
pThis->SetInit(CBotVar::InitType::IS_POINTER);
diff --git a/src/CBot/CBotKeywordStrings.cpp b/src/CBot/CBotKeywordStrings.cpp
deleted file mode 100644
index 75e52ad..0000000
--- a/src/CBot/CBotKeywordStrings.cpp
+++ /dev/null
@@ -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;
- }
-}
\ No newline at end of file
diff --git a/src/CBot/CBotKeywordStrings.h b/src/CBot/CBotKeywordStrings.h
deleted file mode 100644
index 6cdb0cf..0000000
--- a/src/CBot/CBotKeywordStrings.h
+++ /dev/null
@@ -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);
diff --git a/src/CBot/CBotProgram.cpp b/src/CBot/CBotProgram.cpp
index c2cc816..66697d7 100644
--- a/src/CBot/CBotProgram.cpp
+++ b/src/CBot/CBotProgram.cpp
@@ -17,7 +17,6 @@
* along with this program. If not, see http://gnu.org/licenses
*/
-// Modules inlcude
#include "CBot/CBotVar/CBotVar.h"
#include "CBot/CBotCall.h"
@@ -29,51 +28,26 @@
#include "CBot/CBotInstr/CBotFunction.h"
-#include "CBotKeywordStrings.h"
-
#include "CBot/stdlib/stdlib.h"
-// Local include
-
-// Global include
-#include <stdio.h>
-
-////////////////////////////////////////////////////////////////////////////////
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* pInstance)
+CBotProgram::CBotProgram(CBotVar* thisVar)
+: 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()
{
-// delete m_pClass;
- m_pClass->Purge();
- m_pClass = nullptr;
+// delete m_classes;
+ m_classes->Purge();
+ m_classes = nullptr;
CBotClass::FreeLock(this);
- delete m_Prog;
+ delete m_functions;
#if STACKMEM
m_pStack->Delete();
#else
@@ -81,33 +55,31 @@ CBotProgram::~CBotProgram()
#endif
}
-////////////////////////////////////////////////////////////////////////////////
bool CBotProgram::Compile(const std::string& program, std::vector<std::string>& functions, void* pUser)
{
- int error = 0;
+ // Cleanup the previously compiled program
Stop();
-// delete m_pClass;
- m_pClass->Purge(); // purge the old definitions of classes
+// delete m_classes;
+ m_classes->Purge(); // purge the old definitions of classes
// but without destroying the object
- m_pClass = nullptr;
- delete m_Prog; m_Prog= nullptr;
+ m_classes = nullptr;
+ delete m_functions; m_functions = nullptr;
functions.clear();
- m_ErrorCode = CBotNoErr;
+ m_error = CBotNoErr;
- // transforms the program in Tokens
- CBotToken* pBaseToken = CBotToken::CompileTokens(program, error);
+ // Step 1. Process the code into tokens
+ CBotToken* pBaseToken = CBotToken::CompileTokens(program);
if ( pBaseToken == nullptr ) return false;
-
CBotCStack* pStack = new CBotCStack(nullptr);
CBotToken* p = pBaseToken->GetNext(); // skips the first token (separator)
pStack->SetBotCall(this); // defined used routines
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)
{
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 ))
{
CBotClass* nxt = CBotClass::Compile1(p, pStack);
- if (m_pClass == nullptr ) m_pClass = nxt;
- else m_pClass->AddNext(nxt);
+ if (m_classes == nullptr ) m_classes = nxt;
+ else m_classes->AddNext(nxt);
}
else
{
CBotFunction* next = CBotFunction::Compile1(p, pStack, nullptr);
- if (m_Prog == nullptr ) m_Prog = next;
- else m_Prog->AddNext(next);
+ if (m_functions == nullptr ) m_functions = next;
+ else m_functions->AddNext(next);
}
}
if ( !pStack->IsOk() )
{
- m_ErrorCode = pStack->GetError(m_ErrorStart, m_ErrorEnd);
- delete m_Prog;
- m_Prog = nullptr;
+ m_error = pStack->GetError(m_errorStart, m_errorEnd);
+ delete m_functions;
+ m_functions = nullptr;
delete pBaseToken;
return false;
}
+ // Step 3. Real compilation
// CBotFunction* temp = nullptr;
- CBotFunction* next = m_Prog; // rewind the list
+ CBotFunction* next = m_functions; // rewind the list
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() )
{
- m_ErrorCode = pStack->GetError(m_ErrorStart, m_ErrorEnd);
- delete m_Prog;
- m_Prog = nullptr;
+ m_error = pStack->GetError(m_errorStart, m_errorEnd);
+ delete m_functions;
+ m_functions = nullptr;
}
delete pBaseToken;
delete pStack;
- return (m_Prog != nullptr);
+ return (m_functions != nullptr);
}
////////////////////////////////////////////////////////////////////////////////
@@ -186,16 +159,16 @@ bool CBotProgram::Start(const std::string& name)
#endif
m_pStack = nullptr;
- m_pRun = m_Prog;
- while (m_pRun != nullptr)
+ m_entryPoint = m_functions;
+ while (m_entryPoint != nullptr)
{
- if ( m_pRun->GetName() == name ) break;
- m_pRun = m_pRun->m_next;
+ if (m_entryPoint->GetName() == name ) break;
+ m_entryPoint = m_entryPoint->m_next;
}
- if ( m_pRun == nullptr )
+ if (m_entryPoint == nullptr )
{
- m_ErrorCode = CBotErrNoRun;
+ m_error = CBotErrNoRun;
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)
{
- CBotFunction* p = m_Prog;
+ CBotFunction* p = m_functions;
while (p != nullptr)
{
if ( p->GetName() == name ) break;
@@ -231,9 +204,9 @@ bool CBotProgram::Run(void* pUser, int timer)
{
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
if ( timer >= 0 ) m_pStack->SetTimer(timer);
@@ -246,16 +219,16 @@ bool CBotProgram::Run(void* pUser, int timer)
if ( ok )
{
// returns to normal execution
- ok = m_pRun->Execute(nullptr, m_pStack, m_pInstance);
+ ok = m_entryPoint->Execute(nullptr, m_pStack, m_thisVar);
}
#else
- ok = m_pRun->Execute(nullptr, m_pStack, m_pInstance);
+ ok = m_pRun->Execute(nullptr, m_pStack, m_thisVar);
#endif
// completed on a mistake?
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
m_pStack->Delete();
#else
@@ -265,11 +238,11 @@ bool CBotProgram::Run(void* pUser, int timer)
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;
error:
- m_ErrorCode = CBotErrNoRun;
+ m_error = CBotErrNoRun;
return true;
}
@@ -282,7 +255,7 @@ void CBotProgram::Stop()
delete m_pStack;
#endif
m_pStack = nullptr;
- m_pRun = nullptr;
+ m_entryPoint = nullptr;
}
////////////////////////////////////////////////////////////////////////////////
@@ -314,36 +287,24 @@ void CBotProgram::SetTimer(int n)
////////////////////////////////////////////////////////////////////////////////
CBotError CBotProgram::GetError()
{
- return m_ErrorCode;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void CBotProgram::SetIdent(long n)
-{
- m_Ident = n;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-long CBotProgram::GetIdent()
-{
- return m_Ident;
+ return m_error;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotProgram::GetError(CBotError& code, int& start, int& end)
{
- code = m_ErrorCode;
- start = m_ErrorStart;
- end = m_ErrorEnd;
+ code = m_error;
+ start = m_errorStart;
+ end = m_errorEnd;
return code > 0;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotProgram::GetError(CBotError& code, int& start, int& end, CBotProgram*& pProg)
{
- code = m_ErrorCode;
- start = m_ErrorStart;
- end = m_ErrorEnd;
+ code = m_error;
+ start = m_errorStart;
+ end = m_errorEnd;
pProg = this;
return code > 0;
}
@@ -351,7 +312,7 @@ bool CBotProgram::GetError(CBotError& code, int& start, int& end, CBotProgram*&
////////////////////////////////////////////////////////////////////////////////
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)
{
- 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 (!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;
}
else
@@ -445,7 +407,7 @@ bool CBotProgram::RestoreState(FILE* pf)
m_pStack->SetBotCall(this); // bases for routines
// 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;
}
@@ -458,18 +420,18 @@ int CBotProgram::GetVersion()
////////////////////////////////////////////////////////////////////////////////
void CBotProgram::Init()
{
- CBotToken::DefineNum("CBotErrZeroDiv", CBotErrZeroDiv); // division by zero
- CBotToken::DefineNum("CBotErrNotInit", CBotErrNotInit); // uninitialized variable
- CBotToken::DefineNum("CBotErrBadThrow", CBotErrBadThrow); // throw a negative value
- CBotToken::DefineNum("CBotErrNoRetVal", CBotErrNoRetVal); // function did not return results
- CBotToken::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
- CBotToken::DefineNum("CBotErrNotClass", CBotErrNotClass); // Class no longer exists
- CBotToken::DefineNum("CBotErrNull", CBotErrNull); // Attempted to use a null pointer
- CBotToken::DefineNum("CBotErrNan", CBotErrNan); // Can't do operations on nan
- CBotToken::DefineNum("CBotErrOutArray", CBotErrOutArray); // Attempted access out of bounds of an array
- CBotToken::DefineNum("CBotErrStackOver", CBotErrStackOver); // Stack overflow
- CBotToken::DefineNum("CBotErrDeletedPtr", CBotErrDeletedPtr); // Attempted to use deleted object
+ CBotProgram::DefineNum("CBotErrZeroDiv", CBotErrZeroDiv); // division by zero
+ CBotProgram::DefineNum("CBotErrNotInit", CBotErrNotInit); // uninitialized variable
+ CBotProgram::DefineNum("CBotErrBadThrow", CBotErrBadThrow); // throw a negative value
+ CBotProgram::DefineNum("CBotErrNoRetVal", CBotErrNoRetVal); // function did not return results
+ CBotProgram::DefineNum("CBotErrNoRun", CBotErrNoRun); // active Run () without a function // TODO: Is this actually a runtime error?
+ CBotProgram::DefineNum("CBotErrUndefFunc", CBotErrUndefFunc); // Calling a function that no longer exists
+ CBotProgram::DefineNum("CBotErrNotClass", CBotErrNotClass); // Class no longer exists
+ CBotProgram::DefineNum("CBotErrNull", CBotErrNull); // Attempted to use a null pointer
+ CBotProgram::DefineNum("CBotErrNan", CBotErrNan); // Can't do operations on nan
+ CBotProgram::DefineNum("CBotErrOutArray", CBotErrOutArray); // Attempted access out of bounds of an array
+ CBotProgram::DefineNum("CBotErrStackOver", CBotErrStackOver); // Stack overflow
+ CBotProgram::DefineNum("CBotErrDeletedPtr", CBotErrDeletedPtr); // Attempted to use deleted object
CBotProgram::AddFunction("sizeof", rSizeOf, cSizeOf );
@@ -484,4 +446,4 @@ void CBotProgram::Free()
CBotToken::Free() ;
CBotCall ::Free() ;
CBotClass::Free() ;
-}
+}
\ No newline at end of file
diff --git a/src/CBot/CBotProgram.h b/src/CBot/CBotProgram.h
index 41b7168..5d27f92 100644
--- a/src/CBot/CBotProgram.h
+++ b/src/CBot/CBotProgram.h
@@ -86,9 +86,9 @@ public:
/**
* \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
@@ -113,6 +113,12 @@ public:
/**
* \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[out] functions Returns the names of functions declared as extern
* \param pUser Optional pointer to be passed to compile function (see AddFunction())
@@ -122,17 +128,6 @@ public:
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
* \return Error code
* \see GetError(CBotError&, int&, int&) for error location in the code
@@ -344,20 +339,18 @@ public:
private:
//! All user-defined functions
- CBotFunction* m_Prog;
+ CBotFunction* m_functions = nullptr;
//! The entry point function
- CBotFunction* m_pRun;
+ CBotFunction* m_entryPoint = nullptr;
//! Classes defined in this program
- CBotClass* m_pClass;
+ CBotClass* m_classes = nullptr;
//! Execution stack
- CBotStack* m_pStack;
+ CBotStack* m_pStack = nullptr;
//! "this" variable
- CBotVar* m_pInstance;
+ CBotVar* m_thisVar = nullptr;
friend class CBotFunction;
- CBotError m_ErrorCode;
- int m_ErrorStart;
- int m_ErrorEnd;
- //! Associated identifier
- long m_Ident;
+ CBotError m_error = CBotNoErr;
+ int m_errorStart = 0;
+ int m_errorEnd = 0;
};
diff --git a/src/CBot/CBotToken.cpp b/src/CBot/CBotToken.cpp
index ad4469c..89f87e9 100644
--- a/src/CBot/CBotToken.cpp
+++ b/src/CBot/CBotToken.cpp
@@ -17,21 +17,120 @@
* along with this program. If not, see http://gnu.org/licenses
*/
-// Modules inlcude
#include "CBot/CBotToken.h"
-#include "CBotKeywordStrings.h"
-// Local include
-
-// Global include
#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;
-int CBotToken::m_ListIdKeyWords[200];
-std::vector<std::string> CBotToken::m_ListKeyDefine;
-long CBotToken::m_ListKeyNums[MAXDEFNUM];
-
+std::map<std::string, long> CBotToken::m_defineNum;
////////////////////////////////////////////////////////////////////////////////
CBotToken::CBotToken()
{
@@ -94,7 +193,7 @@ CBotToken::~CBotToken()
////////////////////////////////////////////////////////////////////////////////
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 sep2[] = " \r\n\t"; // only separators
static char sep3[] = ",:()[]{}-+*/=;<>!~^|&%."; // operational separators
@@ -216,24 +301,23 @@ static char hexnum[] = "0123456789ABCDEFabcdef";
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 sep; // separators that are after
- char c;
- bool stop = first;
+ std::string token; // found token
+ std::string sep; // separators after the token
+ bool stop = first;
if (*program == 0) return nullptr;
- c = *(program++); // next character
+ char c = *(program++); // next character
if (!first)
{
- mot = c; // built the word
+ token = c; // built the word
c = *(program++); // next character
// special case for strings
- if ( mot[0] == '\"' )
+ if (token[0] == '\"' )
{
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 == 't' ) c = '\t';
}
- mot += c;
+ token += c;
c = *(program++);
}
if ( c == '\"' )
{
- mot += c; // string is complete
+ token += c; // string is complete
c = *(program++); // next character
}
stop = true;
}
// special case for numbers
- if ( CharInList(mot[0], num ))
+ if ( CharInList(token[0], num ))
{
bool bdot = false; // found a point?
bool bexp = false; // found an exponent?
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
liste = hexnum;
}
cw:
while (c != 0 && CharInList(c, liste))
{
-cc: mot += c;
+cc: token += c;
c = *(program++); // next character
}
if ( liste == num ) // not for hexadecimal
@@ -280,7 +364,7 @@ cc: mot += c;
if ( !bexp && ( c == 'e' || c == 'E' ) )
{
bexp = true;
- mot += c;
+ token += c;
c = *(program++); // next character
if ( c == '-' ||
c == '+' ) goto cc;
@@ -291,12 +375,12 @@ cc: mot += c;
stop = true;
}
- if (CharInList(mot[0], sep3)) // an operational separator?
+ if (CharInList(token[0], sep3)) // an operational separator?
{
- std::string motc = mot;
- while (motc += c, c != 0 && GetKeyWords(motc)>0) // operand seeks the longest possible
+ std::string motc = token;
+ 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
}
@@ -310,7 +394,7 @@ cc: mot += c;
{
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:
while (CharInList(c, sep2))
{
@@ -346,33 +430,32 @@ bis:
program--;
- CBotToken* token = new CBotToken(mot, sep);
+ CBotToken* t = new CBotToken(token, sep);
- if (CharInList( mot[0], num )) token->m_type = TokenTypNum;
- if (mot[0] == '\"') token->m_type = TokenTypString;
- if (first) token->m_type = TokenTypNone;
+ if (CharInList(token[0], num )) t->m_type = TokenTypNum;
+ if (token[0] == '\"') t->m_type = TokenTypString;
+ if (first) t->m_type = TokenTypNone;
- token->m_IdKeyWord = GetKeyWords(mot);
- if (token->m_IdKeyWord > 0) token->m_type = TokenTypKeyWord;
- else GetKeyDefNum(mot, token) ; // treats DefineNum
+ t->m_IdKeyWord = GetKeyWord(token);
+ if (t->m_IdKeyWord > 0) t->m_type = TokenTypKeyWord;
+ else GetKeyDefNum(token, t) ; // treats DefineNum
- return token;
+ return t;
}
- mot += c; // built the word
+ token += c; // built the word
c = *(program++); // next character
}
}
////////////////////////////////////////////////////////////////////////////////
-CBotToken* CBotToken::CompileTokens(const std::string& program, int& error)
+CBotToken* CBotToken::CompileTokens(const std::string& program)
{
CBotToken *nxt, *prv, *tokenbase;
- char* p = const_cast<char*> (program.c_str());
+ const char* p = program.c_str();
int pos = 0;
- error = 0;
- prv = tokenbase = NextToken(p, error, true);
+ prv = tokenbase = NextToken(p, true);
if (tokenbase == nullptr) return nullptr;
@@ -381,29 +464,19 @@ CBotToken* CBotToken::CompileTokens(const std::string& program, int& error)
tokenbase->m_end = pos;
pos += tokenbase->m_Sep.length();
- char* pp = p;
- while (nullptr != (nxt = NextToken(p, error)))
+ const char* pp = p;
+ while (nullptr != (nxt = NextToken(p, false)))
{
prv->m_next = nxt; // added after
nxt->m_prev = prv;
prv = nxt; // advance
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
nxt->m_end = pos - nxt->m_Sep.length();
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;
}
@@ -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;
- int l = m_ListKeyWords.size();
-
- if (l == 0)
- {
- LoadKeyWords(); // takes the list for the first time
- l = m_ListKeyWords.size();
- }
-
- for (i = 0; i < l; i++)
+ for (const auto& it : KEYWORDS)
{
- if (m_ListKeyWords[i] == w) return m_ListIdKeyWords[ i ];
+ if (it.second == w) return it.first;
}
return -1;
}
////////////////////////////////////////////////////////////////////////////////
-bool CBotToken::GetKeyDefNum(const std::string& w, CBotToken*& token)
-{
- int i;
- int l = m_ListKeyDefine.size();
-
- for (i = 0; i < l; i++)
- {
- if (m_ListKeyDefine[i] == w)
- {
- token->m_IdKeyWord = m_ListKeyNums[i];
- token->m_type = TokenTypDef;
- return true;
- }
- }
-
- return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-void CBotToken::LoadKeyWords()
+bool CBotToken::GetKeyDefNum(const std::string& name, CBotToken* token)
{
- 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++;
- }
+ if (m_defineNum.count(name) == 0)
+ return false;
- i = TokenKeyOp; //operators
- while (!(s = LoadString(static_cast<TokenId>(i))).empty())
- {
- m_ListKeyWords.push_back(s);
- m_ListIdKeyWords[n++] = i++;
- }
+ token->m_type = TokenTypDef;
+ token->m_IdKeyWord = m_defineNum[name];
+ return true;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotToken::DefineNum(const std::string& name, long val)
{
- int i;
- int l = m_ListKeyDefine.size();
-
- for (i = 0; i < l; i++)
+ if (m_defineNum.count(name) > 0)
{
- 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_ListKeyNums[i] = val;
+ m_defineNum[name] = val;
return true;
}
diff --git a/src/CBot/CBotToken.h b/src/CBot/CBotToken.h
index 2cdada3..6955ed6 100644
--- a/src/CBot/CBotToken.h
+++ b/src/CBot/CBotToken.h
@@ -21,11 +21,10 @@
#include <vector>
#include <string>
+#include <map>
#include "CBot/CBotEnums.h"
-#define MAXDEFNUM 1000 // limited number of DefineNum
-
/**
* \brief Class representing one token of a program.
*
@@ -166,17 +165,7 @@ public:
* \return The first token of the linked liste.
* \todo Replace the error code by an enum.
*/
- static CBotToken* CompileTokens(const std::string& p, int& error);
-
- /*!
- * \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);
+ static CBotToken* CompileTokens(const std::string& p);
/**
* \brief Delete Releases the CBotToken linked list.
@@ -201,6 +190,17 @@ public:
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:
//! The next token in the linked list
CBotToken* m_next; // following in the list
@@ -221,42 +221,23 @@ private:
//! The end position of the token in the CBotProgram
int m_end;
- /*!
- * \brief GetKeyWords Check if the word is a keyword.
- * \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?
+ //! Map of all predefined constants (see DefineNum())
+ static std::map<std::string, long> m_defineNum;
/*!
- * \brief GetKeyDefNum Check if this is a defined word and set the defined
- * word type in a CBotToken.
- * \param [in] w The word to compaire.
- * \param [out] token The token in which the type will be set.
- * \return True if the defined word is found false otherwise.
+ * \brief Check if the word is a keyword
+ * \param w The word to check
+ * \return the keyword ID, or -1 if this is not a keyword
*/
- 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
- * std::string::s_keywordString. This keywords are keywords languages (if, +,
- * for, while, case, extern ...)
- * \todo Fixme Figure out how this should work.
+ /**
+ * \brief Resolve a constant defined with DefineNum()
+ * \param name Constant name
+ * \param token Token that we are working on, will be filled with data about found constant
+ * \return true if the constant was found, false otherwise
*/
- static void LoadKeyWords();
-
- //! 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];
+ static bool GetKeyDefNum(const std::string& name, CBotToken* token);
};
@@ -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.
*/
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);
diff --git a/src/CBot/CBotVar/CBotVar.cpp b/src/CBot/CBotVar/CBotVar.cpp
index 7b15ef3..677a126 100644
--- a/src/CBot/CBotVar/CBotVar.cpp
+++ b/src/CBot/CBotVar/CBotVar.cpp
@@ -355,7 +355,7 @@ void CBotVar::SetInit(CBotVar::InitType initType)
if ( instance == nullptr )
{
instance = new CBotVarClass(nullptr, m_type);
-// instance->SetClass((static_cast<CBotVarPointer*>(this))->m_pClass);
+// instance->SetClass((static_cast<CBotVarPointer*>(this))->m_classes);
SetPointer(instance);
}
instance->SetInit(CBotVar::InitType::DEF);
diff --git a/src/CBot/CBotVar/CBotVarBoolean.cpp b/src/CBot/CBotVar/CBotVarBoolean.cpp
index a0602b8..c7bffd7 100644
--- a/src/CBot/CBotVar/CBotVarBoolean.cpp
+++ b/src/CBot/CBotVar/CBotVarBoolean.cpp
@@ -21,7 +21,6 @@
#include "CBot/CBotEnums.h"
#include "CBot/CBotUtils.h"
-#include "CBot/CBotKeywordStrings.h"
#include "CBot/CBotToken.h"
diff --git a/src/CBot/CBotVar/CBotVarFloat.cpp b/src/CBot/CBotVar/CBotVarFloat.cpp
index 0d7688a..6f93b54 100644
--- a/src/CBot/CBotVar/CBotVarFloat.cpp
+++ b/src/CBot/CBotVar/CBotVarFloat.cpp
@@ -22,7 +22,6 @@
#include "CBot/CBotEnums.h"
#include "CBot/CBotToken.h"
-#include "CBot/CBotKeywordStrings.h"
#include "CBot/CBotUtils.h"
diff --git a/src/CBot/CBotVar/CBotVarInt.cpp b/src/CBot/CBotVar/CBotVarInt.cpp
index b3fad7a..58b8cde 100644
--- a/src/CBot/CBotVar/CBotVarInt.cpp
+++ b/src/CBot/CBotVar/CBotVarInt.cpp
@@ -23,7 +23,6 @@
#include "CBot/CBotEnums.h"
#include "CBot/CBotToken.h"
#include "CBot/CBotUtils.h"
-#include "CBot/CBotKeywordStrings.h"
// Local include
diff --git a/src/CBot/CBotVar/CBotVarString.cpp b/src/CBot/CBotVar/CBotVarString.cpp
index 0dee1c5..48fb21e 100644
--- a/src/CBot/CBotVar/CBotVarString.cpp
+++ b/src/CBot/CBotVar/CBotVarString.cpp
@@ -23,7 +23,6 @@
#include "CBot/CBotEnums.h"
#include "CBot/CBotToken.h"
#include "CBot/CBotUtils.h"
-#include "CBot/CBotKeywordStrings.h"
// Local include
diff --git a/src/CBot/CMakeLists.txt b/src/CBot/CMakeLists.txt
index 62f7d72..0a89055 100644
--- a/src/CBot/CMakeLists.txt
+++ b/src/CBot/CMakeLists.txt
@@ -10,7 +10,6 @@ set(SOURCES
CBotDefParam.cpp
CBotCallMethode.cpp
CBotTypResult.cpp
- CBotKeywordStrings.cpp
CBotInstr/CBotInstr.cpp
CBotInstr/CBotInstrUtils.cpp
CBotInstr/CBotWhile.cpp
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 0627be1..3537b97 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -160,7 +160,7 @@ bool CScript::CheckToken()
CBotToken* allBt;
std::string bs;
std::string token;
- int error, cursor1, cursor2, i;
+ int cursor1, cursor2, i;
char used[100];
if ( !m_object->GetCheckToken() ) return true;
@@ -176,7 +176,7 @@ bool CScript::CheckToken()
used[i] = 0; // token not used
}
- allBt = CBotToken::CompileTokens(m_script.get(), error);
+ allBt = CBotToken::CompileTokens(m_script.get());
bt = allBt;
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());
text = text.substr(rangeStart, rangeEnd-rangeStart);
- int error;
- CBotToken* bt = CBotToken::CompileTokens(text.c_str(), error);
+ CBotToken* bt = CBotToken::CompileTokens(text.c_str());
while ( bt != nullptr )
{
std::string token = bt->GetString();
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/colobot.git
More information about the Pkg-games-commits
mailing list