1 %{
2 /******************************************************************************
3 *
4 * Component: OGR ODS Formula Engine
5 * Purpose: expression and select parser grammar.
6 * Requires Bison 2.4.0 or newer to process. Use "make parser" target.
7 * Author: Even Rouault, even dot rouault at spatialys.com
8 *
9 ******************************************************************************
10 * Copyright (C) 2010 Frank Warmerdam <warmerdam@pobox.com>
11 * Copyright (c) 2012, Even Rouault <even dot rouault at spatialys.com>
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"),
15 * to deal in the Software without restriction, including without limitation
16 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included
21 * in all copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 * DEALINGS IN THE SOFTWARE.
30 ****************************************************************************/
31
32 #include "cpl_conv.h"
33 #include "cpl_string.h"
34 #include "ods_formula.h"
35
36 CPL_CVSID("$Id$")
37
38 #define YYSTYPE ods_formula_node*
39
40 /* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */
41 /* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */
42 /* increase YYINITDEPTH instead, but this will consume memory. */
43 /* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */
44 /* it appears to be a non documented feature of Bison */
45 #define YYSTYPE_IS_TRIVIAL 1
46
ods_formulaerror(ods_formula_parse_context *,const char * msg)47 static void ods_formulaerror( ods_formula_parse_context * /* context */,
48 const char *msg )
49 {
50 CPLError( CE_Failure, CPLE_AppDefined,
51 "Formula Parsing Error: %s", msg );
52 }
53
54 %}
55
56 %define api.pure
57 %require "2.4.0"
58
59 %parse-param {ods_formula_parse_context *context}
60 %lex-param {ods_formula_parse_context *context}
61
62 %token ODST_NUMBER
63 %token ODST_STRING
64 %token ODST_IDENTIFIER
65 %token ODST_FUNCTION_NO_ARG
66 %token ODST_FUNCTION_SINGLE_ARG
67 %token ODST_FUNCTION_TWO_ARG
68 %token ODST_FUNCTION_THREE_ARG
69 %token ODST_FUNCTION_ARG_LIST
70
71 %token ODST_START
72
73 %left ODST_NOT
74 %left ODST_OR
75 %left ODST_AND
76 %left ODST_IF
77
78 %left '+' '-' '&'
79 %left '*' '/' '%'
80 %left ODST_UMINUS
81
82 /* Any grammar rule that does $$ = must be listed afterwards */
83 /* as well as ODST_NUMBER ODST_STRING ODST_IDENTIFIER that are allocated by ods_formulalex() */
84 %destructor { delete $$; } ODST_NUMBER ODST_STRING ODST_IDENTIFIER ODST_FUNCTION_NO_ARG ODST_FUNCTION_SINGLE_ARG ODST_FUNCTION_TWO_ARG ODST_FUNCTION_THREE_ARG ODST_FUNCTION_ARG_LIST
85 %destructor { delete $$; } value_expr value_expr_list cell_range value_expr_and_cell_range_list
86
87 %%
88
89 input:
90 ODST_START value_expr
91 {
92 context->poRoot = $2;
93 }
94
95 comma: ',' | ';'
96
97 value_expr:
98
99 ODST_NUMBER
100 {
101 $$ = $1;
102 }
103
104 | ODST_STRING
105 {
106 $$ = $1;
107 }
108
109 | ODST_FUNCTION_NO_ARG '(' ')'
110 {
111 $$ = $1;
112 }
113
114 | ODST_FUNCTION_SINGLE_ARG '(' value_expr ')'
115 {
116 $$ = $1;
117 $$->PushSubExpression( $3 );
118 }
119
120 | ODST_FUNCTION_TWO_ARG '(' value_expr comma value_expr ')'
121 {
122 $$ = $1;
123 $$->PushSubExpression( $3 );
124 $$->PushSubExpression( $5 );
125 }
126
127 | ODST_FUNCTION_THREE_ARG '(' value_expr comma value_expr comma value_expr ')'
128 {
129 $$ = $1;
130 $$->PushSubExpression( $3 );
131 $$->PushSubExpression( $5 );
132 $$->PushSubExpression( $7 );
133 }
134
135 | ODST_AND '(' value_expr_list ')'
136 {
137 $$ = new ods_formula_node( ODS_AND );
138 $3->ReverseSubExpressions();
139 $$->PushSubExpression( $3 );
140 }
141
142 | ODST_OR '(' value_expr_list ')'
143 {
144 $$ = new ods_formula_node( ODS_OR );
145 $3->ReverseSubExpressions();
146 $$->PushSubExpression( $3 );
147 }
148
149 | ODST_NOT '(' value_expr ')'
150 {
151 $$ = new ods_formula_node( ODS_NOT );
152 $$->PushSubExpression( $3 );
153 }
154
155 | ODST_IF '(' value_expr comma value_expr ')'
156 {
157 $$ = new ods_formula_node( ODS_IF );
158 $$->PushSubExpression( $3 );
159 $$->PushSubExpression( $5 );
160 }
161
162 | ODST_IF '(' value_expr comma value_expr comma value_expr ')'
163 {
164 $$ = new ods_formula_node( ODS_IF );
165 $$->PushSubExpression( $3 );
166 $$->PushSubExpression( $5 );
167 $$->PushSubExpression( $7 );
168 }
169
170 | ODST_FUNCTION_ARG_LIST '(' value_expr_and_cell_range_list ')'
171 {
172 $$ = $1;
173 $3->ReverseSubExpressions();
174 $$->PushSubExpression( $3 );
175 }
176
177 | '(' value_expr ')'
178 {
179 $$ = $2;
180 }
181
182 | value_expr '=' value_expr
183 {
184 $$ = new ods_formula_node( ODS_EQ );
185 $$->PushSubExpression( $1 );
186 $$->PushSubExpression( $3 );
187 }
188
189 | value_expr '<' '>' value_expr
190 {
191 $$ = new ods_formula_node( ODS_NE );
192 $$->PushSubExpression( $1 );
193 $$->PushSubExpression( $4 );
194 }
195
196 | value_expr '!' '=' value_expr
197 {
198 $$ = new ods_formula_node( ODS_NE );
199 $$->PushSubExpression( $1 );
200 $$->PushSubExpression( $4 );
201 }
202
203 | value_expr '<' value_expr
204 {
205 $$ = new ods_formula_node( ODS_LT );
206 $$->PushSubExpression( $1 );
207 $$->PushSubExpression( $3 );
208 }
209
210 | value_expr '>' value_expr
211 {
212 $$ = new ods_formula_node( ODS_GT );
213 $$->PushSubExpression( $1 );
214 $$->PushSubExpression( $3 );
215 }
216
217 | value_expr '<' '=' value_expr
218 {
219 $$ = new ods_formula_node( ODS_LE );
220 $$->PushSubExpression( $1 );
221 $$->PushSubExpression( $4 );
222 }
223
224 | value_expr '=' '<' value_expr
225 {
226 $$ = new ods_formula_node( ODS_LE );
227 $$->PushSubExpression( $1 );
228 $$->PushSubExpression( $4 );
229 }
230
231 | value_expr '=' '>' value_expr
232 {
233 $$ = new ods_formula_node( ODS_LE );
234 $$->PushSubExpression( $1 );
235 $$->PushSubExpression( $4 );
236 }
237
238 | value_expr '>' '=' value_expr
239 {
240 $$ = new ods_formula_node( ODS_GE );
241 $$->PushSubExpression( $1 );
242 $$->PushSubExpression( $4 );
243 }
244
245 | '-' value_expr %prec ODST_UMINUS
246 {
247 if ($2->eNodeType == SNT_CONSTANT &&
248 !($2->field_type == ODS_FIELD_TYPE_INTEGER &&
249 $2->int_value == INT_MIN))
250 {
251 $$ = $2;
252 $$->int_value *= -1;
253 $$->float_value *= -1;
254 }
255 else
256 {
257 $$ = new ods_formula_node( ODS_MULTIPLY );
258 $$->PushSubExpression( new ods_formula_node(-1) );
259 $$->PushSubExpression( $2 );
260 }
261 }
262
263 | value_expr '+' value_expr
264 {
265 $$ = new ods_formula_node( ODS_ADD );
266 $$->PushSubExpression( $1 );
267 $$->PushSubExpression( $3 );
268 }
269
270 | value_expr '-' value_expr
271 {
272 $$ = new ods_formula_node( ODS_SUBTRACT );
273 $$->PushSubExpression( $1 );
274 $$->PushSubExpression( $3 );
275 }
276
277 | value_expr '&' value_expr
278 {
279 $$ = new ods_formula_node( ODS_CONCAT );
280 $$->PushSubExpression( $1 );
281 $$->PushSubExpression( $3 );
282 }
283
284 | value_expr '*' value_expr
285 {
286 $$ = new ods_formula_node( ODS_MULTIPLY );
287 $$->PushSubExpression( $1 );
288 $$->PushSubExpression( $3 );
289 }
290
291 | value_expr '/' value_expr
292 {
293 $$ = new ods_formula_node( ODS_DIVIDE );
294 $$->PushSubExpression( $1 );
295 $$->PushSubExpression( $3 );
296 }
297
298 | value_expr '%' value_expr
299 {
300 $$ = new ods_formula_node( ODS_MODULUS );
301 $$->PushSubExpression( $1 );
302 $$->PushSubExpression( $3 );
303 }
304
305 | '[' ODST_IDENTIFIER ']'
306 {
307 $$ = new ods_formula_node( ODS_CELL );
308 $$->PushSubExpression( $2 );
309 }
310
311 value_expr_list:
312 value_expr comma value_expr_list
313 {
314 $$ = $3;
315 $3->PushSubExpression( $1 );
316 }
317
318 | value_expr
319 {
320 $$ = new ods_formula_node( ODS_LIST );
321 $$->PushSubExpression( $1 );
322 }
323
324 value_expr_and_cell_range_list:
325 value_expr comma value_expr_and_cell_range_list
326 {
327 $$ = $3;
328 $3->PushSubExpression( $1 );
329 }
330
331 | value_expr
332 {
333 $$ = new ods_formula_node( ODS_LIST );
334 $$->PushSubExpression( $1 );
335 }
336 | cell_range comma value_expr_and_cell_range_list
337 {
338 $$ = $3;
339 $3->PushSubExpression( $1 );
340 }
341
342 | cell_range
343 {
344 $$ = new ods_formula_node( ODS_LIST );
345 $$->PushSubExpression( $1 );
346 }
347
348 cell_range:
349 '[' ODST_IDENTIFIER ':' ODST_IDENTIFIER ']'
350 {
351 $$ = new ods_formula_node( ODS_CELL_RANGE );
352 $$->PushSubExpression( $2 );
353 $$->PushSubExpression( $4 );
354 }
355