66 delete sym; |
66 delete sym; |
67 } |
67 } |
68 |
68 |
69 // ============================================================================= |
69 // ============================================================================= |
70 // |
70 // |
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 operator 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 = m_lexer->position(); |
76 int pos = m_lexer->position(); |
77 ExpressionValue* op = null; |
77 ExpressionValue* op = null; |
78 |
78 |
79 if (m_lexer->next (TK_Colon)) |
79 if (m_lexer->next (TK_Colon)) |
80 return new ExpressionColon; |
80 return new ExpressionColon; |
81 |
81 |
82 // Check for OPER_erator |
82 // Check for operator |
83 for (const OperatorInfo& op : g_Operators) |
83 for (const OperatorInfo& op : g_Operators) |
84 if (m_lexer->next (op.token)) |
84 if (m_lexer->next (op.token)) |
85 return new ExpressionOperator ((ExpressionOperatorType) (&op - &g_Operators[0])); |
85 return new ExpressionOperator ((ExpressionOperatorType) (&op - &g_Operators[0])); |
86 |
86 |
87 // Check sub-expression |
87 // Check sub-expression |
193 return null; |
193 return null; |
194 } |
194 } |
195 |
195 |
196 // ============================================================================= |
196 // ============================================================================= |
197 // |
197 // |
198 // The symbol parsing process only does token-based checking for OPER_erators. |
198 // The symbol parsing process only does token-based checking for operators. |
199 // Thus ALL minus OPER_erators are actually unary minuses simply because both |
199 // Thus ALL minus operators are actually unary minuses simply because both |
200 // have TK_Minus as their token and the unary minus is prior to the binary minus |
200 // have TK_Minus as their token and the unary minus is prior to the binary minus |
201 // in the OPER_erator table. Now that we have all symbols present, we can |
201 // in the operator table. Now that we have all symbols present, we can |
202 // correct cases like this. |
202 // correct cases like this. |
203 // |
203 // |
204 void Expression::adjustOperators() |
204 void Expression::adjustOperators() |
205 { |
205 { |
206 for (auto it = m_symbols.begin() + 1; it != m_symbols.end(); ++it) |
206 for (auto it = m_symbols.begin() + 1; it != m_symbols.end(); ++it) |
221 // |
221 // |
222 // Verifies a single value. Helper function for Expression::verify. |
222 // Verifies a single value. Helper function for Expression::verify. |
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 operator we skip to its value. The actual operator will |
227 // be verified separately. |
227 // be verified separately. |
228 if ((*it)->type() == EXPRSYM_Operator && |
228 if ((*it)->type() == EXPRSYM_Operator && |
229 g_Operators[static_cast<ExpressionOperator*> (*it)->id()].numoperands == 1) |
229 g_Operators[static_cast<ExpressionOperator*> (*it)->id()].numoperands == 1) |
230 { |
230 { |
231 ++it; |
231 ++it; |
276 switch (numoperands) |
276 switch (numoperands) |
277 { |
277 { |
278 case 1: |
278 case 1: |
279 { |
279 { |
280 // Ensure that: |
280 // Ensure that: |
281 // - unary OPER_erator is not the last symbol |
281 // - unary operator is not the last symbol |
282 // - unary OPER_erator is succeeded by a value symbol |
282 // - unary operator is succeeded by a value symbol |
283 // - neither symbol overlaps with something already verified |
283 // - neither symbol overlaps with something already verified |
284 tryVerifyValue (verified, it + 1); |
284 tryVerifyValue (verified, it + 1); |
285 |
285 |
286 if (it == last || verified[i] == true) |
286 if (it == last || verified[i] == true) |
287 error ("malformed expression"); |
287 error ("malformed expression"); |
291 } |
291 } |
292 |
292 |
293 case 2: |
293 case 2: |
294 { |
294 { |
295 // Ensure that: |
295 // Ensure that: |
296 // - binary OPER_erator is not the first or last symbol |
296 // - binary operator is not the first or last symbol |
297 // - is preceded and succeeded by values |
297 // - is preceded and succeeded by values |
298 // - none of the three tokens are already verified |
298 // - none of the three tokens are already verified |
299 // |
299 // |
300 // Basically similar logic as above. |
300 // Basically similar logic as above. |
301 if (it == first || it == last || verified[i] == true) |
301 if (it == first || it == last || verified[i] == true) |
307 break; |
307 break; |
308 } |
308 } |
309 |
309 |
310 case 3: |
310 case 3: |
311 { |
311 { |
312 // Ternary OPER_erator case. This goes a bit nuts. |
312 // Ternary operator case. This goes a bit nuts. |
313 // This time we have the following: |
313 // This time we have the following: |
314 // |
314 // |
315 // (VALUE) ? (VALUE) : (VALUE) |
315 // (VALUE) ? (VALUE) : (VALUE) |
316 // ^ |
316 // ^ |
317 // --------/ we are here |
317 // --------/ we are here |
318 // |
318 // |
319 // Check that the: |
319 // Check that the: |
320 // - questionmark OPER_erator is not misplaced (first or last) |
320 // - questionmark operator is not misplaced (first or last) |
321 // - the value behind the OPER_erator (-1) is valid |
321 // - the value behind the operator (-1) is valid |
322 // - the value after the OPER_erator (+1) is valid |
322 // - the value after the operator (+1) is valid |
323 // - the value after the colon (+3) is valid |
323 // - the value after the colon (+3) is valid |
324 // - none of the five tokens are verified |
324 // - none of the five tokens are verified |
325 // |
325 // |
326 tryVerifyValue (verified, it - 1); |
326 tryVerifyValue (verified, it - 1); |
327 tryVerifyValue (verified, it + 1); |
327 tryVerifyValue (verified, it + 1); |
381 return best; |
381 return best; |
382 } |
382 } |
383 |
383 |
384 // ============================================================================= |
384 // ============================================================================= |
385 // |
385 // |
386 // Process the given OPER_erator and values into a new value. |
386 // Process the given operator 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 = &g_Operators[op->id()]; |
391 const OperatorInfo* info = &g_Operators[op->id()]; |
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->id() == 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 operator. 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->buffer(); |
424 DataBuffer* buf = newval->buffer(); |
425 DataBuffer* b0 = values[0]->buffer(); |
425 DataBuffer* b0 = values[0]->buffer(); |
440 for (int i = 0; i < 3; ++i) |
440 for (int i = 0; i < 3; ++i) |
441 values[i]->setBuffer (null); |
441 values[i]->setBuffer (null); |
442 } |
442 } |
443 else |
443 else |
444 { |
444 { |
445 // Generic case: write all arguments and apply the OPER_erator's |
445 // Generic case: write all arguments and apply the operator's |
446 // data header. |
446 // data header. |
447 for (ExpressionValue* val : values) |
447 for (ExpressionValue* val : values) |
448 { |
448 { |
449 newval->buffer()->mergeAndDestroy (val->buffer()); |
449 newval->buffer()->mergeAndDestroy (val->buffer()); |
450 |
450 |