home *** CD-ROM | disk | FTP | other *** search
- /*
- * Expression.C - methods to evaluate and handle arithmetic expressions.
- *
- * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
- * University of Berne, Switzerland
- * All rights reserved.
- *
- * This software may be freely copied, modified, and redistributed
- * provided that this copyright notice is preserved on all copies.
- *
- * You may not distribute this software, in whole or in part, as part of
- * any commercial product without the express consent of the authors.
- *
- * There is no warranty or other guarantee of fitness of this software
- * for any purpose. It is provided solely "as is".
- *
- */
-
- #include "Expression.h"
-
- //___________________________________________________________ ExprItem
-
- implementList(ExprItemList, ExprItemPtr);
- ExprItem::ExprItem(){}
- ExprItem::~ExprItem(){}
-
- //___________________________________________________________ ValueItem
-
- ValueItem::ValueItem(const Value& val) : v(val){}
- ValueItem::ValueItem(Value* val) : v(*val){}
- ValueItem::~ValueItem(){}
- void ValueItem::process(ValueStack* theStack) { theStack->push(v); }
- void ValueItem::print(ValueStack* theStack) { theStack->push(v); }
- int ValueItem::params() { return 0; }
- ExprItem* ValueItem::copy() { return new ValueItem(v); }
-
- //___________________________________________________________ Expression
-
- Expression::Expression()
- : theExpression(new ExprItemList),
- theStack(new ValueStack)
- {}
-
- Expression::Expression(ExprItem* oneItem)
- : theExpression(new ExprItemList(1)),
- theStack(new ValueStack)
- {
- theExpression->append(oneItem);
- }
-
- Expression::Expression(const Expression& expr)
- :theExpression(new ExprItemList(expr.theExpression->count())),
- theStack(new ValueStack)
- {
- for (register long i=0; i<expr.theExpression->count(); i++)
- theExpression->append(expr.theExpression->item(i)->copy());
- }
-
- // constructor for functions and unary operators
- // expression op will be deleted
- Expression::Expression(ExprItem* oper, Expression* op)
- :theExpression(new ExprItemList(op->theExpression->count()+1)),
- theStack(new ValueStack)
- {
- for (register long i=0; i<op->theExpression->count();i++)
- theExpression->append(op->theExpression->item(i)->copy());
- theExpression->append(oper);
-
- delete op;
- }
-
- // constructors for binary operators, changes the order of the arguments!
- // expressions op1, op2 will be deleted
- Expression::Expression(ExprItem* oper, Expression* op1, Expression* op2)
- :theExpression(new ExprItemList(100)),
- theStack(new ValueStack)
- {
- register long i;
-
- // 'op2 op1 oper' will be the resulting expression list
- #ifdef AMIGA_GCC
- for (i=0; i<op1->theExpression->count(); i++)
- theExpression->append(op1->theExpression->item(i)->copy());
- for (i=0; i<op2->theExpression->count(); i++)
- theExpression->append(op2->theExpression->item(i)->copy());
- theExpression->append(oper);
- #else
- for (i=0; i<op2->theExpression->count(); i++)
- theExpression->append(op2->theExpression->item(i)->copy());
- for (i=0; i<op1->theExpression->count(); i++)
- theExpression->append(op1->theExpression->item(i)->copy());
- theExpression->append(oper);
- #endif
-
- delete op1; delete op2;
- }
-
- // constructors for ternary operators, changes the order of the arguments!
- // expressions op1, op2, op3 will be deleted
- Expression::Expression(ExprItem* oper,
- Expression* op1, Expression* op2, Expression* op3)
- :theExpression(new ExprItemList(100)),
- theStack(new ValueStack)
- {
- register long i;
-
- // 'op3 op2 op1 oper' will be the resulting expression list
- #ifdef AMIGA_GCC
- for (i=0; i<op1->theExpression->count(); i++)
- theExpression->append(op1->theExpression->item(i)->copy());
- for (i=0; i<op2->theExpression->count(); i++)
- theExpression->append(op2->theExpression->item(i)->copy());
- for (i=0; i<op3->theExpression->count(); i++)
- theExpression->append(op3->theExpression->item(i)->copy());
- theExpression->append(oper);
- #else
- for (i=0; i<op3->theExpression->count(); i++)
- theExpression->append(op3->theExpression->item(i)->copy());
- for (i=0; i<op2->theExpression->count(); i++)
- theExpression->append(op2->theExpression->item(i)->copy());
- for (i=0; i<op1->theExpression->count(); i++)
- theExpression->append(op1->theExpression->item(i)->copy());
- theExpression->append(oper);
- #endif
-
- delete op1; delete op2; delete op3;
- }
-
- Expression::~Expression()
- {
- #ifndef OLD_STYLE_CPP
- for (register long i=0; i<theExpression->count(); i++)
- delete theExpression->item(i);
- #endif
- delete theExpression;
-
- delete theStack;
- }
-
- // evaluating an expression is simple, cause each ExprItem knows
- // what to do
- Value& Expression::evaluate()
- {
- theStack->clear();
- for (register long i=0; i<theExpression->count(); i++)
- theExpression->item(i)->process(theStack);
-
- return theStack->pop();
- }
-
- // simplify the constant subexpressions of the expression
- // e.g. 2 3 + a * -> 5 a *
- Expression* Expression::simplify()
- {
- int paraminrow = 0; // number of constant parameters in row
-
- for (register long i=0; i<theExpression->count(); i++) {
- int num = theExpression->item(i)->params();
-
- // no simplification is possible, i.e. a variable
- if (num < 0)
- paraminrow = 0;
- // the current ExprItem needs more constant arguments than present
- else if (num > paraminrow)
- paraminrow = 0;
- // simplification is possible
- else {
- Expression tmpExpr;
-
- paraminrow = paraminrow-num+1;
-
- // build up the subexpression an replace it by its result
- for (int j=0; j <= num; j++) {
- tmpExpr.theExpression->prepend(theExpression->item(i));
- theExpression->remove(i--);
- }
- theExpression->insert(++i, new ValueItem(tmpExpr.evaluate()));
- }
- }
-
- return this;
- }
-
- // Construct a string by executing the print member function of each
- // ExprItem. The result is a infix notation of the expression.
- ostream& operator<< (ostream& os, const Expression& expr)
- {
- expr.theStack->clear();
- for (register long i=0; i<expr.theExpression->count(); i++)
- expr.theExpression->item(i)->print(expr.theStack);
-
- return os << (rcString)expr.theStack->pop();
- }
-