src/Expression.cc

changeset 107
55c2bcd8ed5c
parent 106
9174be9ac686
child 108
6409ece8297c
equal deleted inserted replaced
106:9174be9ac686 107:55c2bcd8ed5c
73 // 73 //
74 ExpressionSymbol* Expression::ParseSymbol() 74 ExpressionSymbol* Expression::ParseSymbol()
75 { 75 {
76 int pos = mLexer->GetPosition(); 76 int pos = mLexer->GetPosition();
77 ExpressionValue* op = null; 77 ExpressionValue* op = null;
78 enum ELocalException { failed }; 78
79 79 if (mLexer->GetNext (tkColon))
80 try 80 return new ExpressionColon;
81 { 81
82 mLexer->MustGetNext (tkAny); 82 // Check for operator
83 83 for (const OperatorInfo& op : gOperators)
84 if (mLexer->GetTokenType() == tkColon) 84 if (mLexer->GetNext (op.token))
85 return new ExpressionColon; 85 return new ExpressionOperator ((EOperator) (&op - &gOperators[0]));
86 86
87 // Check for operator 87 // Check sub-expression
88 for (const OperatorInfo& op : gOperators) 88 if (mLexer->GetNext (tkParenStart))
89 if (mLexer->GetTokenType() == op.token) 89 {
90 return new ExpressionOperator ((EOperator) (&op - &gOperators[0])); 90 Expression expr (mParser, mLexer, mType);
91 91 mLexer->MustGetNext (tkParenEnd);
92 // Check sub-expression 92 return expr.GetResult()->Clone();
93 if (mLexer->GetTokenType() == tkParenStart) 93 }
94 { 94
95 Expression expr (mParser, mLexer, mType); 95 op = new ExpressionValue (mType);
96 mLexer->MustGetNext (tkParenEnd); 96
97 return expr.GetResult()->Clone(); 97 // Check function
98 } 98 if (CommandInfo* comm = FindCommandByName (mLexer->PeekNextString()))
99 99 {
100 op = new ExpressionValue (mType); 100 mLexer->Skip();
101 101
102 // Check function 102 if (mType != EUnknownType && comm->returnvalue != mType)
103 if (CommandInfo* comm = FindCommandByName (GetTokenString())) 103 Error ("%1 returns an incompatible data type", comm->name);
104 { 104
105 if (mType != EUnknownType && comm->returnvalue != mType) 105 op->SetBuffer (mParser->ParseCommand (comm));
106 Error ("%1 returns an incompatible data type", comm->name); 106 return op;
107 107 }
108 op->SetBuffer (mParser->ParseCommand (comm)); 108
109 return op; 109 // Check for variables
110 } 110 if (mLexer->GetNext (tkDollarSign))
111 111 {
112 // Check for variables 112 mLexer->MustGetNext (tkSymbol);
113 if (mLexer->GetTokenType() == tkDollarSign) 113 Variable* var = mParser->FindVariable (GetTokenString());
114 { 114
115 mLexer->MustGetNext (tkSymbol); 115 if (var == null)
116 Variable* globalvar = mParser->FindVariable (GetTokenString()); 116 Error ("unknown variable %1", GetTokenString());
117 117
118 if (globalvar == null) 118 if (var->type != mType)
119 Error ("unknown variable %1", GetTokenString()); 119 Error ("expression requires %1, variable $%2 is of type %3",
120 120 GetTypeName (mType), var->name, GetTypeName (var->type));
121 if (globalvar->writelevel == Variable::WRITE_Constexpr) 121
122 op->SetValue (globalvar->value); 122 if (var->isarray)
123 {
124 mLexer->MustGetNext (tkBracketStart);
125 Expression expr (mParser, mLexer, EIntType);
126 expr.GetResult()->ConvertToBuffer();
127 DataBuffer* buf = expr.GetResult()->GetBuffer()->Clone();
128 buf->WriteDWord (dhPushGlobalArray);
129 buf->WriteDWord (var->index);
130 op->SetBuffer (buf);
131 mLexer->MustGetNext (tkBracketEnd);
132 }
133 elif (var->writelevel == Variable::WRITE_Constexpr)
134 op->SetValue (var->value);
135 else
136 {
137 DataBuffer* buf = new DataBuffer (8);
138
139 if (var->IsGlobal())
140 buf->WriteDWord (dhPushGlobalVar);
123 else 141 else
124 { 142 buf->WriteDWord (dhPushLocalVar);
125 DataBuffer* buf = new DataBuffer (8); 143
126 buf->WriteDWord (dhPushGlobalVar); 144 buf->WriteDWord (var->index);
127 buf->WriteDWord (globalvar->index); 145 op->SetBuffer (buf);
128 op->SetBuffer (buf); 146 }
129 } 147
130 148 return op;
131 return op; 149 }
132 } 150
133 151 // Check for literal
134 EToken tt; 152 switch (mType)
135 153 {
136 // Check for literal 154 case EVoidType:
137 switch (mType) 155 case EUnknownType:
138 { 156 {
139 case EVoidType: 157 Error ("unknown identifier `%1` (expected keyword, function or variable)", GetTokenString());
140 case EUnknownType: 158 break;
141 { 159 }
142 Error ("unknown identifier `%1` (expected keyword, function or variable)", GetTokenString()); 160
143 break; 161 case EBoolType:
144 } 162 {
145 163 if (mLexer->GetNext (tkTrue) || mLexer->GetNext (tkFalse))
146 case EBoolType: 164 {
147 { 165 EToken tt = mLexer->GetTokenType();
148 if ((tt = mLexer->GetTokenType()) == tkTrue || tt == tkFalse) 166 op->SetValue (tt == tkTrue ? 1 : 0);
149 { 167 return op;
150 op->SetValue (tt == tkTrue ? 1 : 0); 168 }
151 return op; 169 }
152 } 170
153 } 171 case EIntType:
154 case EIntType: 172 {
155 { 173 if (mLexer->GetNext (tkNumber))
156 if (mLexer->GetTokenType() != tkNumber) 174 {
157 throw failed;
158
159 op->SetValue (GetTokenString().ToLong()); 175 op->SetValue (GetTokenString().ToLong());
160 return op; 176 return op;
161 } 177 }
162 178 }
163 case EStringType: 179
164 { 180 case EStringType:
165 if (mLexer->GetTokenType() != tkString) 181 {
166 throw failed; 182 if (mLexer->GetNext (tkString))
167 183 {
168 op->SetValue (GetStringTableIndex (GetTokenString())); 184 op->SetValue (GetStringTableIndex (GetTokenString()));
169 return op; 185 return op;
170 } 186 }
171 } 187 }
172 188 }
173 assert (false); 189
174 throw failed; 190 mBadTokenText = mLexer->GetToken()->text;
175 } 191 mLexer->SetPosition (pos);
176 catch (ELocalException&) 192 delete op;
177 {
178 // We use a local enum here since catch(...) would catch Error() calls.
179 mBadTokenText = mLexer->GetToken()->text;
180 mLexer->SetPosition (pos);
181 delete op;
182 return null;
183 }
184
185 assert (false);
186 return null; 193 return null;
187 } 194 }
188 195
189 // ============================================================================= 196 // =============================================================================
190 // 197 //
381 ExpressionValue* Expression::EvaluateOperator (const ExpressionOperator* op, 388 ExpressionValue* Expression::EvaluateOperator (const ExpressionOperator* op,
382 const List<ExpressionValue*>& values) 389 const List<ExpressionValue*>& values)
383 { 390 {
384 const OperatorInfo* info = &gOperators[op->GetID()]; 391 const OperatorInfo* info = &gOperators[op->GetID()];
385 bool isconstexpr = true; 392 bool isconstexpr = true;
393 assert (values.Size() == info->numoperands);
386 394
387 for (ExpressionValue* val : values) 395 for (ExpressionValue* val : values)
388 { 396 {
389 if (val->IsConstexpr() == false) 397 if (val->IsConstexpr() == false)
390 { 398 {
479 case opLogicalAnd: a = (nums[0] && nums[1]) ? 1 : 0; break; 487 case opLogicalAnd: a = (nums[0] && nums[1]) ? 1 : 0; break;
480 case opLogicalOr: a = (nums[0] || nums[1]) ? 1 : 0; break; 488 case opLogicalOr: a = (nums[0] || nums[1]) ? 1 : 0; break;
481 case opTernary: a = (nums[0] != 0) ? nums[1] : nums[2]; break; 489 case opTernary: a = (nums[0] != 0) ? nums[1] : nums[2]; break;
482 490
483 case opDivision: 491 case opDivision:
492 {
484 if (nums[1] == 0) 493 if (nums[1] == 0)
485 Error ("division by zero in constant expression"); 494 Error ("division by zero in constant expression");
486 495
487 a = nums[0] / nums[1]; 496 a = nums[0] / nums[1];
488 break; 497 break;
498 }
489 499
490 case opModulus: 500 case opModulus:
501 {
491 if (nums[1] == 0) 502 if (nums[1] == 0)
492 Error ("modulus by zero in constant expression"); 503 Error ("modulus by zero in constant expression");
493 504
494 a = nums[0] % nums[1]; 505 a = nums[0] % nums[1];
495 break; 506 break;
507 }
496 } 508 }
497 509
498 newval->SetValue (a); 510 newval->SetValue (a);
499 } 511 }
500 512

mercurial