Statistics
| Branch: | Revision:

root / src / sim / expr.y @ e26d3d25

History | View | Annotate | Download (10.2 KB)

1 01873262 Georg Kunz
/*===============================================================
2
 * File: expr.y
3
 *
4
 *  Grammar for OMNeT++ NED-2 expressions.
5
 *
6
 *  Author: Andras Varga
7
 *
8
 *=============================================================*/
9
10
/*--------------------------------------------------------------*
11
  Copyright (C) 1992,2005 Andras Varga
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
/* Reserved words */
18
%token DOUBLETYPE INTTYPE STRINGTYPE BOOLTYPE XMLTYPE
19
%token TRUE_ FALSE_ THIS_ ASK_ DEFAULT_ CONST_ SIZEOF_ INDEX_ XMLDOC_
20
21
/* Other tokens: identifiers, numeric literals, operators etc */
22
%token NAME INTCONSTANT REALCONSTANT STRINGCONSTANT
23
%token EQ_ NE_ GE_ LE_
24
%token AND_ OR_ XOR_ NOT_
25
%token BINAND_ BINOR_ BINXOR_ BINCOMPL_
26
%token SHIFTLEFT_ SHIFTRIGHT_
27
28
%token INVALID_CHAR   /* just to generate parse error */
29
30
/* Operator precedences (low to high) and associativity */
31
%left '?' ':'
32
%left AND_ OR_ XOR_
33
%left EQ_ NE_ '>' GE_ '<' LE_
34
%left BINAND_ BINOR_ BINXOR_
35
%left SHIFTLEFT_ SHIFTRIGHT_
36
%left '+' '-'
37
%left '*' '/' '%'
38
%right '^'
39
%left UMIN_ NOT_ BINCOMPL_
40
41
%start expression
42
43
%{
44
45
#include <stdio.h>
46
#include <stdlib.h>
47
#include "expryydefs.h"
48
#include "commonutil.h"
49
50
#define YYDEBUG 1           /* allow debugging */
51
#define YYDEBUGGING_ON 0    /* turn on/off debugging */
52
53
#if YYDEBUG != 0
54
#define YYERROR_VERBOSE     /* more detailed error messages */
55
#include <string.h>         /* YYVERBOSE needs it */
56
#endif
57
58
#define yyin expryyin
59
#define yyout expryyout
60
#define yyrestart expryyrestart
61
#define yy_scan_string expryy_scan_string
62
#define yy_delete_buffer expryy_delete_buffer
63
extern FILE *yyin;
64
extern FILE *yyout;
65
struct yy_buffer_state;
66
struct yy_buffer_state *yy_scan_string(const char *str);
67
void yy_delete_buffer(struct yy_buffer_state *);
68
void yyrestart(FILE *);
69
int yylex();
70
void yyerror (const char *s);
71
72
LineColumn xpos, xprevpos;
73
74
75
#include "cdynamicexpression.h"
76
#include "cpar.h"
77
#include "cxmlelement.h"
78
#include "cexception.h"
79
#include "globals.h"
80
#include "cmathfunction.h"
81
#include "cnedfunction.h"
82
#include "nedsupport.h"
83
#include "stringutil.h"
84
#include "unitconversion.h"
85
86
USING_NAMESPACE
87
88
static cDynamicExpression::Elem *e;
89
90
static char *expryyconcat(char *s1, char *s2, char *s3=NULL)
91
{
92
    char *d = new char[strlen(s1)+strlen(s2)+strlen(s3?s3:"")+4];
93
    strcpy(d, s1);
94
    strcat(d, " ");
95
    strcat(d, s2);
96
    if (s3) {strcat(d, " "); strcat(d, s3);}
97
    delete [] s1; delete [] s2; delete [] s3;
98
    return d;
99
}
100
101
static void addFunction(const char *funcname, int argcount)
102
{
103
    cMathFunction *f = cMathFunction::find(funcname, argcount);
104
    if (f) {
105
        *e++ = f;
106
        return;
107
    }
108
    cNEDFunction *nf = cNEDFunction::find(funcname, argcount);
109
    if (nf) {
110
        (e++)->set(nf,argcount);
111
        return;
112
    }
113
    yyerror(opp_stringf("function `%s' with %d args not found (Define_NED_Function() missing from C++ code?)", funcname, argcount).c_str());
114
}
115
116
static double parseQuantity(const char *text, std::string& unit)
117
{
118
    try {
119
        // evaluate quantities like "5s 230ms"
120
        return UnitConversion::parseQuantity(text, unit);
121
    }
122
    catch (std::exception& e) {
123
        yyerror(e.what());
124
        return 0;
125
    }
126
}
127
128
%}
129
130
%%
131
132
expression
133
        : expr
134
        | xmldocvalue
135
        | ASK_
136
                { yyerror("\"ask\" is not supported here"); }
137
        | DEFAULT_
138
                { yyerror("\"default\" is not supported here"); }
139
        | DEFAULT_ '(' expr ')'
140
                { yyerror("\"default()\" is not supported here"); }
141
        ;
142
143
xmldocvalue
144
        : XMLDOC_ '(' expr ')'
145
                { *e++ = new NEDSupport::XMLDoc(false); }
146
        | XMLDOC_ '(' expr ',' expr ')'
147
                { *e++ = new NEDSupport::XMLDoc(true); }
148
        ;
149
150
expr
151
        : simple_expr
152
        | '(' expr ')'
153
        | CONST_ '(' expr ')'
154
                { yyerror("const() is not supported here"); }
155
156
        | expr '+' expr
157
                { *e++ = cDynamicExpression::ADD; }
158
        | expr '-' expr
159
                { *e++ = cDynamicExpression::SUB; }
160
        | expr '*' expr
161
                { *e++ = cDynamicExpression::MUL; }
162
        | expr '/' expr
163
                { *e++ = cDynamicExpression::DIV; }
164
        | expr '%' expr
165
                { *e++ = cDynamicExpression::MOD; }
166
        | expr '^' expr
167
                { *e++ = cDynamicExpression::POW; }
168
169
        | '-' expr
170
                %prec UMIN_
171
                { *e++ = cDynamicExpression::NEG; }
172
173
        | expr EQ_ expr
174
                { *e++ = cDynamicExpression::EQ; }
175
        | expr NE_ expr
176
                { *e++ = cDynamicExpression::NE; }
177
        | expr '>' expr
178
                { *e++ = cDynamicExpression::GT; }
179
        | expr GE_ expr
180
                { *e++ = cDynamicExpression::GE; }
181
        | expr '<' expr
182
                { *e++ = cDynamicExpression::LT; }
183
        | expr LE_ expr
184
                { *e++ = cDynamicExpression::LE; }
185
186
        | expr AND_ expr
187
                { *e++ = cDynamicExpression::AND; }
188
        | expr OR_ expr
189
                { *e++ = cDynamicExpression::OR; }
190
        | expr XOR_ expr
191
                { *e++ = cDynamicExpression::XOR; }
192
193
        | NOT_ expr
194
                %prec UMIN_
195
                { *e++ = cDynamicExpression::NOT; }
196
197
        | expr BINAND_ expr
198
                { *e++ = cDynamicExpression::BIN_AND; }
199
        | expr BINOR_ expr
200
                { *e++ = cDynamicExpression::BIN_OR; }
201
        | expr BINXOR_ expr
202
                { *e++ = cDynamicExpression::BIN_XOR; }
203
204
        | BINCOMPL_ expr
205
                %prec UMIN_
206
                { *e++ = cDynamicExpression::BIN_NOT; }
207
        | expr SHIFTLEFT_ expr
208
                { *e++ = cDynamicExpression::LSHIFT; }
209
        | expr SHIFTRIGHT_ expr
210
                { *e++ = cDynamicExpression::RSHIFT; }
211
        | expr '?' expr ':' expr
212
                { *e++ = cDynamicExpression::IIF; }
213
214
        | INTTYPE '(' expr ')'
215
                { addFunction("int",1); }
216
        | DOUBLETYPE '(' expr ')'
217
                { addFunction("double",1); }
218
        | STRINGTYPE '(' expr ')'
219
                { addFunction("string",1); }
220
221
        | NAME '(' ')'
222
                { addFunction($1,0); delete [] $1; }
223
        | NAME '(' expr ')'
224
                { addFunction($1,1); delete [] $1; }
225
        | NAME '(' expr ',' expr ')'
226
                { addFunction($1,2); delete [] $1; }
227
        | NAME '(' expr ',' expr ',' expr ')'
228
                { addFunction($1,3); delete [] $1; }
229
        | NAME '(' expr ',' expr ',' expr ',' expr ')'
230
                { addFunction($1,4); delete [] $1; }
231
         ;
232
233
simple_expr
234
        : identifier
235
        | special_expr
236
        | literal
237
        ;
238
239
identifier
240
        : NAME
241
                { *e++ = new NEDSupport::ParameterRef($1, true, false); delete [] $1; }
242
        | THIS_ '.' NAME
243
                { *e++ = new NEDSupport::ParameterRef($3, false, true); delete [] $3; }
244
        | NAME '.' NAME
245
                { *e++ = new NEDSupport::SiblingModuleParameterRef($1, $3, true, false); delete [] $1; delete [] $3; }
246
        | NAME '[' expression ']' '.' NAME
247
                { *e++ = new NEDSupport::SiblingModuleParameterRef($1, $6, true, true); delete [] $1; delete [] $6; }
248
        ;
249
250
special_expr
251
        : INDEX_
252
                { *e++ = new NEDSupport::ModuleIndex(); }
253
        | INDEX_ '(' ')'
254
                { *e++ = new NEDSupport::ModuleIndex(); }
255
        | SIZEOF_ '(' NAME ')'
256
                { *e++ = new NEDSupport::Sizeof($3, true, false); delete [] $3; }
257
        | SIZEOF_ '(' THIS_ '.' NAME ')'
258
                { *e++ = new NEDSupport::Sizeof($5, false, false); delete [] $5; }
259
        | SIZEOF_ '(' NAME '.' NAME ')'
260
                { delete [] $3; delete [] $5; yyerror("sizeof(submodule.gate) notation not supported here"); }
261
        | SIZEOF_ '(' NAME '[' expression ']' '.' NAME ')'
262
                { delete [] $3; delete [] $8; yyerror("sizeof(submodule[index].gate) notation not supported here"); }
263
        ;
264
265
literal
266
        : stringliteral
267
        | boolliteral
268
        | numliteral
269
        ;
270
271
stringliteral
272
        : STRINGCONSTANT
273
                { *e++ = opp_parsequotedstr($1).c_str(); delete [] $1; }
274
        ;
275
276
boolliteral
277
        : TRUE_
278
                { *e++ = true; }
279
        | FALSE_
280
                { *e++ = false; }
281
        ;
282
283
numliteral
284
        : INTCONSTANT
285
                { *e++ = opp_atol($1); delete [] $1; }
286
        | REALCONSTANT
287
                { *e++ = opp_atof($1); delete [] $1; }
288
        | quantity
289
                {
290
                  std::string unit;
291
                  *e++ = parseQuantity($1, unit);
292
                  if (!unit.empty())
293
                      (e-1)->setUnit(unit.c_str());
294
                  delete [] $1;
295
                }
296
        ;
297
298
quantity
299
        : quantity INTCONSTANT NAME
300
                { $$ = expryyconcat($1,$2,$3); }
301
        | quantity REALCONSTANT NAME
302
                { $$ = expryyconcat($1,$2,$3); }
303
        | INTCONSTANT NAME
304
                { $$ = expryyconcat($1,$2); }
305
        | REALCONSTANT NAME
306
                { $$ = expryyconcat($1,$2); }
307
        ;
308
309
%%
310
311
//----------------------------------------------------------------------
312
313
void doParseExpression(const char *nedtext, cDynamicExpression::Elem *&elems, int& nelems)
314
{
315
    NONREENTRANT_PARSER();
316
317
    elems = NULL;
318
    nelems = 0;
319
320
    // reset the lexer
321
    xpos.co = 0;
322
    xpos.li = 1;
323
    xprevpos = xpos;
324
325
    yyin = NULL;
326
    yyout = stderr; // not used anyway
327
328
    // alloc buffer
329
    struct yy_buffer_state *handle = yy_scan_string(nedtext);
330
    if (!handle)
331
        throw std::runtime_error("parser is unable to allocate work memory");
332
333
    cDynamicExpression::Elem *v = new cDynamicExpression::Elem[100]; // overestimate for now; XXX danger of overrun
334
    e = v;
335
336
    // parse
337
    int ret;
338
    try
339
    {
340
        ret = yyparse();
341
    }
342
    catch (std::exception& e)
343
    {
344
        yy_delete_buffer(handle);
345
        delete [] v;
346
        throw;
347
    }
348
    yy_delete_buffer(handle);
349
350
    // copy v[] and return
351
    nelems = e - v;
352
    elems = new cDynamicExpression::Elem[nelems];
353
    for (int i=0; i<nelems; i++)
354
        elems[i] = v[i];
355
    delete [] v;
356
}
357
358
void yyerror(const char *s)
359
{
360
    // chop newline
361
    char buf[250];
362
    strcpy(buf, s);
363
    if (buf[strlen(buf)-1] == '\n')
364
        buf[strlen(buf)-1] = '\0';
365
366
    throw std::runtime_error(buf);
367
}