コード例 #1
0
ファイル: CBotWhile.cpp プロジェクト: BTML/colobot
CBotInstr* CBotTry::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotTry*    inst = new CBotTry();           // creates the object
    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)

    inst->SetToken(p);
    if (!IsOfType(p, ID_TRY)) return nullptr;      // should never happen

    CBotCStack* pStk = pStack->TokenStack(pp);  // un petit bout de pile svp

    inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk );
    CBotCatch** pn = &inst->m_ListCatch;

    while (pStk->IsOk() && p->GetType() == ID_CATCH)
    {
        CBotCatch*  i = CBotCatch::Compile(p, pStk);
        *pn = i;
        pn = &i->m_next;
    }

    if (pStk->IsOk() && IsOfType( p, ID_FINALLY) )
    {
        inst->m_FinalInst = CBotBlock::CompileBlkOrInst( p, pStk );
    }

    if (pStk->IsOk())
    {
        return pStack->Return(inst, pStk);  // return an object to the application
    }

    delete inst;                                // error, frees up
    return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
}
コード例 #2
0
ファイル: CBotFunction.cpp プロジェクト: PaweX/colobot
CBotInstr* CBotReturn::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotToken*  pp = p;

    if (!IsOfType(p, ID_RETURN)) return NULL;   // should never happen

    CBotReturn* inst = new CBotReturn();        // creates the object
    inst->SetToken( pp );

    CBotTypResult   type = pStack->GetRetType();

    if ( type.GetType() == 0 )                  // returned void ?
    {
        if ( IsOfType( p, ID_SEP ) ) return inst;
        pStack->SetError( TX_BADTYPE, pp );
        return NULL;
    }

    inst->m_Instr = CBotExpression::Compile(p, pStack);
    if ( pStack->IsOk() )
    {
        CBotTypResult   retType = pStack->GetTypResult(2);
        if (TypeCompatible(retType, type, ID_ASS)) 
        {
            if ( IsOfType( p, ID_SEP ) )
                return inst;

            pStack->SetError(TX_ENDOF, p->GetStart());
        }
        pStack->SetError(TX_BADTYPE, p->GetStart());
    }

    delete inst;
    return NULL;                            // no object, the error is on the stack
}
コード例 #3
0
ファイル: CBotWhile.cpp プロジェクト: BTML/colobot
CBotCatch* CBotCatch::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotCatch*  inst = new CBotCatch();         // creates the object
    pStack->SetStartError(p->GetStart());

    inst->SetToken(p);
    if (!IsOfType(p, ID_CATCH)) return nullptr;    // should never happen

    if (IsOfType(p, ID_OPENPAR))
    {
        inst->m_Cond = CBotExpression::Compile(p, pStack);
        if (( pStack->GetType() < CBotTypLong ||
              pStack->GetTypResult().Eq(CBotTypBoolean) )&& pStack->IsOk() )
        {
            if (IsOfType(p, ID_CLOSEPAR))
            {
                inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStack );
                if ( pStack->IsOk() )
                    return inst;                // return an object to the application
            }
            pStack->SetError(TX_CLOSEPAR, p->GetStart());
        }
        pStack->SetError(TX_BADTYPE, p->GetStart());
    }
    pStack->SetError(TX_OPENPAR, p->GetStart());
    delete inst;                                // error, frees up
    return nullptr;                                // no object, the error is on the stack
}
コード例 #4
0
ファイル: CBotListInstr.cpp プロジェクト: 2asoft/colobot
CBotInstr* CBotListInstr::Compile(CBotToken* &p, CBotCStack* pStack, bool bLocal)
{
    CBotCStack* pStk = pStack->TokenStack(p, bLocal);        // variables are local

    CBotListInstr* inst = new CBotListInstr();

    while (true)
    {
        if (p == nullptr) break;

        if (IsOfType(p, ID_SEP)) continue;              // empty statement ignored
        if (p->GetType() == ID_CLBLK) break;

        if (IsOfType(p, 0))
        {
            pStack->SetError(CBotErrCloseBlock, p->GetStart());
            delete inst;
            return pStack->Return(nullptr, pStk);
        }

        CBotInstr* i = CBotBlock::CompileBlkOrInst(p, pStk);    // compiles next

        if (!pStk->IsOk())
        {
            delete inst;
            return pStack->Return(nullptr, pStk);
        }

        if (inst->m_instr == nullptr) inst->m_instr = i;
        else inst->m_instr->AddNext(i);                            // added a result
    }
    return pStack->Return(inst, pStk);
}
コード例 #5
0
ファイル: CBotWhile.cpp プロジェクト: BTML/colobot
CBotInstr* CBotCase::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotCase*   inst = new CBotCase();          // creates the object
    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)

    inst->SetToken(p);
    if (!IsOfType(p, ID_CASE, ID_DEFAULT)) return nullptr;     // should never happen

    if ( pp->GetType() == ID_CASE )
    {
        pp = p;
        inst->m_Value = CBotExprNum::Compile(p, pStack);
        if ( inst->m_Value == nullptr )
        {
            pStack->SetError( TX_BADNUM, pp );
            delete inst;
            return nullptr;
        }
    }
    if ( !IsOfType( p, ID_DOTS ))
    {
        pStack->SetError( TX_MISDOTS, p->GetStart() );
        delete inst;
        return nullptr;
    }

    return inst;
}
コード例 #6
0
ファイル: CBotFunction.cpp プロジェクト: PaweX/colobot
// compiles a list of parameters
CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
{
    // mainly not pStack->TokenStack here
    // declared variables must remain visible thereafter

    pStack->SetStartError(p->GetStart());

    if (IsOfType(p, ID_OPENPAR))
    {
        CBotDefParam* list = NULL;
    
        while (!IsOfType(p, ID_CLOSEPAR))
        {
            CBotDefParam* param = new CBotDefParam();
            if (list == NULL) list = param;
            else list->AddNext(param);          // added to the list

//            CBotClass*  pClass = NULL;//= CBotClass::Find(p);
            param->m_typename = p->GetString();
            CBotTypResult type = param->m_type = TypeParam(p, pStack);
//          if ( type == CBotTypPointer ) type = CBotTypClass;          // we must create a new object

            if (param->m_type.GetType() > 0)
            {
                CBotToken*  pp = p;
                param->m_token = *p;
                if (pStack->IsOk() && IsOfType(p, TokenTypVar) )
                {

                    // variable already declared?
                    if (pStack->CheckVarLocal(pp))
                    {
                        pStack->SetError(TX_REDEFVAR, pp);
                        break;
                    }

                    if ( type.Eq(CBotTypArrayPointer) ) type.SetType(CBotTypArrayBody);
                    CBotVar*    var = CBotVar::Create(pp->GetString(), type);       // creates the variable
//                  if ( pClass ) var->SetClass(pClass);
                    var->SetInit(2);                                    // mark initialized
                    param->m_nIdent = CBotVar::NextUniqNum();
                    var->SetUniqNum(param->m_nIdent);
                    pStack->AddVar(var);                                // place on the stack

                    if (IsOfType(p, ID_COMMA) || p->GetType() == ID_CLOSEPAR)
                        continue;
                }
                pStack->SetError(TX_CLOSEPAR, p->GetStart());
            }
            pStack->SetError(TX_NOTYP, p);
            delete list;
            return NULL;
        }
        return list;
    }
    pStack->SetError(TX_OPENPAR, p->GetStart());
    return NULL;
}
コード例 #7
0
ファイル: CBotInstrUtils.cpp プロジェクト: Grunaka/colobot
CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars)
{
    bool        first = true;
    CBotInstr*    ret = nullptr;   // to return to the list

    CBotCStack*    pile = pStack;
    int            i = 0;

    if (IsOfType(p, ID_OPENPAR))
    {
        int    start, end;
        if (!IsOfType(p, ID_CLOSEPAR)) while (true)
        {
            start = p->GetStart();
            pile = pile->TokenStack();  // keeps the result on the stack

            if (first) pStack->SetStartError(start);
            first = false;

            CBotInstr*    param = CBotExpression::Compile(p, pile);
            end      = p->GetStart();

            if (!pile->IsOk())
            {
                return pStack->Return(nullptr, pile);
            }

            if (ret == nullptr) ret = param;
            else ret->AddNext(param);   // construct the list

            if (param != nullptr)
            {
                if (pile->GetTypResult().Eq(99))
                {
                    delete pStack->TokenStack();
                    pStack->SetError(CBotErrVoid, p->GetStart());
                    return nullptr;
                }
                ppVars[i] = pile->GetVar();
                ppVars[i]->GetToken()->SetPos(start, end);
                i++;

                if (IsOfType(p, ID_COMMA)) continue;    // skips the comma
                if (IsOfType(p, ID_CLOSEPAR)) break;
            }

            pStack->SetError(CBotErrClosePar, p->GetStart());
            delete pStack->TokenStack();
            return nullptr;
        }
    }
    ppVars[i] = nullptr;
    return    ret;
}
コード例 #8
0
ファイル: CBotUtils.cpp プロジェクト: CHmSID/colobot
CBotTypResult ArrayType(CBotToken* &p, CBotCStack* pile, CBotTypResult type)
{
    while ( IsOfType( p, ID_OPBRK ) )
    {
        if ( !IsOfType( p, ID_CLBRK ) )
        {
            pile->SetError(CBotErrCloseIndex, p->GetStart());
            return CBotTypResult( -1 );
        }
        type = CBotTypResult( CBotTypArrayPointer, type );
    }
    return type;
}
コード例 #9
0
TEST_F(WorldChunkTests,PlacedCubeIsSaved)
{
    // Set three cubes
    pChunk->put( CubeData( EMATERIAL_GRASS ), Point( 2, 5, 6 ) );
    pChunk->put( CubeData( EMATERIAL_WOOD ), Point( 24, 5, 0 ) );
    pChunk->put( CubeData( EMATERIAL_ROCK ), Point( 31, 0, 12 ) );

    // Check type, make sure set (in random order)
    EXPECT_FALSE( IsOfType( pChunk, EMATERIAL_DIRT, Point( 24, 5, 0 ) ) );

    EXPECT_TRUE(  IsOfType( pChunk, EMATERIAL_WOOD, Point( 24, 5, 0 ) ) );
    EXPECT_TRUE(  IsOfType( pChunk, EMATERIAL_ROCK, Point( 31, 0, 12 ) ) );
    EXPECT_TRUE(  IsOfType( pChunk, EMATERIAL_GRASS, Point( 2, 5, 6 ) ) );
}
コード例 #10
0
ファイル: CBotWhile.cpp プロジェクト: BTML/colobot
CBotInstr* CBotStartDebugDD::Compile(CBotToken* &p, CBotCStack* pStack)
{

    if (!IsOfType(p, ID_DEBUGDD)) return nullptr;  // should never happen

    return new CBotStartDebugDD();          // creates the object

}
コード例 #11
0
ファイル: CBotWhile.cpp プロジェクト: BTML/colobot
CBotInstr* CBotFor::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotFor*    inst = new CBotFor();           // creates the object
    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)

    if ( IsOfType( p, TokenTypVar ) &&
         IsOfType( p, ID_DOTS ) )
    {
        inst->m_label = pp->GetString();        // register the name of label
    }

    inst->SetToken(p);
    if (!IsOfType(p, ID_FOR)) return nullptr;      // should never happen

    if ( !IsOfType(p, ID_OPENPAR))              // missing parenthesis ?
    {
        pStack->SetError(TX_OPENPAR, p->GetStart());
        return nullptr;
    }

    CBotCStack* pStk = pStack->TokenStack(pp, true);    // un petit bout de pile svp

    // compiles instructions for initialization
    inst->m_Init = CBotListExpression::Compile( p, pStk );
    if ( pStk->IsOk() )
    {
        if ( !IsOfType(p, ID_SEP))                      // lack the semicolon?
        {
            pStack->SetError(TX_OPENPAR, p->GetStart());
            delete inst;
            return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
        }
        inst->m_Test = CBotBoolExpr::Compile( p, pStk );
        if ( pStk->IsOk() )
        {
            if ( !IsOfType(p, ID_SEP))                      // lack the semicolon?
            {
                pStack->SetError(TX_OPENPAR, p->GetStart());
                delete inst;
                return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
            }
            inst->m_Incr = CBotListExpression::Compile( p, pStk );
            if ( pStk->IsOk() )
            {
                if ( IsOfType(p, ID_CLOSEPAR))              // missing parenthesis ?
                {
                    IncLvl(inst->m_label);
                    inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, true );
                    DecLvl();
                    if ( pStk->IsOk() )
                        return pStack->Return(inst, pStk);;
                }
                pStack->SetError(TX_CLOSEPAR, p->GetStart());
            }
        }
    }

    delete inst;                                // error, frees up
    return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
}
コード例 #12
0
ファイル: CBotFunction.cpp プロジェクト: PaweX/colobot
CBotClass* CBotClass::Compile(CBotToken* &p, CBotCStack* pStack)
{
    if ( !IsOfType(p, ID_PUBLIC) ) return NULL;
    if ( !IsOfType(p, ID_CLASS) ) return NULL;

    CBotString name = p->GetString();

    // a name for the class is there?
    if (IsOfType(p, TokenTypVar))
    {
        // the class was created by Compile1
        CBotClass* pOld = CBotClass::Find(name);

        if ( IsOfType( p, ID_EXTENDS ) )
        {
            IsOfType(p, TokenTypVar); // necessarily
        }
        IsOfType( p, ID_OPBLK); // necessarily

        while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) )
        {
            pOld->CompileDefItem(p, pStack, true);
        }

        pOld->m_IsDef = true;           // complete definition
        if (pStack->IsOk()) return pOld;
    }
    pStack->SetError(TX_ENDOF, p);
    return NULL;
}
コード例 #13
0
ファイル: CBotIf.cpp プロジェクト: Programerus/colobot
CBotInstr* CBotIf::Compile(CBotToken* &p, CBotCStack* pStack)
{
	CBotToken*	pp = p;							// conserve le ^au token (début instruction)

	if (!IsOfType(p, ID_IF)) return NULL;		// ne doit jamais arriver

	CBotCStack* pStk = pStack->TokenStack(pp);	// un petit bout de pile svp

	CBotIf*	inst = new CBotIf();				// crée l'object
	inst->SetToken( pp );

	if ( NULL != (inst->m_Condition = CBotCondition::Compile( p, pStk )) )
	{
		// la condition existe bel et bien

		inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, TRUE );
		if ( pStk->IsOk() )
		{
			// le bloc d'instruction est ok (peut être vide)

			// regarde si l'instruction suivante est le token "else"
			if (IsOfType(p, ID_ELSE))
			{
				// si oui, compile le bloc d'instruction qui suit
				inst->m_BlockElse = CBotBlock::CompileBlkOrInst( p, pStk, TRUE );
				if (!pStk->IsOk())
				{
					// il n'y a pas de bloc correct après le else
					// libère l'objet, et transmet l'erreur qui est sur la pile
					delete inst;
					return pStack->Return(NULL, pStk);
				}
			}

			// rend l'object correct à qui le demande.
			return pStack->Return(inst, pStk);
		}
	}

	// erreur, libère l'objet
	delete inst;
	// et transmet l'erreur qui se trouve sur la pile.
	return pStack->Return(NULL, pStk);
}
コード例 #14
0
ファイル: CBotIf.cpp プロジェクト: 2asoft/colobot
CBotInstr* CBotIf::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotToken*  pp = p;                         // preserves at the ^ token (starting instruction)

    if (!IsOfType(p, ID_IF)) return nullptr;       // should never happen

    CBotCStack* pStk = pStack->TokenStack(pp);  // un petit bout de pile svp

    CBotIf* inst = new CBotIf();                // create the object
    inst->SetToken( pp );

    if ( nullptr != (inst->m_condition = CBotCondition::Compile(p, pStk )) )
    {
        // the condition does exist

        inst->m_block = CBotBlock::CompileBlkOrInst(p, pStk, true );
        if ( pStk->IsOk() )
        {
            // the statement block is ok (can be empty)

            // see if the next instruction is the token "else"
            if (IsOfType(p, ID_ELSE))
            {
                // if so, compiles the following statement block
                inst->m_blockElse = CBotBlock::CompileBlkOrInst(p, pStk, true );
                if (!pStk->IsOk())
                {
                    // there is no correct block after the else
                    // frees the object, and transmits the error that is on the stack
                    delete inst;
                    return pStack->Return(nullptr, pStk);
                }
            }

            // return the corrent object to the application
            return pStack->Return(inst, pStk);
        }
    }

    // error, frees the object
    delete inst;
    // and transmits the error that is on the stack.
    return pStack->Return(nullptr, pStk);
}
コード例 #15
0
ファイル: CBotWhile.cpp プロジェクト: BTML/colobot
CBotInstr* CBotDo::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotDo* inst = new CBotDo();                // creates the object

    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)

    if ( IsOfType( p, TokenTypVar ) &&
         IsOfType( p, ID_DOTS ) )
    {
        inst->m_label = pp->GetString();        // register the name of label
    }

    inst->SetToken(p);
    if (!IsOfType(p, ID_DO)) return nullptr;       // should never happen

    CBotCStack* pStk = pStack->TokenStack(pp);  // un petit bout de pile svp


    // looking for a statement block after the do
    IncLvl(inst->m_label);
    inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, true );
    DecLvl();

    if ( pStk->IsOk() )
    {
        if (IsOfType(p, ID_WHILE))
        {
            if ( nullptr != (inst->m_Condition = CBotCondition::Compile( p, pStk )) )
            {
                // the condition exists
                if (IsOfType(p, ID_SEP))
                {
                    return pStack->Return(inst, pStk);  // return an object to the application
                }
                pStk->SetError(TX_ENDOF, p->GetStart());
            }
        }
        pStk->SetError(TX_WHILE, p->GetStart());
    }

    delete inst;                                // error, frees up
    return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
}
コード例 #16
0
ファイル: CBotBlock.cpp プロジェクト: CHmSID/colobot
CBotInstr* CBotBlock::Compile(CBotToken* &p, CBotCStack* pStack, bool bLocal)
{
    pStack->SetStartError(p->GetStart());

    if (IsOfType(p, ID_OPBLK))
    {
        CBotInstr* inst = CBotListInstr::Compile(p, pStack, bLocal);

        if (IsOfType(p, ID_CLBLK))
        {
            return inst;
        }

        pStack->SetError(CBotErrCloseBlock, p->GetStart());    // missing parenthesis
        delete inst;
        return nullptr;
    }

    pStack->SetError(CBotErrOpenBlock, p->GetStart());
    return nullptr;
}
コード例 #17
0
ファイル: CBotFunction.cpp プロジェクト: PaweX/colobot
CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
{
    if ( !IsOfType(p, ID_PUBLIC) )
    {
        pStack->SetError(TX_NOPUBLIC, p);
        return NULL;
    }
    
    if ( !IsOfType(p, ID_CLASS) ) return NULL;

    CBotString name = p->GetString();

    CBotClass* pOld = CBotClass::Find(name);
    if ( pOld != NULL && pOld->m_IsDef )
    {
        pStack->SetError( TX_REDEFCLASS, p );
        return NULL;
    }

    // a name of the class is there?
    if (IsOfType(p, TokenTypVar))
    {
        CBotClass* pPapa = NULL;
        if ( IsOfType( p, ID_EXTENDS ) )
        {
            CBotString name = p->GetString();
            pPapa = CBotClass::Find(name);

            if (!IsOfType(p, TokenTypVar) || pPapa == NULL )
            {
                pStack->SetError( TX_NOCLASS, p );
                return NULL;
            }
        }
        CBotClass* classe = (pOld == NULL) ? new CBotClass(name, pPapa) : pOld;
        classe->Purge();                            // emptythe old definitions
        classe->m_IsDef = false;                    // current definition

        if ( !IsOfType( p, ID_OPBLK) )
        {
            pStack->SetError(TX_OPENBLK, p);
            return NULL;
        }

        while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) )
        {
            classe->CompileDefItem(p, pStack, false);
        }

        if (pStack->IsOk()) return classe;
    }
    pStack->SetError(TX_ENDOF, p);
    return NULL;
}
コード例 #18
0
ファイル: CBotWhile.cpp プロジェクト: 2asoft/colobot
CBotInstr* CBotWhile::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotWhile*  inst = new CBotWhile();         // creates the object
    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)

    if ( IsOfType( p, TokenTypVar ) &&
         IsOfType( p, ID_DOTS ) )
    {
        inst->m_label = pp->GetString();        // records the name of the label
    }

    inst->SetToken(p);
    if (!IsOfType(p, ID_WHILE)) return nullptr;    // should never happen

    CBotCStack* pStk = pStack->TokenStack(pp);  // un petit bout de pile svp
                                                // a bit of battery please (??)

    if ( nullptr != (inst->m_condition = CBotCondition::Compile(p, pStk )) )
    {
        // the condition exists

        IncLvl(inst->m_label);
        inst->m_block = CBotBlock::CompileBlkOrInst(p, pStk, true );
        DecLvl();

        if ( pStk->IsOk() )
        {
            // the statement block is ok (it may be empty!

            return pStack->Return(inst, pStk);  // return an object to the application
                                                // makes the object to which the application
        }
    }

    delete inst;                                // error, frees the place
    return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
}
コード例 #19
0
ファイル: CBotWhile.cpp プロジェクト: BTML/colobot
CBotInstr* CBotBreak::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)
    int type = p->GetType();

    if (!IsOfType(p, ID_BREAK, ID_CONTINUE)) return nullptr;   // should never happen

    if ( !ChkLvl(CBotString(), type ) )
    {
        pStack->SetError(TX_BREAK, pp);
        return nullptr;                            // no object, the error is on the stack
    }

    CBotBreak*  inst = new CBotBreak();         // creates the object
    inst->SetToken(pp);                         // keeps the operation

    pp = p;
    if ( IsOfType( p, TokenTypVar ) )
    {
        inst->m_label = pp->GetString();        // register the name of label
        if ( !ChkLvl(inst->m_label, type ) )
        {
            delete inst;
            pStack->SetError(TX_NOLABEL, pp);
            return nullptr;                            // no object, the error is on the stack
        }
    }

    if (IsOfType(p, ID_SEP))
    {
        return  inst;                           // return what it wants
    }
    delete inst;

    pStack->SetError(TX_ENDOF, p->GetStart());
    return nullptr;                            // no object, the error is on the stack
}
コード例 #20
0
ファイル: CBotWhile.cpp プロジェクト: BTML/colobot
CBotInstr* CBotThrow::Compile(CBotToken* &p, CBotCStack* pStack)
{
    pStack->SetStartError(p->GetStart());

    CBotThrow*  inst = new CBotThrow();         // creates the object
    inst->SetToken(p);

    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)

    if (!IsOfType(p, ID_THROW)) return nullptr;    // should never happen

    inst->m_Value = CBotExpression::Compile( p, pStack );

    if (pStack->GetType() < CBotTypLong && pStack->IsOk())
    {
        return inst;                            // return an object to the application
    }
    pStack->SetError(TX_BADTYPE, pp);

    delete inst;                                // error, frees up
    return nullptr;                                // no object, the error is on the stack
}
コード例 #21
0
ファイル: CBotWhile.cpp プロジェクト: BTML/colobot
CBotInstr* CBotListExpression::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotListExpression* inst = new CBotListExpression();

    inst->m_Expr = CompileInstrOrDefVar( p, pStack );           // compile the first expression in a list
    if (pStack->IsOk())
    {
        while ( IsOfType(p, ID_COMMA) )                         // more instructions?
        {
            CBotInstr*  i = CompileInstrOrDefVar( p, pStack );      // Is this a declaration of an integer?
            inst->m_Expr->AddNext(i);                           // added after
            if ( !pStack->IsOk() )
            {
                delete inst;
                return nullptr;                                    // no object, the error is on the stack
            }
        }
        return inst;
    }
    delete inst;
    return nullptr;
}
コード例 #22
0
ファイル: LuaInstance.cpp プロジェクト: MrFraggy/NazaraEngine
bool NzLuaInstance::IsOfType(int index, const NzString& tname) const
{
	return IsOfType(index, tname.GetConstBuffer());
}
コード例 #23
0
	bool LuaState::IsOfType(int index, const String& tname) const
	{
		return IsOfType(index, tname.GetConstBuffer());
	}
コード例 #24
0
ファイル: CBotNew.cpp プロジェクト: 2asoft/colobot
CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotToken* pp = p;
    if (!IsOfType(p, ID_NEW)) return nullptr;

    // verifies that the token is a class name
    if (p->GetType() != TokenTypVar)
    {
        pStack->SetError(CBotErrBadNew, p);
        return nullptr;
    }

    CBotClass* pClass = CBotClass::Find(p);
    if (pClass == nullptr)
    {
        pStack->SetError(CBotErrBadNew, p);
        return nullptr;
    }

    CBotNew* inst = new CBotNew();
    inst->SetToken(pp);

    inst->m_vartoken = *p;
    p = p->GetNext();

    // creates the object on the stack
    // with a pointer to the object
    CBotVar*    pVar = CBotVar::Create("", pClass);

    // do the call of the creator
    CBotCStack* pStk = pStack->TokenStack();
    {
        // check if there are parameters
        CBotVar*    ppVars[1000];
        inst->m_parameters = CompileParams(p, pStk, ppVars);
        if (!pStk->IsOk()) goto error;

        // constructor exist?
        CBotTypResult r = pClass->CompileMethode(pClass->GetName(), pVar, ppVars, pStk, inst->m_nMethodeIdent);
        delete pStk->TokenStack();  // release extra stack
        int typ = r.GetType();

        // if there is no constructor, and no parameters either, it's ok
        if (typ == CBotErrUndefCall && inst->m_parameters == nullptr) typ = 0;
        pVar->SetInit(CBotVar::InitType::DEF);    // mark the instance as init

        if (typ>20)
        {
            pStk->SetError(static_cast<CBotError>(typ), inst->m_vartoken.GetEnd());
            goto error;
        }

        // if the constructor does not exist, but there are parameters
        if (typ<0 && inst->m_parameters != nullptr)
        {
            pStk->SetError(CBotErrNoConstruct, &inst->m_vartoken);
            goto error;
        }

        // makes pointer to the object on the stack
        pStk->SetVar(pVar);

        pp = p;
        // chained method ?
        if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStk, true)))
        {
            inst->m_exprRetVar->SetToken(pp);
            delete pStk->TokenStack();
        }

        if (pStack->IsOk())
            return pStack->Return(inst, pStk);
    }
error:
    delete inst;
    return pStack->Return(nullptr, pStk);
}
コード例 #25
0
ファイル: CBotProgram.cpp プロジェクト: Smok94/colobot
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();
}
コード例 #26
0
ファイル: CBotListArray.cpp プロジェクト: CHmSID/colobot
CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type)
{
    CBotCStack* pStk = pStack->TokenStack(p);

    CBotToken* pp = p;

    if (IsOfType( p, ID_NULL ) || (IsOfType(p, ID_OPBLK) && IsOfType(p, ID_CLBLK)))
    {
        CBotInstr* inst = new CBotExprLitNull();
        inst->SetToken(pp);
        return pStack->Return(inst, pStk);            // ok with empty element
    }
    p = pp;

    CBotListArray*    inst = new CBotListArray();

    if (IsOfType( p, ID_OPBLK ))
    {
        // each element takes the one after the other
        if (type.Eq( CBotTypArrayPointer ))
        {
            pStk->SetStartError(p->GetStart());
            if (nullptr == ( inst->m_expr = CBotListArray::Compile( p, pStk, type.GetTypElem() ) ))
            {
                if (pStk->IsOk())
                {
                    inst->m_expr = CBotTwoOpExpr::Compile(p, pStk);
                    if (inst->m_expr == nullptr || !pStk->GetTypResult().Compare(type))  // compatible type ?
                    {
                        pStk->SetError(CBotErrBadType1, p->GetStart());
                        goto error;
                    }
                }
            }

            while (IsOfType( p, ID_COMMA ))                                     // other elements?
            {
                pStk->SetStartError(p->GetStart());

                CBotInstr* i = nullptr;
                if (nullptr == ( i = CBotListArray::Compile(p, pStk, type.GetTypElem() ) ))
                {
                    if (pStk->IsOk())
                    {
                        i = CBotTwoOpExpr::Compile(p, pStk);
                        if (i == nullptr || !pStk->GetTypResult().Compare(type))  // compatible type ?
                        {
                            pStk->SetError(CBotErrBadType1, p->GetStart());
                            goto error;
                        }
                    }
                }

                inst->m_expr->AddNext3b(i);

                if ( p->GetType() == ID_COMMA ) continue;
                if ( p->GetType() == ID_CLBLK ) break;

                pStk->SetError(CBotErrClosePar, p);
                goto error;
            }
        }
        else
        {
            pStk->SetStartError(p->GetStart());
            if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
            {
                goto error;
            }

            CBotTypResult valType = pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);

            if (!TypeCompatible(valType, type, ID_ASS) )
            {
                pStk->SetError(CBotErrBadType1, p->GetStart());
                goto error;
            }

            while (IsOfType( p, ID_COMMA ))                                      // other elements?
            {
                pStk->SetStartError(p->GetStart());

                CBotInstr* i = CBotTwoOpExpr::Compile(p, pStk) ;
                if (nullptr == i)
                {
                    goto error;
                }

                CBotTypResult valType = pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);

                if (!TypeCompatible(valType, type, ID_ASS) )
                {
                    pStk->SetError(CBotErrBadType1, p->GetStart());
                    goto error;
                }
                inst->m_expr->AddNext3b(i);

                if (p->GetType() == ID_COMMA) continue;
                if (p->GetType() == ID_CLBLK) break;

                pStk->SetError(CBotErrClosePar, p);
                goto error;
            }
        }

        if (!IsOfType(p, ID_CLBLK) )
        {
            pStk->SetError(CBotErrClosePar, p->GetStart());
            goto error;
        }

        return pStack->Return(inst, pStk);
    }

error:
    delete inst;
    return pStack->Return(nullptr, pStk);
}
コード例 #27
0
ファイル: CBotTwoOpExpr.cpp プロジェクト: CHmSID/colobot
CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations)
{
    int typeMask;

    if ( pOperations == nullptr ) pOperations = ListOp;
    int* pOp = pOperations;
    while ( *pOp++ != 0 );              // follows the table

    CBotCStack* pStk = pStack->TokenStack();                    // one end of stack please

    // search the intructions that may be suitable to the left of the operation
    CBotInstr*  left = (*pOp == 0) ?
                        CBotParExpr::Compile( p, pStk ) :       // expression (...) left
                        CBotTwoOpExpr::Compile( p, pStk, pOp ); // expression A * B left

    if (left == nullptr) return pStack->Return(nullptr, pStk);        // if error,  transmit

    // did we expected the operand?
    int typeOp = p->GetType();
    if ( IsInList(typeOp, pOperations, typeMask) )
    {
        CBotTypResult    type1, type2;
        type1 = pStk->GetTypResult();                           // what kind of the first operand?

        if (typeOp == ID_LOGIC)       // special case provided for: ? op1: op2;
        {
            if ( !type1.Eq(CBotTypBoolean) )
            {
                pStk->SetError( CBotErrBadType1, p);
                return pStack->Return(nullptr, pStk);
            }
            CBotLogicExpr* inst = new CBotLogicExpr();
            inst->m_condition = left;

            p = p->GetNext();                                       // skip the token of the operation
            inst->m_op1 = CBotExpression::Compile(p, pStk);
            CBotToken* pp = p;
            if ( inst->m_op1 == nullptr || !IsOfType( p, ID_DOTS ) )
            {
                pStk->SetError( CBotErrNoDoubleDots, p->GetStart());
                delete inst;
                return pStack->Return(nullptr, pStk);
            }
            type1 = pStk->GetTypResult();

            inst->m_op2 = CBotExpression::Compile(p, pStk);
            if ( inst->m_op2 == nullptr )
            {
                pStk->SetError( CBotErrNoTerminator, p->GetStart() );
                delete inst;
                return pStack->Return(nullptr, pStk);
            }
            type2 = pStk->GetTypResult();
            if (!TypeCompatible(type1, type2))
            {
                pStk->SetError( CBotErrBadType2, pp );
                delete inst;
                return pStack->Return(nullptr, pStk);
            }

            pStk->SetType(type1);       // the greatest of 2 types

            return pStack->Return(inst, pStk);
        }

        CBotTwoOpExpr* inst = new CBotTwoOpExpr();              // element for operation
        inst->SetToken(p);                                      // stores the operation


        p = p->GetNext();                                           // skip the token of the operation

        // looking statements that may be suitable for right

        if ( nullptr != (inst->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp )) )
                                                                // expression (...) right
        {
            // there is an second operand acceptable

            type2 = pStk->GetTypResult();                       // what kind of results?

            if ( type1.Eq(99) || type2.Eq(99) )                 // operand is void
            {
                pStack->SetError(CBotErrBadType2, &inst->m_token);
                delete inst;
                return nullptr;
            }

            // what kind of result?
            int TypeRes = std::max( type1.GetType(CBotTypResult::GetTypeMode::NULL_AS_POINTER), type2.GetType(CBotTypResult::GetTypeMode::NULL_AS_POINTER) );
            if (typeOp == ID_ADD && type1.Eq(CBotTypString))
            {
                TypeRes = CBotTypString;
                type2 = type1;  // any type convertible chain
            }
            else if (typeOp == ID_ADD && type2.Eq(CBotTypString))
            {
                TypeRes = CBotTypString;
                type1 = type2;  // any type convertible chain
            }
            else if (!TypeOk(TypeRes, typeMask)) type1.SetType(99);// error of type

            switch (typeOp)
            {
            case ID_LOG_OR:
            case ID_LOG_AND:
            case ID_TXT_OR:
            case ID_TXT_AND:
            case ID_EQ:
            case ID_NE:
            case ID_HI:
            case ID_LO:
            case ID_HS:
            case ID_LS:
                TypeRes = CBotTypBoolean;
            }
            if ( TypeCompatible (type1, type2, typeOp) )               // the results are compatible
            {
                // ok so, saves the operand in the object
                inst->m_leftop = left;

                // special for evaluation of the operations of the same level from left to right
                while ( IsInList(p->GetType(), pOperations, typeMask) ) // same operation(s) follows?
                {
                    typeOp = p->GetType();
                    CBotTwoOpExpr* i = new CBotTwoOpExpr();             // element for operation
                    i->SetToken(p);                                     // stores the operation
                    i->m_leftop = inst;                                 // left operand
                    type1 = TypeRes;

                    p = p->GetNext();                                       // advance after
                    i->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp );
                    type2 = pStk->GetTypResult();

                    if ( !TypeCompatible (type1, type2, typeOp) )       // the results are compatible
                    {
                        pStk->SetError(CBotErrBadType2, &i->m_token);
                        delete i;
                        return pStack->Return(nullptr, pStk);
                    }

                    if ( TypeRes != CBotTypString )                     // keep string conversion
                        TypeRes = std::max(type1.GetType(), type2.GetType());
                    inst = i;
                }

                CBotTypResult t(type1);
                    t.SetType(TypeRes);
                // is a variable on the stack for the type of result
                pStk->SetVar(CBotVar::Create("", t));

                // and returns the requested object
                return pStack->Return(inst, pStk);
            }
            pStk->SetError(CBotErrBadType2, &inst->m_token);
        }

        // in case of error, releases the elements
        delete left;
        delete inst;
        // and transmits the error to the stack
        return pStack->Return(nullptr, pStk);
    }

    // if we are not dealing with an operation + or -
    // goes to that requested, the operand (left) found
    // instead of the object "addition"
    return pStack->Return(left, pStk);
}
コード例 #28
0
ファイル: CBotParExpr.cpp プロジェクト: 2asoft/colobot
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);
}
コード例 #29
0
ファイル: CBotLeftExpr.cpp プロジェクト: 2asoft/colobot
CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotCStack* pStk = pStack->TokenStack();

    pStk->SetStartError(p->GetStart());

    // is it a variable name?
    if (p->GetType() == TokenTypVar)
    {
        CBotLeftExpr* inst = new CBotLeftExpr();    // creates the object

        inst->SetToken(p);

        CBotVar*     var;

        if (nullptr != (var = pStk->FindVar(p)))   // seek if known variable
        {
            inst->m_nIdent = var->GetUniqNum();
            if (inst->m_nIdent > 0 && inst->m_nIdent < 9000)
            {
                if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, CBotVar::ProtectionLevel::ReadOnly))
                {
                    pStk->SetError(CBotErrPrivate, p);
                    goto err;
                }
                // this is an element of the current class
                // adds the equivalent of this. before
                CBotToken pthis("this");
                inst->SetToken(&pthis);
                inst->m_nIdent = -2;    // indent for this

                CBotFieldExpr* i = new CBotFieldExpr();     // new element
                i->SetToken(p);     // keeps the name of the token
                inst->AddNext3(i);  // add after

                var = pStk->FindVar(pthis);
                var = var->GetItem(p->GetString());
                i->SetUniqNum(var->GetUniqNum());
            }
            p = p->GetNext();   // next token

            while (true)
            {
                if (var->GetType() == CBotTypArrayPointer)
                {
                    if (IsOfType( p, ID_OPBRK ))
                    {
                        CBotIndexExpr* i = new CBotIndexExpr();
                        i->m_expr = CBotExpression::Compile(p, pStk);
                        inst->AddNext3(i);  // add to the chain

                        var = (static_cast<CBotVarArray*>(var))->GetItem(0,true);    // gets the component [0]

                        if (i->m_expr == nullptr)
                        {
                            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)                // for classes
                {
                    if (IsOfType(p, ID_DOT))
                    {
                        CBotToken* pp = p;

                        CBotFieldExpr* i = new CBotFieldExpr();            // new element
                        i->SetToken(pp);                                // keeps the name of the token
                        inst->AddNext3(i);                                // adds after

                        if (p->GetType() == TokenTypVar)                // must be a name
                        {
                            CBotVar*   preVar = var;
                            var = var->GetItem(p->GetString());            // get item correspondent
                            if (var != nullptr)
                            {
                                if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var,
                                                                        CBotVar::ProtectionLevel::ReadOnly))
                                {
                                    pStk->SetError(CBotErrPrivate, pp);
                                    goto err;
                                }

                                i->SetUniqNum(var->GetUniqNum());
                                p = p->GetNext();                        // skips the name
                                continue;
                            }
                            pStk->SetError(CBotErrUndefItem, p);
                        }
                        pStk->SetError(CBotErrUndefClass, p->GetStart());
                        goto err;
                    }
                }
                break;
            }


            if (pStk->IsOk()) return static_cast<CBotLeftExpr*> (pStack->Return(inst, pStk));
        }
        pStk->SetError(CBotErrUndefVar, p);
err:
        delete inst;
        return static_cast<CBotLeftExpr*> ( pStack->Return(nullptr, pStk));
    }

    return static_cast<CBotLeftExpr*> ( pStack->Return(nullptr, pStk));
}
コード例 #30
0
ファイル: CBotExprRetVar.cpp プロジェクト: 2asoft/colobot
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;
}