void CBotStack::GetRunPos(const char* &FunctionName, int &start, int &end) { CBotProgram* prog = m_prog; // Current program CBotInstr* funct = NULL; // function found CBotInstr* instr = NULL; // the highest intruction CBotStack* p = this; while (p->m_next != NULL) { if ( p->m_instr != NULL ) instr = p->m_instr; if ( p->m_bFunc == 1 ) funct = p->m_instr; if ( p->m_next->m_prog != prog ) break ; if (p->m_next2 && p->m_next2->m_state != 0) p = p->m_next2 ; else p = p->m_next; } if ( p->m_instr != NULL ) instr = p->m_instr; if ( p->m_bFunc == 1 ) funct = p->m_instr; if ( funct == NULL ) return; CBotToken* t = funct->GetToken(); FunctionName = t->GetString(); // if ( p->m_instr != NULL ) instr = p->m_instr; t = instr->GetToken(); start = t->GetStart(); end = t->GetEnd(); }
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); }
CBotInstr* CBotClassInst::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass) { // seeks the corresponding classes if ( pClass == NULL ) { pStack->SetStartError(p->GetStart()); pClass = CBotClass::Find(p); if ( pClass == NULL ) { // not found? is bizare pStack->SetError(TX_NOCLASS, p); return NULL; } p = p->GetNext(); } bool bIntrinsic = pClass->IsIntrinsic(); CBotTypResult type = CBotTypResult( bIntrinsic ? CBotTypIntrinsic : CBotTypPointer, pClass ); CBotClassInst* inst = static_cast<CBotClassInst*>(CompileArray(p, pStack, type)); if ( inst != NULL || !pStack->IsOk() ) return inst; CBotCStack* pStk = pStack->TokenStack(); inst = new CBotClassInst(); /// \TODO Need to be revised and fixed after adding unit tests CBotToken token(pClass->GetName(), CBotString(), p->GetStart(), p->GetEnd()); inst->SetToken(&token); CBotToken* vartoken = p; if ( NULL != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) ) { (static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = type; if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable { pStk->SetStartError(vartoken->GetStart()); pStk->SetError(TX_REDEFVAR, vartoken->GetEnd()); goto error; } if (IsOfType(p, ID_OPBRK)) // with any clues? { delete inst; // is not type CBotInt p = vartoken; // returns to the variable name // compiles declaration an array inst = static_cast<CBotClassInst*>(CBotInstArray::Compile( p, pStk, type )); if (!pStk->IsOk() ) { pStk->SetError(TX_CLBRK, p->GetStart()); goto error; } goto suite; // no assignment, variable already created } CBotVar* var; var = CBotVar::Create(vartoken->GetString(), type); // creates the instance // var->SetClass(pClass); var->SetUniqNum( (static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum()); // its attribute a unique number pStack->AddVar(var); // placed on the stack // look if there are parameters inst->m_hasParams = (p->GetType() == ID_OPENPAR); CBotVar* ppVars[1000]; inst->m_Parameters = CompileParams(p, pStk, ppVars); if ( !pStk->IsOk() ) goto error; // if there are parameters, is the equivalent to the stament "new" // CPoint A ( 0, 0 ) is equivalent to // CPoint A = new CPoint( 0, 0 ) // if ( NULL != inst->m_Parameters ) if ( inst->m_hasParams ) { // the constructor is there? // CBotString noname; CBotTypResult r = pClass->CompileMethode(pClass->GetName(), var, ppVars, pStk, inst->m_nMethodeIdent); delete pStk->TokenStack(); // releases the supplement stack int typ = r.GetType(); if (typ == TX_UNDEFCALL) { // si le constructeur n'existe pas if (inst->m_Parameters != NULL) // with parameters { pStk->SetError(TX_NOCONST, vartoken); goto error; } typ = 0; } if (typ>20) { pStk->SetError(typ, vartoken->GetEnd()); goto error; } } if (IsOfType(p, ID_ASS)) // with a assignment? { if (inst->m_hasParams) { pStk->SetError(TX_ENDOF, p->GetStart()); goto error; } if ( NULL == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) ) { goto error; } CBotClass* result = pStk->GetClass(); if ( !pStk->GetTypResult(1).Eq(CBotTypNullPointer) && ( !pStk->GetTypResult(1).Eq(CBotTypPointer) || ( result != NULL && !pClass->IsChildOf(result) ))) // type compatible ? { pStk->SetError(TX_BADTYPE, p->GetStart()); goto error; } // if ( !bIntrinsic ) var->SetPointer(pStk->GetVar()->GetPointer()); if ( !bIntrinsic ) { // does not use the result on the stack, to impose the class CBotVar* pvar = CBotVar::Create("", pClass); var->SetPointer( pvar ); // variable already declared instance pointer delete pvar; // removes the second pointer } var->SetInit(true); // marks the pointer as init } else if (inst->m_hasParams) { // creates the object on the "job" (\TODO "tas") // with a pointer to the object if ( !bIntrinsic ) { CBotVar* pvar = CBotVar::Create("", pClass); var->SetPointer( pvar ); // variable already declared instance pointer delete pvar; // removes the second pointer } var->SetInit(2); // marks the pointer as init } suite: if (IsOfType(p, ID_COMMA)) // several chained definitions { if ( NULL != ( inst->m_next = CBotClassInst::Compile(p, pStk, pClass) )) // compiles the following { return pStack->Return(inst, pStk); } } if (IsOfType(p, ID_SEP)) // complete instruction { return pStack->Return(inst, pStk); } pStk->SetError(TX_ENDOF, p->GetStart()); } error: delete inst; return pStack->Return(NULL, pStk); }
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; }