#ifndef __EXPR_H #define __EXPR_H class Expr; class Expr { public: DWORD marker; // A parameter, by the hParam handle static const int PARAM = 0; // A parameter, by a pointer straight in to the param table (faster, // if we know that the param table won't move around) static const int PARAM_PTR = 1; // These are used only for user-entered expressions. static const int POINT = 10; static const int ENTITY = 11; static const int CONSTANT = 20; static const int PLUS = 100; static const int MINUS = 101; static const int TIMES = 102; static const int DIV = 103; static const int NEGATE = 104; static const int SQRT = 105; static const int SQUARE = 106; static const int SIN = 107; static const int COS = 108; // Special helpers for when we're parsing an expression from text. // Initially, literals (like a constant number) appear in the same // format as they will in the finished expression, but the operators // are different until the parser fixes things up (and builds the // tree from the flat list that the lexer outputs). static const int ALL_RESOLVED = 1000; static const int PAREN = 1001; static const int BINARY_OP = 1002; static const int UNARY_OP = 1003; int op; Expr *a; Expr *b; union { double v; hParam parh; Param *parp; hEntity entity; // For use while parsing char c; } x; static inline Expr *AllocExpr(void) { return (Expr *)AllocTemporary(sizeof(Expr)); } static Expr *From(hParam p); static Expr *From(double v); Expr *AnyOp(int op, Expr *b); inline Expr *Plus (Expr *b) { return AnyOp(PLUS, b); } inline Expr *Minus(Expr *b) { return AnyOp(MINUS, b); } inline Expr *Times(Expr *b) { return AnyOp(TIMES, b); } inline Expr *Div (Expr *b) { return AnyOp(DIV, b); } inline Expr *Negate(void) { return AnyOp(NEGATE, NULL); } inline Expr *Sqrt (void) { return AnyOp(SQRT, NULL); } inline Expr *Square(void) { return AnyOp(SQUARE, NULL); } inline Expr *Sin (void) { return AnyOp(SIN, NULL); } inline Expr *Cos (void) { return AnyOp(COS, NULL); } Expr *PartialWrt(hParam p); double Eval(void); DWORD ParamsUsed(void); static bool Tol(double a, double b); Expr *FoldConstants(void); void Substitute(hParam oldh, hParam newh); void ParamsToPointers(void); void App(char *str, ...); char *Print(void); void PrintW(void); // worker // Make a copy of an expression that won't get blown away when we // do a FreeAllExprs(), or free it later. Expr *DeepCopyKeep(void); static void FreeKeep(Expr **f); // or a copy that will Expr *DeepCopy(void); // number of child nodes: 0 (e.g. constant), 1 (sqrt), or 2 (+) int Children(void); // Make a copy, with the parameters (usually referenced by hParam) // resolved to pointers to the actual value. This speeds things up // considerably. Expr *DeepCopyWithParamsAsPointers(IdList *firstTry, IdList *thenTry); static Expr *From(char *in); static void Lex(char *in); static Expr *Next(void); static void Consume(void); static void PushOperator(Expr *e); static Expr *PopOperator(void); static Expr *TopOperator(void); static void PushOperand(Expr *e); static Expr *PopOperand(void); static void Reduce(void); static void ReduceAndPush(Expr *e); static int Precedence(Expr *e); static int Precedence(int op); static void Parse(void); }; class ExprVector { public: Expr *x, *y, *z; static ExprVector From(Expr *x, Expr *y, Expr *z); static ExprVector From(Vector vn); static ExprVector From(hParam x, hParam y, hParam z); ExprVector Plus(ExprVector b); ExprVector Minus(ExprVector b); Expr *Dot(ExprVector b); ExprVector Cross(ExprVector b); ExprVector ScaledBy(Expr *s); Expr *Magnitude(void); Vector Eval(void); }; class ExprQuaternion { public: Expr *w, *vx, *vy, *vz; static ExprQuaternion From(Expr *w, Expr *vx, Expr *vy, Expr *vz); static ExprQuaternion From(Quaternion qn); ExprVector RotationU(void); ExprVector RotationV(void); ExprVector RotationN(void); ExprVector Rotate(ExprVector p); ExprQuaternion Times(ExprQuaternion b); Expr *Magnitude(void); }; #endif