home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / graphtal / expressi.c < prev    next >
C/C++ Source or Header  |  1992-10-19  |  5KB  |  175 lines

  1. /*
  2.  * Expression.C - methods to evaluate and handle arithmetic expressions.
  3.  *
  4.  * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  */
  17.  
  18. #include "Expression.h"
  19.  
  20. //___________________________________________________________ ExprItem
  21.  
  22. implementList(ExprItemList, ExprItemPtr);
  23. ExprItem::ExprItem(){}
  24. ExprItem::~ExprItem(){}
  25.  
  26. //___________________________________________________________ ValueItem
  27.  
  28. ValueItem::ValueItem(const Value& val) : v(val){}
  29. ValueItem::ValueItem(Value* val) : v(*val){}
  30. ValueItem::~ValueItem(){}
  31. void ValueItem::process(ValueStack* theStack) { theStack->push(v); }
  32. void ValueItem::print(ValueStack* theStack) { theStack->push(v); }
  33. int ValueItem::params() { return 0; }
  34. ExprItem* ValueItem::copy() { return new ValueItem(v); }
  35.  
  36. //___________________________________________________________ Expression
  37.  
  38. Expression::Expression()
  39. : theExpression(new ExprItemList),
  40.   theStack(new ValueStack)
  41. {}
  42.  
  43. Expression::Expression(ExprItem* oneItem)
  44. : theExpression(new ExprItemList(1)),
  45.   theStack(new ValueStack)
  46. {
  47.   theExpression->append(oneItem);
  48. }
  49.  
  50. Expression::Expression(const Expression& expr)
  51. :theExpression(new ExprItemList(expr.theExpression->count())),
  52.  theStack(new ValueStack)
  53. {  
  54.   for (register long i=0; i<expr.theExpression->count(); i++)
  55.     theExpression->append(expr.theExpression->item(i)->copy());
  56. }
  57.  
  58. // constructor for functions and unary operators 
  59. //  expression op will be deleted
  60. Expression::Expression(ExprItem* oper, Expression* op)
  61. :theExpression(new ExprItemList(op->theExpression->count()+1)),
  62.  theStack(new ValueStack)
  63. {
  64.   for (register long i=0; i<op->theExpression->count();i++)
  65.     theExpression->append(op->theExpression->item(i)->copy());
  66.   theExpression->append(oper);
  67.  
  68.   delete op;
  69. }
  70.  
  71. // constructors for binary operators, changes the order of the arguments!
  72. //  expressions op1, op2 will be deleted
  73. Expression::Expression(ExprItem* oper, Expression* op1, Expression* op2)
  74. :theExpression(new ExprItemList(100)),
  75.  theStack(new ValueStack)
  76. {
  77.   register long i;
  78.  
  79.   // 'op2 op1 oper' will be the resulting expression list
  80.   for (i=0; i<op2->theExpression->count(); i++)
  81.     theExpression->append(op2->theExpression->item(i)->copy());
  82.   for (i=0; i<op1->theExpression->count(); i++)
  83.     theExpression->append(op1->theExpression->item(i)->copy());
  84.   theExpression->append(oper);
  85.  
  86.   delete op1;  delete op2;
  87. }
  88.  
  89. // constructors for ternary operators, changes the order of the arguments!
  90. //  expressions op1, op2, op3 will be deleted
  91. Expression::Expression(ExprItem* oper, 
  92.                Expression* op1, Expression* op2, Expression* op3)
  93. :theExpression(new ExprItemList(100)),
  94.  theStack(new ValueStack)
  95. {
  96.   register long i;
  97.  
  98.   // 'op3 op2 op1 oper' will be the resulting expression list
  99.   for (i=0; i<op3->theExpression->count(); i++)
  100.     theExpression->append(op3->theExpression->item(i)->copy());
  101.   for (i=0; i<op2->theExpression->count(); i++)
  102.     theExpression->append(op2->theExpression->item(i)->copy());
  103.   for (i=0; i<op1->theExpression->count(); i++)
  104.     theExpression->append(op1->theExpression->item(i)->copy());
  105.   theExpression->append(oper);
  106.  
  107.   delete op1;  delete op2; delete op3;
  108. }
  109.  
  110. Expression::~Expression()
  111. {
  112. #ifndef OLD_STYLE_CPP
  113.   for (register long i=0; i<theExpression->count(); i++)
  114.     delete theExpression->item(i);
  115. #endif
  116.   delete theExpression;
  117.  
  118.   delete theStack;
  119. }
  120.  
  121. // evaluating an expression is simple, cause each ExprItem knows 
  122. //  what to do
  123. Value& Expression::evaluate()
  124. {
  125.   theStack->clear();
  126.   for (register long i=0; i<theExpression->count(); i++)
  127.     theExpression->item(i)->process(theStack);
  128.  
  129.   return theStack->pop();
  130. }
  131.  
  132. // simplify the constant subexpressions of the expression
  133. //  e.g. 2 3 + a * -> 5 a *
  134. Expression* Expression::simplify()
  135. {
  136.   int paraminrow = 0;  // number of constant parameters in row
  137.  
  138.   for (register long i=0; i<theExpression->count(); i++) {
  139.     int num = theExpression->item(i)->params();
  140.  
  141.     // no simplification is possible, i.e. a variable
  142.     if (num < 0) 
  143.       paraminrow = 0;
  144.     // the current ExprItem needs more constant arguments than present
  145.     else if (num > paraminrow)
  146.       paraminrow = 0;
  147.     // simplification is possible
  148.     else {
  149.       Expression tmpExpr;
  150.  
  151.       paraminrow = paraminrow-num+1;
  152.  
  153.       // build up the subexpression an replace it by its result
  154.       for (int j=0; j <= num; j++) {
  155.     tmpExpr.theExpression->prepend(theExpression->item(i));
  156.     theExpression->remove(i--);
  157.       }
  158.       theExpression->insert(++i, new ValueItem(tmpExpr.evaluate()));
  159.     }
  160.   }
  161.  
  162.   return this;
  163. }
  164.  
  165. // Construct a string by executing the print member function of each 
  166. //  ExprItem. The result is a infix notation of the expression.
  167. ostream& operator<< (ostream& os, const Expression& expr)
  168. {
  169.   expr.theStack->clear();
  170.   for (register long i=0; i<expr.theExpression->count(); i++)
  171.     expr.theExpression->item(i)->print(expr.theStack);
  172.  
  173.   return os << (rcString)expr.theStack->pop();
  174. }
  175.