void CScript::ColorizeScript(Ui::CEdit* edit) { CBotToken* bt; CBotString bs; const char* token; int error, type, cursor1, cursor2; Gfx::FontHighlight color; edit->ClearFormat(); bt = CBotToken::CompileTokens(edit->GetText(), error); while ( bt != 0 ) { bs = bt->GetString(); token = bs; type = bt->GetType(); cursor1 = bt->GetStart(); cursor2 = bt->GetEnd(); color = Gfx::FONT_HIGHLIGHT_NONE; if ( type >= TokenKeyWord && type < TokenKeyWord+100 ) { color = Gfx::FONT_HIGHLIGHT_TOKEN; } if ( type >= TokenKeyDeclare && type < TokenKeyDeclare+100 ) { color = Gfx::FONT_HIGHLIGHT_TYPE; } if ( type >= TokenKeyVal && type < TokenKeyVal+100 ) { color = Gfx::FONT_HIGHLIGHT_CONST; } if ( type == TokenTypVar ) { if ( IsType(token) ) { color = Gfx::FONT_HIGHLIGHT_TYPE; } else if ( IsFunction(token) ) { color = Gfx::FONT_HIGHLIGHT_TOKEN; } } if ( type == TokenTypDef ) { color =Gfx::FONT_HIGHLIGHT_CONST; } if ( cursor1 < cursor2 && color != Gfx::FONT_HIGHLIGHT_NONE ) { edit->SetFormat(cursor1, cursor2, color); } bt = bt->GetNext(); } CBotToken::Delete(bt); }
bool CBotProgram::Compile(const std::string& program, std::vector<std::string>& externFunctions, void* pUser) { // Cleanup the previously compiled program Stop(); for (CBotClass* c : m_classes) c->Purge(); // purge the old definitions of classes // but without destroying the object m_classes.clear(); for (CBotFunction* f : m_functions) delete f; m_functions.clear(); externFunctions.clear(); m_error = CBotNoErr; // Step 1. Process the code into tokens auto tokens = CBotToken::CompileTokens(program); if (tokens == nullptr) return false; auto pStack = std::unique_ptr<CBotCStack>(new CBotCStack(nullptr)); CBotToken* p = tokens.get()->GetNext(); // skips the first token (separator) pStack->SetProgram(this); // defined used routines m_externalCalls->SetUserPtr(pUser); // Step 2. Find all function and class definitions while ( pStack->IsOk() && p != nullptr && p->GetType() != 0) { if ( IsOfType(p, ID_SEP) ) continue; // semicolons lurking if ( p->GetType() == ID_CLASS || ( p->GetType() == ID_PUBLIC && p->GetNext()->GetType() == ID_CLASS )) { m_classes.push_back(CBotClass::Compile1(p, pStack.get())); } else { m_functions.push_back(CBotFunction::Compile1(p, pStack.get(), nullptr)); } } // Define fields and pre-compile methods for each class in this program if (pStack->IsOk()) CBotClass::DefineClasses(m_classes, pStack.get()); if ( !pStack->IsOk() ) { m_error = pStack->GetError(m_errorStart, m_errorEnd); for (CBotFunction* f : m_functions) delete f; m_functions.clear(); return false; } // Step 3. Real compilation std::list<CBotFunction*>::iterator next = m_functions.begin(); p = tokens.get()->GetNext(); // returns to the beginning while ( pStack->IsOk() && p != nullptr && p->GetType() != 0 ) { if ( IsOfType(p, ID_SEP) ) continue; // semicolons lurking if ( p->GetType() == ID_CLASS || ( p->GetType() == ID_PUBLIC && p->GetNext()->GetType() == ID_CLASS )) { CBotClass::Compile(p, pStack.get()); // completes the definition of the class } else { CBotFunction::Compile(p, pStack.get(), *next); if ((*next)->IsExtern()) externFunctions.push_back((*next)->GetName()/* + next->GetParams()*/); if ((*next)->IsPublic()) CBotFunction::AddPublic(*next); (*next)->m_pProg = this; // keeps pointers to the module ++next; } } if ( !pStack->IsOk() ) { m_error = pStack->GetError(m_errorStart, m_errorEnd); for (CBotFunction* f : m_functions) delete f; m_functions.clear(); } return !m_functions.empty(); }
bool CScript::CheckToken() { CBotToken* bt; CBotToken* allBt; CBotString bs; const char* token; int error, cursor1, cursor2, i; char used[100]; if ( !m_object->GetCheckToken() ) return true; m_error = 0; m_title[0] = 0; m_mainFunction[0] = 0; m_token[0] = 0; m_bCompile = false; for ( i=0 ; i<m_main->GetObligatoryToken() ; i++ ) { used[i] = 0; // token not used } allBt = CBotToken::CompileTokens(m_script, error); bt = allBt; while ( bt != 0 ) { bs = bt->GetString(); token = bs; cursor1 = bt->GetStart(); cursor2 = bt->GetEnd(); i = m_main->IsObligatoryToken(token); if ( i != -1 ) { used[i] = 1; // token used } if ( !m_main->IsProhibitedToken(token) ) { m_error = ERR_PROHIBITEDTOKEN; m_cursor1 = cursor1; m_cursor2 = cursor2; strcpy(m_title, "<prohibited>"); m_mainFunction[0] = 0; CBotToken::Delete(allBt); return false; } bt = bt->GetNext(); } // At least once every obligatory instruction? for ( i=0 ; i<m_main->GetObligatoryToken() ; i++ ) { if ( used[i] == 0 ) // token not used? { strcpy(m_token, m_main->GetObligatoryToken(i)); m_error = ERR_OBLIGATORYTOKEN; strcpy(m_title, "<obligatory>"); m_mainFunction[0] = 0; CBotToken::Delete(allBt); return false; } } CBotToken::Delete(allBt); return true; }