71 // Try to parse an expression symbol (i.e. an OPER_erator or OPER_erand or a colon) |
71 // Try to parse an expression symbol (i.e. an OPER_erator or OPER_erand or a colon) |
72 // from the lexer. |
72 // from the lexer. |
73 // |
73 // |
74 ExpressionSymbol* Expression::ParseSymbol() |
74 ExpressionSymbol* Expression::ParseSymbol() |
75 { |
75 { |
76 int pos = mLexer->GetPosition(); |
76 int pos = mLexer->Position(); |
77 ExpressionValue* op = null; |
77 ExpressionValue* op = null; |
78 |
78 |
79 if (mLexer->GetNext (TK_Colon)) |
79 if (mLexer->Next (TK_Colon)) |
80 return new ExpressionColon; |
80 return new ExpressionColon; |
81 |
81 |
82 // Check for OPER_erator |
82 // Check for OPER_erator |
83 for (const OperatorInfo& op : gOperators) |
83 for (const OperatorInfo& op : gOperators) |
84 if (mLexer->GetNext (op.token)) |
84 if (mLexer->Next (op.token)) |
85 return new ExpressionOperator ((ExpressionOperatorType) (&op - &gOperators[0])); |
85 return new ExpressionOperator ((ExpressionOperatorType) (&op - &gOperators[0])); |
86 |
86 |
87 // Check sub-expression |
87 // Check sub-expression |
88 if (mLexer->GetNext (TK_ParenStart)) |
88 if (mLexer->Next (TK_ParenStart)) |
89 { |
89 { |
90 Expression expr (mParser, mLexer, mType); |
90 Expression expr (mParser, mLexer, mType); |
91 mLexer->MustGetNext (TK_ParenEnd); |
91 mLexer->MustGetNext (TK_ParenEnd); |
92 return expr.GetResult()->Clone(); |
92 return expr.Result()->Clone(); |
93 } |
93 } |
94 |
94 |
95 op = new ExpressionValue (mType); |
95 op = new ExpressionValue (mType); |
96 |
96 |
97 // Check function |
97 // Check function |
105 op->SetBuffer (mParser->ParseCommand (comm)); |
105 op->SetBuffer (mParser->ParseCommand (comm)); |
106 return op; |
106 return op; |
107 } |
107 } |
108 |
108 |
109 // Check for variables |
109 // Check for variables |
110 if (mLexer->GetNext (TK_DollarSign)) |
110 if (mLexer->Next (TK_DollarSign)) |
111 { |
111 { |
112 mLexer->MustGetNext (TK_Symbol); |
112 mLexer->MustGetNext (TK_Symbol); |
113 Variable* var = mParser->FindVariable (GetTokenString()); |
113 Variable* var = mParser->FindVariable (TokenString()); |
114 |
114 |
115 if (var == null) |
115 if (var == null) |
116 Error ("unknown variable %1", GetTokenString()); |
116 Error ("unknown variable %1", TokenString()); |
117 |
117 |
118 if (var->type != mType) |
118 if (var->type != mType) |
119 Error ("expression requires %1, variable $%2 is of type %3", |
119 Error ("expression requires %1, variable $%2 is of type %3", |
120 GetTypeName (mType), var->name, GetTypeName (var->type)); |
120 DataTypeName (mType), var->name, DataTypeName (var->type)); |
121 |
121 |
122 if (var->isarray) |
122 if (var->isarray) |
123 { |
123 { |
124 mLexer->MustGetNext (TK_BracketStart); |
124 mLexer->MustGetNext (TK_BracketStart); |
125 Expression expr (mParser, mLexer, TYPE_Int); |
125 Expression expr (mParser, mLexer, TYPE_Int); |
126 expr.GetResult()->ConvertToBuffer(); |
126 expr.Result()->ConvertToBuffer(); |
127 DataBuffer* buf = expr.GetResult()->GetBuffer()->Clone(); |
127 DataBuffer* buf = expr.Result()->Buffer()->Clone(); |
128 buf->WriteDWord (DH_PushGlobalArray); |
128 buf->WriteDWord (DH_PushGlobalArray); |
129 buf->WriteDWord (var->index); |
129 buf->WriteDWord (var->index); |
130 op->SetBuffer (buf); |
130 op->SetBuffer (buf); |
131 mLexer->MustGetNext (TK_BracketEnd); |
131 mLexer->MustGetNext (TK_BracketEnd); |
132 } |
132 } |
152 switch (mType) |
152 switch (mType) |
153 { |
153 { |
154 case TYPE_Void: |
154 case TYPE_Void: |
155 case TYPE_Unknown: |
155 case TYPE_Unknown: |
156 { |
156 { |
157 Error ("unknown identifier `%1` (expected keyword, function or variable)", GetTokenString()); |
157 Error ("unknown identifier `%1` (expected keyword, function or variable)", TokenString()); |
158 break; |
158 break; |
159 } |
159 } |
160 |
160 |
161 case TYPE_Bool: |
161 case TYPE_Bool: |
162 { |
162 { |
163 if (mLexer->GetNext (TK_True) || mLexer->GetNext (TK_False)) |
163 if (mLexer->Next (TK_True) || mLexer->Next (TK_False)) |
164 { |
164 { |
165 TokenType tt = mLexer->GetTokenType(); |
165 ETokenType tt = mLexer->TokenType(); |
166 op->SetValue (tt ==TK_True ? 1 : 0); |
166 op->SetValue (tt == TK_True ? 1 : 0); |
167 return op; |
167 return op; |
168 } |
168 } |
169 } |
169 } |
170 |
170 |
171 case TYPE_Int: |
171 case TYPE_Int: |
172 { |
172 { |
173 if (mLexer->GetNext (TK_Number)) |
173 if (mLexer->Next (TK_Number)) |
174 { |
174 { |
175 op->SetValue (GetTokenString().ToLong()); |
175 op->SetValue (TokenString().ToLong()); |
176 return op; |
176 return op; |
177 } |
177 } |
178 } |
178 } |
179 |
179 |
180 case TYPE_String: |
180 case TYPE_String: |
181 { |
181 { |
182 if (mLexer->GetNext (TK_String)) |
182 if (mLexer->Next (TK_String)) |
183 { |
183 { |
184 op->SetValue (GetStringTableIndex (GetTokenString())); |
184 op->SetValue (StringTableIndex (TokenString())); |
185 return op; |
185 return op; |
186 } |
186 } |
187 } |
187 } |
188 } |
188 } |
189 |
189 |
190 mBadTokenText = mLexer->GetToken()->text; |
190 mBadTokenText = mLexer->Token()->text; |
191 mLexer->SetPosition (pos); |
191 mLexer->SetPosition (pos); |
192 delete op; |
192 delete op; |
193 return null; |
193 return null; |
194 } |
194 } |
195 |
195 |
203 // |
203 // |
204 void Expression::AdjustOperators() |
204 void Expression::AdjustOperators() |
205 { |
205 { |
206 for (auto it = mSymbols.begin() + 1; it != mSymbols.end(); ++it) |
206 for (auto it = mSymbols.begin() + 1; it != mSymbols.end(); ++it) |
207 { |
207 { |
208 if ((*it)->GetType() != EXPRSYM_Operator) |
208 if ((*it)->Type() != EXPRSYM_Operator) |
209 continue; |
209 continue; |
210 |
210 |
211 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
211 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
212 |
212 |
213 // Unary minus with a value as the previous symbol cannot really be |
213 // Unary minus with a value as the previous symbol cannot really be |
214 // unary; replace with binary minus. |
214 // unary; replace with binary minus. |
215 if (op->GetID() == OPER_UnaryMinus && (*(it - 1))->GetType() == EXPRSYM_Value) |
215 if (op->ID() == OPER_UnaryMinus && (*(it - 1))->Type() == EXPRSYM_Value) |
216 op->SetID (OPER_Subtraction); |
216 op->SetID (OPER_Subtraction); |
217 } |
217 } |
218 } |
218 } |
219 |
219 |
220 // ============================================================================= |
220 // ============================================================================= |
223 // |
223 // |
224 void Expression::TryVerifyValue (bool* verified, SymbolList::Iterator it) |
224 void Expression::TryVerifyValue (bool* verified, SymbolList::Iterator it) |
225 { |
225 { |
226 // If it's an unary OPER_erator we skip to its value. The actual OPER_erator will |
226 // If it's an unary OPER_erator we skip to its value. The actual OPER_erator will |
227 // be verified separately. |
227 // be verified separately. |
228 if ((*it)->GetType() == EXPRSYM_Operator && |
228 if ((*it)->Type() == EXPRSYM_Operator && |
229 gOperators[static_cast<ExpressionOperator*> (*it)->GetID()].numoperands == 1) |
229 gOperators[static_cast<ExpressionOperator*> (*it)->ID()].numoperands == 1) |
230 { |
230 { |
231 ++it; |
231 ++it; |
232 } |
232 } |
233 |
233 |
234 int i = it - mSymbols.begin(); |
234 int i = it - mSymbols.begin(); |
235 |
235 |
236 // Ensure it's an actual value |
236 // Ensure it's an actual value |
237 if ((*it)->GetType() != EXPRSYM_Value) |
237 if ((*it)->Type() != EXPRSYM_Value) |
238 Error ("malformed expression (symbol #%1 is not a value)", i); |
238 Error ("malformed expression (symbol #%1 is not a value)", i); |
239 |
239 |
240 verified[i] = true; |
240 verified[i] = true; |
241 } |
241 } |
242 |
242 |
265 |
265 |
266 for (auto it = mSymbols.begin(); it != mSymbols.end(); ++it) |
266 for (auto it = mSymbols.begin(); it != mSymbols.end(); ++it) |
267 { |
267 { |
268 int i = (it - first); |
268 int i = (it - first); |
269 |
269 |
270 if ((*it)->GetType() != EXPRSYM_Operator) |
270 if ((*it)->Type() != EXPRSYM_Operator) |
271 continue; |
271 continue; |
272 |
272 |
273 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
273 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
274 int numoperands = gOperators[op->GetID()].numoperands; |
274 int numoperands = gOperators[op->ID()].numoperands; |
275 |
275 |
276 switch (numoperands) |
276 switch (numoperands) |
277 { |
277 { |
278 case 1: |
278 case 1: |
279 { |
279 { |
329 |
329 |
330 if (it == first || |
330 if (it == first || |
331 it >= mSymbols.end() - 3 || |
331 it >= mSymbols.end() - 3 || |
332 verified[i] == true || |
332 verified[i] == true || |
333 verified[i + 2] == true || |
333 verified[i + 2] == true || |
334 (*(it + 2))->GetType() != EXPRSYM_Colon) |
334 (*(it + 2))->Type() != EXPRSYM_Colon) |
335 { |
335 { |
336 Error ("malformed expression"); |
336 Error ("malformed expression"); |
337 } |
337 } |
338 |
338 |
339 verified[i] = true; |
339 verified[i] = true; |
359 // Which OPER_erator to evaluate? |
359 // Which OPER_erator to evaluate? |
360 // |
360 // |
361 Expression::SymbolList::Iterator Expression::FindPrioritizedOperator() |
361 Expression::SymbolList::Iterator Expression::FindPrioritizedOperator() |
362 { |
362 { |
363 SymbolList::Iterator best = mSymbols.end(); |
363 SymbolList::Iterator best = mSymbols.end(); |
364 int bestpriority = INT_MAX; |
364 int bestpriority = __INT_MAX__; |
365 |
365 |
366 for (SymbolList::Iterator it = mSymbols.begin(); it != mSymbols.end(); ++it) |
366 for (SymbolList::Iterator it = mSymbols.begin(); it != mSymbols.end(); ++it) |
367 { |
367 { |
368 if ((*it)->GetType() != EXPRSYM_Operator) |
368 if ((*it)->Type() != EXPRSYM_Operator) |
369 continue; |
369 continue; |
370 |
370 |
371 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
371 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
372 const OperatorInfo* info = &gOperators[op->GetID()]; |
372 const OperatorInfo* info = &gOperators[op->ID()]; |
373 |
373 |
374 if (info->priority < bestpriority) |
374 if (info->priority < bestpriority) |
375 { |
375 { |
376 best = it; |
376 best = it; |
377 bestpriority = info->priority; |
377 bestpriority = info->priority; |
386 // Process the given OPER_erator and values into a new value. |
386 // Process the given OPER_erator and values into a new value. |
387 // |
387 // |
388 ExpressionValue* Expression::EvaluateOperator (const ExpressionOperator* op, |
388 ExpressionValue* Expression::EvaluateOperator (const ExpressionOperator* op, |
389 const List<ExpressionValue*>& values) |
389 const List<ExpressionValue*>& values) |
390 { |
390 { |
391 const OperatorInfo* info = &gOperators[op->GetID()]; |
391 const OperatorInfo* info = &gOperators[op->ID()]; |
392 bool isconstexpr = true; |
392 bool isconstexpr = true; |
393 assert (values.Size() == info->numoperands); |
393 assert (values.Size() == info->numoperands); |
394 |
394 |
395 for (ExpressionValue* val : values) |
395 for (ExpressionValue* val : values) |
396 { |
396 { |
413 // This is not a constant expression so we'll have to use databuffers |
413 // This is not a constant expression so we'll have to use databuffers |
414 // to convey the expression to bytecode. Actual value cannot be evaluated |
414 // to convey the expression to bytecode. Actual value cannot be evaluated |
415 // until Zandronum processes it at run-time. |
415 // until Zandronum processes it at run-time. |
416 newval->SetBuffer (new DataBuffer); |
416 newval->SetBuffer (new DataBuffer); |
417 |
417 |
418 if (op->GetID() == OPER_Ternary) |
418 if (op->ID() == OPER_Ternary) |
419 { |
419 { |
420 // There isn't a dataheader for ternary OPER_erator. Instead, we use DH_IfNotGoto |
420 // There isn't a dataheader for ternary OPER_erator. Instead, we use DH_IfNotGoto |
421 // to create an "if-block" inside an expression. |
421 // to create an "if-block" inside an expression. |
422 // Behold, big block of writing madness! :P |
422 // Behold, big block of writing madness! :P |
423 // |
423 // |
424 DataBuffer* buf = newval->GetBuffer(); |
424 DataBuffer* buf = newval->Buffer(); |
425 DataBuffer* b0 = values[0]->GetBuffer(); |
425 DataBuffer* b0 = values[0]->Buffer(); |
426 DataBuffer* b1 = values[1]->GetBuffer(); |
426 DataBuffer* b1 = values[1]->Buffer(); |
427 DataBuffer* b2 = values[2]->GetBuffer(); |
427 DataBuffer* b2 = values[2]->Buffer(); |
428 ByteMark* mark1 = buf->AddMark (""); // start of "else" case |
428 ByteMark* mark1 = buf->AddMark (""); // start of "else" case |
429 ByteMark* mark2 = buf->AddMark (""); // end of expression |
429 ByteMark* mark2 = buf->AddMark (""); // end of expression |
430 buf->MergeAndDestroy (b0); |
430 buf->MergeAndDestroy (b0); |
431 buf->WriteDWord (DH_IfNotGoto); // if the first OPER_erand (condition) |
431 buf->WriteDWord (DH_IfNotGoto); // if the first OPER_erand (condition) |
432 buf->AddReference (mark1); // didn't eval true, jump into mark1 |
432 buf->AddReference (mark1); // didn't eval true, jump into mark1 |
444 { |
444 { |
445 // Generic case: write all arguments and apply the OPER_erator's |
445 // Generic case: write all arguments and apply the OPER_erator's |
446 // data header. |
446 // data header. |
447 for (ExpressionValue* val : values) |
447 for (ExpressionValue* val : values) |
448 { |
448 { |
449 newval->GetBuffer()->MergeAndDestroy (val->GetBuffer()); |
449 newval->Buffer()->MergeAndDestroy (val->Buffer()); |
450 |
450 |
451 // Null the pointer out so that the value's destructor will not |
451 // Null the pointer out so that the value's destructor will not |
452 // attempt to double-free it. |
452 // attempt to double-free it. |
453 val->SetBuffer (null); |
453 val->SetBuffer (null); |
454 } |
454 } |
455 |
455 |
456 newval->GetBuffer()->WriteDWord (info->header); |
456 newval->Buffer()->WriteDWord (info->header); |
457 } |
457 } |
458 } |
458 } |
459 else |
459 else |
460 { |
460 { |
461 // We have a constant expression. We know all the values involved and |
461 // We have a constant expression. We know all the values involved and |
462 // can thus compute the result of this expression on compile-time. |
462 // can thus compute the result of this expression on compile-time. |
463 List<int> nums; |
463 List<int> nums; |
464 int a; |
464 int a; |
465 |
465 |
466 for (ExpressionValue* val : values) |
466 for (ExpressionValue* val : values) |
467 nums << val->GetValue(); |
467 nums << val->Value(); |
468 |
468 |
469 switch (op->GetID()) |
469 switch (op->ID()) |
470 { |
470 { |
471 case OPER_Addition: a = nums[0] + nums[1]; break; |
471 case OPER_Addition: a = nums[0] + nums[1]; break; |
472 case OPER_Subtraction: a = nums[0] - nums[1]; break; |
472 case OPER_Subtraction: a = nums[0] - nums[1]; break; |
473 case OPER_Multiplication: a = nums[0] * nums[1]; break; |
473 case OPER_Multiplication: a = nums[0] * nums[1]; break; |
474 case OPER_UnaryMinus: a = -nums[0]; break; |
474 case OPER_UnaryMinus: a = -nums[0]; break; |
527 while ((it = FindPrioritizedOperator()) != mSymbols.end()) |
527 while ((it = FindPrioritizedOperator()) != mSymbols.end()) |
528 { |
528 { |
529 int i = it - mSymbols.begin(); |
529 int i = it - mSymbols.begin(); |
530 List<SymbolList::Iterator> OPER_erands; |
530 List<SymbolList::Iterator> OPER_erands; |
531 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
531 ExpressionOperator* op = static_cast<ExpressionOperator*> (*it); |
532 const OperatorInfo* info = &gOperators[op->GetID()]; |
532 const OperatorInfo* info = &gOperators[op->ID()]; |
533 int lower, upper; // Boundaries of area to replace |
533 int lower, upper; // Boundaries of area to replace |
534 |
534 |
535 switch (info->numoperands) |
535 switch (info->numoperands) |
536 { |
536 { |
537 case 1: |
537 case 1: |
577 mSymbols.RemoveAt (i); |
577 mSymbols.RemoveAt (i); |
578 |
578 |
579 mSymbols.Insert (lower, newvalue); |
579 mSymbols.Insert (lower, newvalue); |
580 } |
580 } |
581 |
581 |
582 assert (mSymbols.Size() == 1 && mSymbols.First()->GetType() == EXPRSYM_Value); |
582 assert (mSymbols.Size() == 1 && mSymbols.First()->Type() == EXPRSYM_Value); |
583 ExpressionValue* val = static_cast<ExpressionValue*> (mSymbols.First()); |
583 ExpressionValue* val = static_cast<ExpressionValue*> (mSymbols.First()); |
584 return val; |
584 return val; |
585 } |
585 } |
586 |
586 |
587 // ============================================================================= |
587 // ============================================================================= |
588 // |
588 // |
589 ExpressionValue* Expression::GetResult() |
589 ExpressionValue* Expression::Result() |
590 { |
590 { |
591 return static_cast<ExpressionValue*> (mSymbols.First()); |
591 return static_cast<ExpressionValue*> (mSymbols.First()); |
592 } |
592 } |
593 |
593 |
594 // ============================================================================= |
594 // ============================================================================= |
595 // |
595 // |
596 String Expression::GetTokenString() |
596 String Expression::TokenString() |
597 { |
597 { |
598 return mLexer->GetToken()->text; |
598 return mLexer->Token()->text; |
599 } |
599 } |
600 |
600 |
601 // ============================================================================= |
601 // ============================================================================= |
602 // |
602 // |
603 ExpressionOperator::ExpressionOperator (ExpressionOperatorType id) : |
603 ExpressionOperator::ExpressionOperator (ExpressionOperatorType id) : |
629 |
629 |
630 switch (mValueType) |
630 switch (mValueType) |
631 { |
631 { |
632 case TYPE_Bool: |
632 case TYPE_Bool: |
633 case TYPE_Int: |
633 case TYPE_Int: |
634 GetBuffer()->WriteDWord (DH_PushNumber); |
634 Buffer()->WriteDWord (DH_PushNumber); |
635 GetBuffer()->WriteDWord (abs (mValue)); |
635 Buffer()->WriteDWord (abs (mValue)); |
636 |
636 |
637 if (mValue < 0) |
637 if (mValue < 0) |
638 GetBuffer()->WriteDWord (DH_UnaryMinus); |
638 Buffer()->WriteDWord (DH_UnaryMinus); |
639 break; |
639 break; |
640 |
640 |
641 case TYPE_String: |
641 case TYPE_String: |
642 GetBuffer()->WriteDWord (DH_PushStringIndex); |
642 Buffer()->WriteDWord (DH_PushStringIndex); |
643 GetBuffer()->WriteDWord (mValue); |
643 Buffer()->WriteDWord (mValue); |
644 break; |
644 break; |
645 |
645 |
646 case TYPE_Void: |
646 case TYPE_Void: |
647 case TYPE_Unknown: |
647 case TYPE_Unknown: |
648 assert (false); |
648 assert (false); |