home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / oct93 / graphics / graphtal.lha / Graphtal / Expression.C < prev    next >
C/C++ Source or Header  |  1993-08-26  |  6KB  |  194 lines

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