282 lines
8.1 KiB
C++
282 lines
8.1 KiB
C++
/*
|
|
* This file is part of the Colobot: Gold Edition source code
|
|
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
|
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see http://gnu.org/licenses
|
|
*/
|
|
|
|
#include "CBot/CBotInstr/CBotParExpr.h"
|
|
|
|
#include "CBot/CBotInstr/CBotExpression.h"
|
|
#include "CBot/CBotInstr/CBotExprLitBool.h"
|
|
#include "CBot/CBotInstr/CBotExprLitChar.h"
|
|
#include "CBot/CBotInstr/CBotExprLitNan.h"
|
|
#include "CBot/CBotInstr/CBotExprLitNull.h"
|
|
#include "CBot/CBotInstr/CBotExprLitNum.h"
|
|
#include "CBot/CBotInstr/CBotExprLitString.h"
|
|
#include "CBot/CBotInstr/CBotExprUnaire.h"
|
|
#include "CBot/CBotInstr/CBotExprVar.h"
|
|
#include "CBot/CBotInstr/CBotInstrCall.h"
|
|
#include "CBot/CBotInstr/CBotNew.h"
|
|
#include "CBot/CBotInstr/CBotPostIncExpr.h"
|
|
#include "CBot/CBotInstr/CBotPreIncExpr.h"
|
|
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
|
|
|
|
#include "CBot/CBotVar/CBotVar.h"
|
|
|
|
#include "CBot/CBotCStack.h"
|
|
|
|
namespace CBot
|
|
{
|
|
|
|
CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack, bool bConstExpr)
|
|
{
|
|
CBotCStack* pStk = pStack->TokenStack();
|
|
|
|
pStk->SetStartError(p->GetStart());
|
|
|
|
if (bConstExpr)
|
|
return CBotParExpr::CompileConstExpr(p, pStack);
|
|
|
|
// 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 sizeof operator ?
|
|
inst = CBot::CompileSizeOf(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's an "ordinaty" variable
|
|
inst = CBotExprVar::Compile(p, pStk);
|
|
|
|
CBotToken* pp = p;
|
|
// post incremented or decremented?
|
|
if (IsOfType(p, ID_INC, ID_DEC))
|
|
{
|
|
// recompile the variable for read-only
|
|
delete inst;
|
|
p = pvar;
|
|
inst = CBotExprVar::Compile(p, pStk, true);
|
|
if (pStk->GetType() >= CBotTypBoolean)
|
|
{
|
|
pStk->SetError(CBotErrBadType1, pp);
|
|
delete inst;
|
|
return pStack->Return(nullptr, pStk);
|
|
}
|
|
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))
|
|
{
|
|
if (p->GetType() == TokenTypVar)
|
|
{
|
|
if (nullptr != (inst = CBotExprVar::Compile(p, pStk, true)))
|
|
{
|
|
if (pStk->GetType() < CBotTypBoolean) // a number ?
|
|
{
|
|
CBotPreIncExpr* i = new CBotPreIncExpr();
|
|
i->SetToken(pp);
|
|
i->m_instr = inst;
|
|
return pStack->Return(i, pStk);
|
|
}
|
|
delete inst;
|
|
}
|
|
}
|
|
pStk->SetError(CBotErrBadType1, pp);
|
|
return pStack->Return(nullptr, pStk);
|
|
}
|
|
|
|
return CBotParExpr::CompileLitExpr(p, pStack);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack)
|
|
{
|
|
CBotCStack* pStk = pStack->TokenStack();
|
|
|
|
CBotToken* pp = p;
|
|
|
|
// is this a unary operation?
|
|
CBotInstr* inst = CBotExprUnaire::Compile(p, pStk, true);
|
|
if (inst != nullptr || !pStk->IsOk())
|
|
return pStack->Return(inst, pStk);
|
|
|
|
// is it a number or DefineNum?
|
|
if (p->GetType() == TokenTypNum ||
|
|
p->GetType() == TokenTypDef )
|
|
{
|
|
CBotInstr* inst = CBot::CompileExprLitNum(p, pStk);
|
|
return pStack->Return(inst, pStk);
|
|
}
|
|
|
|
// is it sizeof operator ?
|
|
inst = CBot::CompileSizeOf(p, pStk);
|
|
if (inst != nullptr || !pStk->IsOk())
|
|
{
|
|
return pStack->Return(inst, pStk);
|
|
}
|
|
|
|
// is this a character?
|
|
if (p->GetType() == TokenTypChar)
|
|
{
|
|
CBotInstr* inst = CBotExprLitChar::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* CBotParExpr::CompileConstExpr(CBotToken* &p, CBotCStack* pStack)
|
|
{
|
|
CBotCStack* pStk = pStack->TokenStack();
|
|
|
|
// is it an expression in parentheses?
|
|
if (IsOfType(p, ID_OPENPAR))
|
|
{
|
|
CBotInstr* inst = CBotTwoOpExpr::Compile(p, pStk, nullptr, true);
|
|
|
|
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, true, true);
|
|
if (inst != nullptr || !pStk->IsOk())
|
|
return pStack->Return(inst, pStk);
|
|
|
|
// is it a number or DefineNum?
|
|
if (p->GetType() == TokenTypNum ||
|
|
p->GetType() == TokenTypDef )
|
|
{
|
|
CBotInstr* inst = CBot::CompileExprLitNum(p, pStk);
|
|
return pStack->Return(inst, pStk);
|
|
}
|
|
|
|
// is this a character?
|
|
if (p->GetType() == TokenTypChar)
|
|
{
|
|
CBotInstr* inst = CBotExprLitChar::Compile(p, pStk);
|
|
return pStack->Return(inst, pStk);
|
|
}
|
|
|
|
// is it sizeof operator ?
|
|
inst = CBot::CompileSizeOf(p, pStk);
|
|
if (inst != nullptr || !pStk->IsOk())
|
|
{
|
|
return pStack->Return(inst, pStk);
|
|
}
|
|
|
|
return pStack->Return(nullptr, pStk);
|
|
}
|
|
|
|
} // namespace CBot
|