1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
///////////////////////////////////////////////////
// expression du genre Op�rande1 + Op�rande2
// Op�rande1 - Op�rande2
#include "CBot.h"
// divers constructeurs
CBotAddExpr::CBotAddExpr()
{
m_leftop =
m_rightop = NULL; // NULL pour pouvoir faire delete sans autre
name = "CBotAddExpr"; // debug
}
CBotAddExpr::~CBotAddExpr()
{
delete m_leftop;
delete m_rightop;
}
// compile une instruction de type A + B
CBotInstr* CBotAddExpr::Compile(CBotToken* &p, CBotStack* pStack)
{
CBotStack* pStk = pStack->TokenStack(); // un bout de pile svp
// cherche des instructions qui peuvent convenir � gauche de l'op�ration + ou -
CBotInstr* left = CBotMulExpr::Compile( p, pStk ); // expression A * B � gauche
if (left == NULL) return pStack->Return(NULL, pStk); // si erreur, la transmet
// est-ce qu'on a le token + ou - ensuite ?
if ( p->GetType() == ID_ADD ||
p->GetType() == ID_SUB) // plus ou moins
{
CBotAddExpr* inst = new CBotAddExpr(); // �l�ment pour op�ration
inst->SetToken(p); // m�morise l'op�ration
int type1, type2;
type1 = pStack->GetType(); // de quel type le premier op�rande ?
p = p->Next(); // saute le token de l'op�ration
// cherche des instructions qui peuvent convenir � droite
if ( NULL != (inst->m_rightop = CBotAddExpr::Compile( p, pStk )) ) // expression (...) � droite
{
// il y a un second op�rande acceptable
type2 = pStack->GetType(); // de quel type le r�sultat ?
if ( type1 == type2 ) // les r�sultats sont-ils compatibles
{
// si ok, enregistre l'op�rande dans l'objet
inst->m_leftop = left;
// et rend l'object � qui l'a demand�
return pStack->Return(inst, pStk);
}
}
// en cas d'erreur, lib�re les �l�ments
delete left;
delete inst;
// et transmet l'erreur qui se trouve sur la pile
return pStack->Return(NULL, pStk);
}
// si on n'a pas affaire � une op�ration + ou -
// rend � qui l'a demand�, l'op�rande (de gauche) trouv�
// � la place de l'objet "addition"
return pStack->Return(left, pStk);
}
// fait l'op�ration d'addition ou de soustraction
BOOL CBotAddExpr::Execute(CBotStack* &pStack)
{
CBotStack* pStk1 = pStack->AddStack(this); // ajoute un �l�ment � la pile
// ou le retrouve en cas de reprise
// if ( pSk1 == EOX ) return TRUE;
// selon la reprise, on peut �tre dans l'un des 2 �tats
if ( pStk1->GetState() == 0 && // 1er �tat, �value l'op�rande de gauche
!m_leftop->Execute(pStk1) ) return FALSE; // interrompu ici ?
// passe � l'�tape suivante
pStk1->SetState(1); // pr�t pour la suite
// demande un peu plus de stack pour ne pas toucher le r�sultat de gauche
// qui se trouve sur la pile, justement.
CBotStack* pStk2 = pStk1->AddStack(); // ajoute un �l�ment � la pile
// ou le retrouve en cas de reprise
// 2e �tat, �value l'op�rande de droite
if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrompu ici ?
int type1 = pStk1->GetType(); // de quels types les r�sultats ?
int type2 = pStk2->GetType();
// cr�e une variable temporaire pour y mettre le r�sultat
CBotVar* result = new CBotVar( NULL, MAX(type1, type2));
// fait l'op�ration selon la demande
switch (GetTokenType())
{
case ID_ADD:
result->Add(pStk1->GetVar(), pStk2->GetVar()); // additionne
break;
case ID_SUB:
result->Sub(pStk1->GetVar(), pStk2->GetVar()); // soustrait
break;
}
pStk2->SetVar(result); // met le r�sultat sur la pile
pStk1->Return(pStk2); // lib�re la pile
return pStack->Return(pStk1); // transmet le r�sultat
}
|