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