Project

General

Profile

Statistics
| Branch: | Revision:

root / src / common / expression.y @ a3be1d55

History | View | Annotate | Download (6.97 KB)

1 01873262 Georg Kunz
/*===============================================================
2
 * File: expression.y
3
 *
4
 *  Grammar for generic arithmetic expressions.
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
/* Reserved words */
18
%token DOUBLETYPE INTTYPE STRINGTYPE BOOLTYPE
19
%token TRUE_ FALSE_
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 "commonutil.h"
48
#include "expressionyydefs.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 expressionyyin
59
#define yyout expressionyyout
60
#define yyrestart expressionyyrestart
61
#define yy_scan_string expressionyy_scan_string
62
#define yy_delete_buffer expressionyy_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 "expression.h"
76
#include "exception.h"
77
#include "stringutil.h"
78
#include "unitconversion.h"
79
80
using OPP::Expression;
81
82
static Expression::Elem *e;
83
static Expression::Resolver *resolver;
84
85
/*
86
static char *expryyconcat(char *s1, char *s2, char *s3=NULL)
87
{
88
    char *d = new char[strlen(s1)+strlen(s2)+strlen(s3?s3:"")+4];
89
    strcpy(d, s1);
90
    strcat(d, " ");
91
    strcat(d, s2);
92
    if (s3) {strcat(d, " "); strcat(d, s3);}
93
    delete [] s1; delete [] s2; delete [] s3;
94
    return d;
95
}
96
*/
97
98
static void addFunction(const char *funcname, int numargs)
99
{
100
    try {
101
        *e++ = resolver->resolveFunction(funcname, numargs);
102
    }
103
    catch (std::exception& e) {
104
        yyerror(e.what());
105
    }
106
}
107
108
static void addVariableRef(const char *varname)
109
{
110
    try {
111
        *e++ = resolver->resolveVariable(varname);
112
    }
113
    catch (std::exception& e) {
114
        yyerror(e.what());
115
    }
116
}
117
118
%}
119
120
%%
121
122
expression
123
        : expr
124
        ;
125
126
expr
127
        : simple_expr
128
        | '(' expr ')'
129
130
        | expr '+' expr
131
                { *e++ = Expression::ADD; }
132
        | expr '-' expr
133
                { *e++ = Expression::SUB; }
134
        | expr '*' expr
135
                { *e++ = Expression::MUL; }
136
        | expr '/' expr
137
                { *e++ = Expression::DIV; }
138
        | expr '%' expr
139
                { *e++ = Expression::MOD; }
140
        | expr '^' expr
141
                { *e++ = Expression::POW; }
142
143
        | '-' expr
144
                %prec UMIN_
145
                { *e++ = Expression::NEG; }
146
147
        | expr EQ_ expr
148
                { *e++ = Expression::EQ; }
149
        | expr NE_ expr
150
                { *e++ = Expression::NE; }
151
        | expr '>' expr
152
                { *e++ = Expression::GT; }
153
        | expr GE_ expr
154
                { *e++ = Expression::GE; }
155
        | expr '<' expr
156
                { *e++ = Expression::LT; }
157
        | expr LE_ expr
158
                { *e++ = Expression::LE; }
159
160
        | expr AND_ expr
161
                { *e++ = Expression::AND; }
162
        | expr OR_ expr
163
                { *e++ = Expression::OR; }
164
        | expr XOR_ expr
165
                { *e++ = Expression::XOR; }
166
167
        | NOT_ expr
168
                %prec UMIN_
169
                { *e++ = Expression::NOT; }
170
171
        | expr BINAND_ expr
172
                { *e++ = Expression::BIN_AND; }
173
        | expr BINOR_ expr
174
                { *e++ = Expression::BIN_OR; }
175
        | expr BINXOR_ expr
176
                { *e++ = Expression::BIN_XOR; }
177
178
        | BINCOMPL_ expr
179
                %prec UMIN_
180
                { *e++ = Expression::BIN_NOT; }
181
        | expr SHIFTLEFT_ expr
182
                { *e++ = Expression::LSHIFT; }
183
        | expr SHIFTRIGHT_ expr
184
                { *e++ = Expression::RSHIFT; }
185
        | expr '?' expr ':' expr
186
                { *e++ = Expression::IIF; }
187
188
        | NAME '(' ')'
189
                { addFunction($1,0); delete [] $1; }
190
        | NAME '(' expr ')'
191
                { addFunction($1,1); delete [] $1; }
192
        | NAME '(' expr ',' expr ')'
193
                { addFunction($1,2); delete [] $1; }
194
        | NAME '(' expr ',' expr ',' expr ')'
195
                { addFunction($1,3); delete [] $1; }
196
        | NAME '(' expr ',' expr ',' expr ',' expr ')'
197
                { addFunction($1,4); delete [] $1; }
198
         ;
199
200
simple_expr
201
        : identifier
202
        | literal
203
        ;
204
205
identifier
206
        : NAME
207
                { addVariableRef($1); delete [] $1; }
208
        ;
209
210
literal
211
        : stringliteral
212
        | boolliteral
213
        | numliteral
214
        ;
215
216
stringliteral
217
        : STRINGCONSTANT
218
                { *e++ = opp_parsequotedstr($1).c_str(); delete [] $1; }
219
        ;
220
221
boolliteral
222
        : TRUE_
223
                { *e++ = true; }
224
        | FALSE_
225
                { *e++ = false; }
226
        ;
227
228
numliteral
229
        : INTCONSTANT
230
                { *e++ = opp_atol($1); delete [] $1; }
231
        | REALCONSTANT
232
                { *e++ = opp_atof($1); delete [] $1; }
233
        ;
234
235
%%
236
237
//----------------------------------------------------------------------
238
239
void doParseExpression(const char *text, Expression::Resolver *res, Expression::Elem *&elems, int& nelems)
240
{
241
    NONREENTRANT_PARSER();
242
243
    elems = NULL;
244
    nelems = 0;
245
246
    // reset the lexer
247
    xpos.co = 0;
248
    xpos.li = 1;
249
    xprevpos = xpos;
250
251
    yyin = NULL;
252
    yyout = stderr; // not used anyway
253
254
    // alloc buffer
255
    struct yy_buffer_state *handle = yy_scan_string(text);
256
    if (!handle)
257
        throw std::runtime_error("parser is unable to allocate work memory");
258
259
    Expression::Elem *v = new Expression::Elem[100]; // overestimate for now; XXX danger of overrun
260
    e = v;
261
    resolver = res;
262
263
    // parse
264
    int ret;
265
    try
266
    {
267
        ret = yyparse();
268
    }
269
    catch (std::exception& e)
270
    {
271
        yy_delete_buffer(handle);
272
        delete [] v;
273
        throw;
274
    }
275
    yy_delete_buffer(handle);
276
277
    // copy v[] and return
278
    nelems = e - v;
279
    elems = new Expression::Elem[nelems];
280
    for (int i=0; i<nelems; i++)
281
        elems[i] = v[i];
282
    delete [] v;
283
}
284
285
void yyerror(const char *s)
286
{
287
    // chop newline
288
    char buf[250];
289
    strcpy(buf, s);
290
    if (buf[strlen(buf)-1] == '\n')
291
        buf[strlen(buf)-1] = '\0';
292
293
    throw std::runtime_error(buf);
294
}