CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack) { CBotCStack* pStk = pStack->TokenStack(); pStk->SetStartError(p->GetStart()); // is it an expression in parentheses? if (IsOfType(p, ID_OPENPAR)) { CBotInstr* inst = CBotExpression::Compile(p, pStk); if (nullptr != inst) { if (IsOfType(p, ID_CLOSEPAR)) { return pStack->Return(inst, pStk); } pStk->SetError(CBotErrClosePar, p->GetStart()); } delete inst; return pStack->Return(nullptr, pStk); } // is this a unary operation? CBotInstr* inst = CBotExprUnaire::Compile(p, pStk); if (inst != nullptr || !pStk->IsOk()) return pStack->Return(inst, pStk); // is it a variable name? if (p->GetType() == TokenTypVar) { // this may be a method call without the "this." before inst = CBotExprVar::CompileMethode(p, pStk); if (inst != nullptr) return pStack->Return(inst, pStk); // is it a procedure call? inst = CBotInstrCall::Compile(p, pStk); if (inst != nullptr || !pStk->IsOk()) return pStack->Return(inst, pStk); CBotToken* pvar = p; // no, it an "ordinaty" variable inst = CBotExprVar::Compile(p, pStk); CBotToken* pp = p; // post incremented or decremented? if (IsOfType(p, ID_INC, ID_DEC)) { if (pStk->GetType() >= CBotTypBoolean) { pStk->SetError(CBotErrBadType1, pp); delete inst; return pStack->Return(nullptr, pStk); } // recompile the variable for read-only delete inst; p = pvar; inst = CBotExprVar::Compile(p, pStk, CBotVar::ProtectionLevel::ReadOnly); p = p->GetNext(); CBotPostIncExpr* i = new CBotPostIncExpr(); i->SetToken(pp); i->m_instr = inst; // associated statement return pStack->Return(i, pStk); } return pStack->Return(inst, pStk); } // pre increpemted or pre decremented? CBotToken* pp = p; if (IsOfType(p, ID_INC, ID_DEC)) { CBotPreIncExpr* i = new CBotPreIncExpr(); i->SetToken(pp); if (p->GetType() == TokenTypVar) { if (nullptr != (i->m_instr = CBotExprVar::Compile(p, pStk, CBotVar::ProtectionLevel::ReadOnly))) { if (pStk->GetType() >= CBotTypBoolean) { pStk->SetError(CBotErrBadType1, pp); delete inst; return pStack->Return(nullptr, pStk); } return pStack->Return(i, pStk); } delete i; return pStack->Return(nullptr, pStk); } } // is it a number or DefineNum? if (p->GetType() == TokenTypNum || p->GetType() == TokenTypDef ) { CBotInstr* inst = CBotExprLitNum::Compile(p, pStk); return pStack->Return(inst, pStk); } // is this a chaine? if (p->GetType() == TokenTypString) { CBotInstr* inst = CBotExprLitString::Compile(p, pStk); return pStack->Return(inst, pStk); } // is a "true" or "false" if (p->GetType() == ID_TRUE || p->GetType() == ID_FALSE ) { CBotInstr* inst = CBotExprLitBool::Compile(p, pStk); return pStack->Return(inst, pStk); } // is an object to be created with new if (p->GetType() == ID_NEW) { CBotInstr* inst = CBotNew::Compile(p, pStk); return pStack->Return(inst, pStk); } // is a null pointer if (IsOfType(p, ID_NULL)) { CBotInstr* inst = new CBotExprLitNull(); inst->SetToken(pp); CBotVar* var = CBotVar::Create("", CBotTypNullPointer); pStk->SetVar(var); return pStack->Return(inst, pStk); } // is a number nan if (IsOfType(p, ID_NAN)) { CBotInstr* inst = new CBotExprLitNan(); inst->SetToken(pp); CBotVar* var = CBotVar::Create("", CBotTypInt); var->SetInit(CBotVar::InitType::IS_NAN); pStk->SetVar(var); return pStack->Return(inst, pStk); } return pStack->Return(nullptr, pStk); }
CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack) { CBotSwitch* inst = new CBotSwitch(); // creates the object CBotToken* pp = p; // preserves at the ^ token (starting position) inst->SetToken(p); if (!IsOfType(p, ID_SWITCH)) return nullptr; // should never happen CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp if ( IsOfType(p, ID_OPENPAR ) ) { if ( nullptr != (inst->m_Value = CBotExpression::Compile( p, pStk )) ) { if ( pStk->GetType() < CBotTypLong ) { if ( IsOfType(p, ID_CLOSEPAR ) ) { if ( IsOfType(p, ID_OPBLK ) ) { IncLvl(); while( !IsOfType( p, ID_CLBLK ) ) { if ( p->GetType() == ID_CASE || p->GetType() == ID_DEFAULT) { CBotCStack* pStk2 = pStk->TokenStack(p); // un petit bout de pile svp CBotInstr* i = CBotCase::Compile( p, pStk2 ); if (i == nullptr) { delete inst; return pStack->Return(nullptr, pStk2); } delete pStk2; if ( inst->m_Block == nullptr ) inst->m_Block = i; else inst->m_Block->AddNext(i); continue; } if ( inst->m_Block == nullptr ) { pStk->SetError(TX_NOCASE, p->GetStart()); delete inst; return pStack->Return(nullptr, pStk); } CBotInstr* i = CBotBlock::CompileBlkOrInst( p, pStk, true ); if ( !pStk->IsOk() ) { delete inst; return pStack->Return(nullptr, pStk); } inst->m_Block->AddNext(i); if ( p == nullptr ) { pStk->SetError(TX_CLOSEBLK, -1); delete inst; return pStack->Return(nullptr, pStk); } } DecLvl(); if ( inst->m_Block == nullptr ) { pStk->SetError(TX_NOCASE, p->GetStart()); delete inst; return pStack->Return(nullptr, pStk); } // the statement block is ok return pStack->Return(inst, pStk); // return an object to the application } pStk->SetError( TX_OPENBLK, p->GetStart() ); } pStk->SetError( TX_CLOSEPAR, p->GetStart() ); } pStk->SetError( TX_BADTYPE, p->GetStart() ); } } pStk->SetError( TX_OPENPAR, p->GetStart()); delete inst; // error, frees up return pStack->Return(nullptr, pStk); // no object, the error is on the stack }
CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMethodsOnly) { if (p->GetType() == ID_DOT) { CBotVar* var = pStack->GetVar(); if (var == nullptr) return nullptr; CBotCStack* pStk = pStack->TokenStack(); CBotInstr* inst = new CBotExprRetVar(); while (true) { pStk->SetStartError(p->GetStart()); if (var->GetType() == CBotTypArrayPointer) { if (bMethodsOnly) goto err; if (IsOfType( p, ID_OPBRK )) { CBotIndexExpr* i = new CBotIndexExpr(); i->m_expr = CBotExpression::Compile(p, pStk); inst->AddNext3(i); var = var->GetItem(0,true); if (i->m_expr == nullptr || pStk->GetType() != CBotTypInt) { pStk->SetError(CBotErrBadIndex, p->GetStart()); goto err; } if (!pStk->IsOk() || !IsOfType( p, ID_CLBRK )) { pStk->SetError(CBotErrCloseIndex, p->GetStart()); goto err; } continue; } } if (var->GetType(CBotVar::GetTypeMode::CLASS_AS_POINTER) == CBotTypPointer) { if (IsOfType(p, ID_DOT)) { CBotToken* pp = p; if (p->GetType() == TokenTypVar) { if (p->GetNext()->GetType() == ID_OPENPAR) { CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var, bMethodsOnly); if (!pStk->IsOk()) goto err; inst->AddNext3(i); return pStack->Return(inst, pStk); } else if (bMethodsOnly) { p = p->GetPrev(); goto err; } else { CBotFieldExpr* i = new CBotFieldExpr(); i->SetToken(pp); inst->AddNext3(i); CBotVar* preVar = var; var = var->GetItem(p->GetString()); if (var != nullptr) { i->SetUniqNum(var->GetUniqNum()); if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var)) { pStk->SetError(CBotErrPrivate, pp); goto err; } } } if (var != nullptr) { p = p->GetNext(); continue; } pStk->SetError(CBotErrUndefItem, p); goto err; } pStk->SetError(CBotErrUndefClass, p); goto err; } } break; } pStk->SetCopyVar(var); if (pStk->IsOk()) return pStack->Return(inst, pStk); pStk->SetError(CBotErrUndefVar, p); err: delete inst; return pStack->Return(nullptr, pStk); } return nullptr; }
CBotInstr* CBotDefArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type) { CBotCStack* pStk = pStack->TokenStack(p); CBotDefArray* inst = new CBotDefArray(); CBotToken* vartoken = p; inst->SetToken(vartoken); // determinse the expression is valid for the item on the left side if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk ))) { if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable? { pStk->SetError(CBotErrRedefVar, vartoken); goto error; } CBotInstr* i; while (IsOfType(p, ID_OPBRK)) { pStk->SetStartError(p->GetStart()); if (p->GetType() != ID_CLBRK) { i = CBotExpression::Compile(p, pStk); // expression for the value if (i == nullptr || pStk->GetType() != CBotTypInt) // must be a number { pStk->SetError(CBotErrBadIndex, p->GetStart()); goto error; } } else i = new CBotEmpty(); // if no special formula inst->AddNext3b(i); // construct a list type = CBotTypResult(CBotTypArrayPointer, type); if (IsOfType(p, ID_CLBRK)) continue; pStk->SetError(CBotErrCloseIndex, p->GetStart()); goto error; } CBotVar* var = CBotVar::Create(*vartoken, type); // create an instance inst->m_typevar = type; var->SetUniqNum( (static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum()); pStack->AddVar(var); // place it on the stack if (IsOfType(p, ID_ASS)) // with an assignment { pStk->SetStartError(p->GetStart()); if ( IsOfType(p, ID_SEP) ) { pStk->SetError(CBotErrNoExpression, p->GetPrev()); goto error; } if ( nullptr == (inst->m_listass = CBotListArray::Compile(p, pStk, type.GetTypElem())) ) { if (pStk->IsOk()) { inst->m_listass = CBotTwoOpExpr::Compile(p, pStk); if (inst->m_listass == nullptr || !pStk->GetTypResult().Compare(type)) // compatible type ? { pStk->SetError(CBotErrBadType1, p->GetStart()); goto error; } } } if (pStk->IsOk()) while (true) // mark initialized { var = var->GetItem(0, true); if (var == nullptr) break; if (var->GetType() == CBotTypArrayPointer) continue; if (var->GetType() <= CBotTypString) var->SetInit(CBotVar::InitType::DEF); break; } } if (pStk->IsOk()) return pStack->Return(inst, pStk); } error: delete inst; return pStack->Return(nullptr, pStk); }