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