Statistics
| Branch: | Revision:

root / src / common / expression.h @ e1750c09

History | View | Annotate | Download (12.4 KB)

1 01873262 Georg Kunz
//==========================================================================
2
//  EXPRESSION.H  - part of
3
//                     OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//  Author: Andras Varga
7
//
8
//==========================================================================
9
10
/*--------------------------------------------------------------*
11
  Copyright (C) 2006-2008 OpenSim Ltd.
12

13
  This file is distributed WITHOUT ANY WARRANTY. See the file
14
  `license' for details on this and other legal matters.
15
*--------------------------------------------------------------*/
16
17
#ifndef __EXPRESSION_H
18
#define __EXPRESSION_H
19
20
#include <string>
21
#include "commondefs.h"
22
#include "commonutil.h"
23
#include "stringutil.h"
24
25
NAMESPACE_BEGIN
26
27
/**
28
 * This is an extensible arithmetic expression evaluator class. Supports the
29
 * following data types: long, double, string, bool.
30
 *
31
 * The code is based on the simkernel's expression evaluator, with a number of
32
 * modifications:
33
 *   - no dependence on simkernel classes (cPar, cComponent, cRuntimeError, etc)
34
 *   - no support for NED constructs (sizeof(), index, this, default(), etc)
35
 *   - no support for xmldoc() and the XML data type
36
 *   - "unit" support for numeric values removed
37
 *   - does not use stringpool
38
 *   - added resolver
39
 *   - $ and @ accepted in identifier names
40
 */
41
class COMMON_API Expression
42
{
43
  public:
44
    /**
45
     * Operations supported by this class:
46
     *  - add, subtract, multiply, divide ("+" is also string concatenation)
47
     *  - modulo, power of, negation (-1)
48
     *  - equal, not equal, greater, greater or equal, less, less or equal
49
     *  - inline if (the C/C++ ?: operator)
50
     *  - logical and, or, xor, not
51
     *  - bitwise and, or, xor, not (1's complement)
52
     *  - left shift, right shift
53
     */
54
    enum OpType {
55
        ADD, SUB, MUL, DIV, MOD, POW, NEG,
56
        EQ, NE, GT, GE, LT, LE, IIF, AND, OR, XOR, NOT,
57
        BIN_AND, BIN_OR, BIN_XOR, BIN_NOT, LSHIFT, RSHIFT
58
    };
59
60
    class Functor; // forward decl
61
62
    /**
63
     * One element in a (reverse Polish) expression
64
     */
65
    class Elem
66
    {
67
      friend class Expression;
68
      public:
69
        // Types:
70
        //  - bool
71
        //  - double (there is no long -- we calculate everything in double)
72
        //  - string
73
        //  - math operator (+-*/%^...)
74
        //  - functor
75
        //
76
        enum Type {UNDEF, BOOL, DBL, STR, FUNCTOR, OP};
77
      private:
78
        Type type;
79
        union {
80
            bool b;
81
            double d;
82
            char *s;
83
            Functor *fu;
84
            OpType op;
85
        };
86
87
      private:
88
        void deleteOld() { // note: when defined in .cc file, VC++ linker won't find it from the envir lib
89
            if (type==STR)
90
                delete [] s;
91
            else if (type==FUNCTOR)
92
                delete fu;
93
        }
94
95
      public:
96
        Elem()  {type=UNDEF;}
97
        Elem(const Elem& other)  {type=UNDEF; operator=(other);}
98
        ~Elem() {deleteOld();}
99
100
        /** @name Getters */
101
        //@{
102
        Type getType() const {return type;}
103
        bool getBool() const {Assert(type==BOOL); return b;}
104
        double getDouble() const {Assert(type==DBL); return d;}
105
        const char *getString() const {Assert(type==STR); return s;}
106
        Functor *getFunctor() const {Assert(type==FUNCTOR); return fu;}
107
        OpType getOp() const {Assert(type==OP); return op;}
108
        //@}
109
110
        /**
111
         * Assignment operator -- we need to copy Elem at a hundred places
112
         */
113
        void operator=(const Elem& other) {Elem_eq(*this, other);}
114
115
        /**
116
         * Effect during evaluation of the expression: pushes the given boolean
117
         * constant to the evaluation stack.
118
         */
119
        void operator=(bool _b)  {type=BOOL; b=_b;}
120
121
        /**
122
         * Effect during evaluation of the expression: pushes the given number
123
         * (which is converted to double) to the evaluation stack.
124
         */
125
        void operator=(int _i)  {type=DBL; d=_i;}
126
127
        /**
128
         * Effect during evaluation of the expression: pushes the given number
129
         * (which is converted to double) to the evaluation stack.
130
         */
131
        void operator=(short _i)  {type=DBL; d=_i;}
132
133
        /**
134
         * Effect during evaluation of the expression: pushes the given number
135
         * (which is converted to double) to the evaluation stack.
136
         */
137
        void operator=(long _l)  {type=DBL; d=_l;}
138
139
        /**
140
         * Effect during evaluation of the expression: pushes the given number
141
         * to the evaluation stack.
142
         */
143
        void operator=(double _d)  {type=DBL; d=_d;}
144
145
        /**
146
         * Effect during evaluation of the expression: pushes the given string
147
         * to the evaluation stack.
148
         */
149
        void operator=(const char *_s)  {type=STR; Assert(_s); s=opp_strdup(_s);}
150
151
        /**
152
         * Function object, with an interface not unlike cNEDFunction.
153
         * This object will be deleted by expression's destructor.
154
         */
155
        void operator=(Functor *_f)  {type=FUNCTOR; Assert(_f); fu=_f;}
156
157
        /**
158
         * Unary, binary or tertiary (?: only) operations.
159
         */
160
        void operator=(OpType _op)  {type=OP; op=_op;}
161
162
        /**
163
         * Utility function, returns the argument count of this element.
164
         * I.e. returns 0 for BOOL, DBL, STRING and zero-arg Functors,
165
         * returns 1 for a one-arg Functors, and returns 2 for most operators.
166
         */
167
        int getNumArgs() const {return Elem_getNumArgs(*this);}
168
169
        /**
170
         * Debug string.
171
         */
172
        std::string str() const { return Elem_str(type,b,d,s,fu,op);}
173
    };
174
175
    /**
176
     * The dynamic expression evaluator calculates in Values.
177
     * There is no "long" field in it: all numeric calculations are performed
178
     * in double. XXX This is fine for 32-bit longs, but not for 64-bit ones,
179
     * as double's mantissa is only 53 bits.
180
     */
181
    struct Value
182
    {
183
        enum {UNDEF=0, BOOL='B', DBL='D', STR='S'} type;
184
        bool bl;
185
        double dbl;
186
        std::string s;
187
188
        Value()  {type=UNDEF;}
189
        Value(bool b)  {*this=b;}
190
        Value(long l)  {*this=l;}
191
        Value(double d)  {*this=d;}
192
        Value(const char *s)  {*this=s;}
193
        Value(const std::string& s)  {*this=s;}
194
        void operator=(bool b)  {type=BOOL; bl=b;}
195
        void operator=(long l)  {type=DBL; dbl=l;}
196
        void operator=(double d)  {type=DBL; dbl=d;}
197
        void operator=(const char *s)  {type=STR; this->s=s?s:"";}
198
        void operator=(const std::string& s)  {type=STR; this->s=s;}
199
        std::string str();
200
    };
201
202
    /**
203
     * Function object base class. They can be used to implement variables, etc.
204
     */
205
    class Functor
206
    {
207
      public:
208
        virtual ~Functor() {}
209
        virtual Functor *dup() const = 0;
210
        virtual const char *getName() const = 0;
211
        virtual const char *getArgTypes() const = 0;
212
        virtual int getNumArgs() const {return strlen(getArgTypes());}
213
        virtual char getReturnType() const = 0;
214
        virtual Value evaluate(Value args[], int numargs) = 0;
215
        virtual std::string str(std::string args[], int numargs) = 0;
216
    };
217
218
    /**
219
     * A functor subclass that implements a variable; still an abstract class.
220
     */
221
    class Variable : public Functor
222
    {
223
      public:
224
        virtual const char *getArgTypes() const {return "";}
225
        virtual int getNumArgs() const {return 0;}
226
        virtual std::string str(std::string args[], int numargs) {return getName();}
227
    };
228
229
    /**
230
     * A functor subclass that implements a function; still an abstract class.
231
     */
232
    class Function : public Functor
233
    {
234
      public:
235
        // returns name(arg1,arg2,...)
236
        virtual std::string str(std::string args[], int numargs) {return Function_str(getName(), args, numargs);}
237
    };
238
239
    /**
240
     * Abstract base class for variable and function resolvers. A resolver
241
     * is used during parsing, and tells the parser how to convert variable
242
     * references and functions into Functor objects for the stored
243
     * expression. Methods should throw an exception with a human-readable
244
     * description when the variable or function cannot be resolved; this will
245
     * be converted to an error message.
246
     */
247
    class Resolver
248
    {
249
      public:
250
        virtual ~Resolver() {}
251
        virtual Functor *resolveVariable(const char *varname) = 0;
252
        virtual Functor *resolveFunction(const char *funcname, int argcount) = 0;
253
    };
254
255
  protected:
256
    Elem *elems;
257
    int nelems;
258
259
    // workaround: when calling out-of-line methods of inner classes (Elem, Function etc)
260
    // from the Envir lib, VC++ 9.0 linker reports them as undefined symbols; workaround
261
    // is to delegate them to Expression.
262
    static void Elem_eq(Elem& e, const Elem& other);
263
    static int Elem_getNumArgs(const Elem& e);
264
    static std::string Elem_str(int type, bool b, double d, const char *s, Functor *fu, int op);
265
    static std::string Function_str(const char *name, std::string args[], int numargs);
266
267
  public:
268
    /** @name Constructors, destructor, assignment. */
269
    //@{
270
271
    /**
272
     * Constructor.
273
     */
274
    Expression();
275
276
    /**
277
     * Copy constructor.
278
     */
279
    Expression(const Expression& other) {elems=NULL; operator=(other);}
280
281
    /**
282
     * Destructor.
283
     */
284
    virtual ~Expression();
285
286
    /**
287
     * Assignment operator.
288
     */
289
    Expression& operator=(const Expression& other);
290
    //@}
291
292
    /** @name Setter and evaluator methods. */
293
    //@{
294
    /**
295
     * Sets the Reverse Polish expression to evaluate. The array must be a
296
     * dynamically allocated one, and will be deleted by this object.
297
     * No verification is performed on the expression at this time.
298
     */
299
    virtual void setExpression(Elem e[], int nelems);
300
301
    /**
302
     * Returns the Reverse Polish expression as an array of Elems.
303
     * The array size is getExpressionLength().
304
     */
305
    virtual const Elem *getExpression() const {return elems;}
306
307
    /**
308
     * Returns the length of the array that contains the Reverse Polish
309
     * expression. The array is returned by getExpression().
310
     */
311
    virtual int getExpressionLength() const {return nelems;}
312
313
    /**
314
     * Evaluate the expression, and return the results as a Value.
315
     * Throws an error if the expression has some problem (i.e. stack
316
     * overflow/underflow, "cannot cast", "function not found", etc.)
317
     */
318
    virtual Value evaluate() const;
319
320
    /**
321
     * Evaluate the expression and convert the result to bool if possible;
322
     * throw an error if conversion from that type is not supported.
323
     */
324
    virtual bool boolValue();
325
326
    /**
327
     * Evaluate the expression and convert the result to long if possible;
328
     * throw an error if conversion from that type is not supported.
329
     */
330
    virtual long longValue();
331
332
    /**
333
     * Evaluate the expression and convert the result to double if possible;
334
     * throw an error if conversion from that type is not supported.
335
     */
336
    virtual double doubleValue();
337
338
    /**
339
     * Evaluate the expression and convert the result to string if possible;
340
     * throw an error if conversion from that type is not supported.
341
     */
342
    virtual std::string stringValue();
343
    //@}
344
345
    /** @name Miscellaneous utility functions. */
346
    //@{
347
    /**
348
     * Converts the expression to string.
349
     */
350
    virtual std::string str() const;
351
352
    /**
353
     * Interprets the string as an expression, and stores it. Resolver
354
     * is used for translating variable and function references during
355
     * parsing. Throws exception on parse errors.
356
     */
357
    virtual void parse(const char *text, Resolver *resolver);
358
359
    /**
360
     * Returns true if the expression is just a literal (or equivalent to one,
361
     * like "2+2").
362
     */
363
    virtual bool isAConstant() const;
364
    //@}
365
};
366
367
368
/**
369
 * Function object to implement all math.h functions.
370
 */
371
class COMMON_API MathFunction : public Expression::Function
372
{
373
  private:
374
    std::string funcname;
375
    double (*f)(...);
376
    int argcount;
377
  public:
378
    struct FuncDesc {const char *name; double (*f)(...); int argcount;};
379
  private:
380
    static FuncDesc functable[];
381
    static FuncDesc *lookup(const char *name);
382
  public:
383
    static bool supports(const char *name);
384
    MathFunction(const char *name);
385
    virtual ~MathFunction();
386
    virtual Functor *dup() const;
387
    virtual const char *getName() const;
388
    virtual const char *getArgTypes() const;
389
    virtual char getReturnType() const;
390
    virtual Expression::Value evaluate(Expression::Value args[], int numargs);
391
};
392
393
NAMESPACE_END
394
395
396
#endif
397