1 : %{
2 : /******************************************************************************
3 : * $Id: ods_formula_parser.y 23831 2012-01-30 23:12:23Z rouault $
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 :
46 0 : static void ods_formulaerror( ods_formula_parse_context *context, const char *msg )
47 : {
48 : CPLError( CE_Failure, CPLE_AppDefined,
49 0 : "Formula Parsing Error: %s", msg );
50 0 : }
51 :
52 : %}
53 :
54 : %define api.pure
55 : %require "2.4.0"
56 :
57 : %parse-param {ods_formula_parse_context *context}
58 : %lex-param {ods_formula_parse_context *context}
59 :
60 : %token ODST_NUMBER
61 : %token ODST_STRING
62 : %token ODST_IDENTIFIER
63 : %token ODST_FUNCTION_NO_ARG
64 : %token ODST_FUNCTION_SINGLE_ARG
65 : %token ODST_FUNCTION_TWO_ARG
66 : %token ODST_FUNCTION_THREE_ARG
67 : %token ODST_FUNCTION_ARG_LIST
68 :
69 : %token ODST_START
70 :
71 : %left ODST_NOT
72 : %left ODST_OR
73 : %left ODST_AND
74 : %left ODST_IF
75 :
76 : %left '+' '-' '&'
77 : %left '*' '/' '%'
78 : %left ODST_UMINUS
79 :
80 : /* Any grammar rule that does $$ = must be listed afterwards */
81 : /* as well as ODST_NUMBER ODST_STRING ODST_IDENTIFIER that are allocated by ods_formulalex() */
82 0 : %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
83 0 : %destructor { delete $$; } value_expr value_expr_list cell_range value_expr_and_cell_range_list
84 :
85 : %%
86 :
87 : input:
88 : ODST_START value_expr
89 : {
90 116 : context->poRoot = $2;
91 : }
92 116 :
93 : comma: ',' | ';'
94 :
95 : value_expr:
96 :
97 : ODST_NUMBER
98 : {
99 157 : $$ = $1;
100 : }
101 157 :
102 : | ODST_STRING
103 : {
104 34 : $$ = $1;
105 : }
106 34 :
107 : | ODST_FUNCTION_NO_ARG '(' ')'
108 : {
109 1 : $$ = $1;
110 : }
111 1 :
112 : | ODST_FUNCTION_SINGLE_ARG '(' value_expr ')'
113 : {
114 10 : $$ = $1;
115 10 : $$->PushSubExpression( $3 );
116 : }
117 10 :
118 : | ODST_FUNCTION_TWO_ARG '(' value_expr comma value_expr ')'
119 : {
120 7 : $$ = $1;
121 7 : $$->PushSubExpression( $3 );
122 7 : $$->PushSubExpression( $5 );
123 : }
124 7 :
125 : | ODST_FUNCTION_THREE_ARG '(' value_expr comma value_expr comma value_expr ')'
126 : {
127 8 : $$ = $1;
128 8 : $$->PushSubExpression( $3 );
129 8 : $$->PushSubExpression( $5 );
130 8 : $$->PushSubExpression( $7 );
131 : }
132 8 :
133 : | ODST_AND '(' value_expr_list ')'
134 : {
135 4 : $$ = new ods_formula_node( ODS_AND );
136 4 : $3->ReverseSubExpressions();
137 4 : $$->PushSubExpression( $3 );
138 : }
139 4 :
140 : | ODST_OR '(' value_expr_list ')'
141 : {
142 4 : $$ = new ods_formula_node( ODS_OR );
143 4 : $3->ReverseSubExpressions();
144 4 : $$->PushSubExpression( $3 );
145 : }
146 4 :
147 : | ODST_NOT '(' value_expr ')'
148 : {
149 2 : $$ = new ods_formula_node( ODS_NOT );
150 2 : $$->PushSubExpression( $3 );
151 : }
152 2 :
153 : | ODST_IF '(' value_expr comma value_expr ')'
154 : {
155 2 : $$ = new ods_formula_node( ODS_IF );
156 2 : $$->PushSubExpression( $3 );
157 2 : $$->PushSubExpression( $5 );
158 : }
159 2 :
160 : | ODST_IF '(' value_expr comma value_expr comma value_expr ')'
161 : {
162 2 : $$ = new ods_formula_node( ODS_IF );
163 2 : $$->PushSubExpression( $3 );
164 2 : $$->PushSubExpression( $5 );
165 2 : $$->PushSubExpression( $7 );
166 : }
167 2 :
168 : | ODST_FUNCTION_ARG_LIST '(' value_expr_and_cell_range_list ')'
169 : {
170 6 : $$ = $1;
171 6 : $3->ReverseSubExpressions();
172 6 : $$->PushSubExpression( $3 );
173 : }
174 6 :
175 : | '(' value_expr ')'
176 : {
177 1 : $$ = $2;
178 : }
179 1 :
180 : | value_expr '=' value_expr
181 : {
182 10 : $$ = new ods_formula_node( ODS_EQ );
183 10 : $$->PushSubExpression( $1 );
184 10 : $$->PushSubExpression( $3 );
185 : }
186 10 :
187 : | value_expr '<' '>' value_expr
188 : {
189 10 : $$ = new ods_formula_node( ODS_NE );
190 10 : $$->PushSubExpression( $1 );
191 10 : $$->PushSubExpression( $4 );
192 : }
193 10 :
194 : | value_expr '!' '=' value_expr
195 : {
196 0 : $$ = new ods_formula_node( ODS_NE );
197 0 : $$->PushSubExpression( $1 );
198 0 : $$->PushSubExpression( $4 );
199 : }
200 0 :
201 : | value_expr '<' value_expr
202 : {
203 14 : $$ = new ods_formula_node( ODS_LT );
204 14 : $$->PushSubExpression( $1 );
205 14 : $$->PushSubExpression( $3 );
206 : }
207 14 :
208 : | value_expr '>' value_expr
209 : {
210 10 : $$ = new ods_formula_node( ODS_GT );
211 10 : $$->PushSubExpression( $1 );
212 10 : $$->PushSubExpression( $3 );
213 : }
214 10 :
215 : | value_expr '<' '=' value_expr
216 : {
217 10 : $$ = new ods_formula_node( ODS_LE );
218 10 : $$->PushSubExpression( $1 );
219 10 : $$->PushSubExpression( $4 );
220 : }
221 10 :
222 : | value_expr '=' '<' value_expr
223 : {
224 0 : $$ = new ods_formula_node( ODS_LE );
225 0 : $$->PushSubExpression( $1 );
226 0 : $$->PushSubExpression( $4 );
227 : }
228 0 :
229 : | value_expr '=' '>' value_expr
230 : {
231 0 : $$ = new ods_formula_node( ODS_LE );
232 0 : $$->PushSubExpression( $1 );
233 0 : $$->PushSubExpression( $4 );
234 : }
235 0 :
236 : | value_expr '>' '=' value_expr
237 : {
238 10 : $$ = new ods_formula_node( ODS_GE );
239 10 : $$->PushSubExpression( $1 );
240 10 : $$->PushSubExpression( $4 );
241 : }
242 10 :
243 : | '-' value_expr %prec ODST_UMINUS
244 : {
245 1 : if ($2->eNodeType == SNT_CONSTANT)
246 : {
247 0 : $$ = $2;
248 0 : $$->int_value *= -1;
249 0 : $$->float_value *= -1;
250 : }
251 : else
252 : {
253 1 : $$ = new ods_formula_node( ODS_MULTIPLY );
254 2 : $$->PushSubExpression( new ods_formula_node(-1) );
255 1 : $$->PushSubExpression( $2 );
256 : }
257 : }
258 1 :
259 : | value_expr '+' value_expr
260 : {
261 1 : $$ = new ods_formula_node( ODS_ADD );
262 1 : $$->PushSubExpression( $1 );
263 1 : $$->PushSubExpression( $3 );
264 : }
265 1 :
266 : | value_expr '-' value_expr
267 : {
268 1 : $$ = new ods_formula_node( ODS_SUBTRACT );
269 1 : $$->PushSubExpression( $1 );
270 1 : $$->PushSubExpression( $3 );
271 : }
272 1 :
273 : | value_expr '&' value_expr
274 : {
275 1 : $$ = new ods_formula_node( ODS_CONCAT );
276 1 : $$->PushSubExpression( $1 );
277 1 : $$->PushSubExpression( $3 );
278 : }
279 1 :
280 : | value_expr '*' value_expr
281 : {
282 3 : $$ = new ods_formula_node( ODS_MULTIPLY );
283 3 : $$->PushSubExpression( $1 );
284 3 : $$->PushSubExpression( $3 );
285 : }
286 3 :
287 : | value_expr '/' value_expr
288 : {
289 2 : $$ = new ods_formula_node( ODS_DIVIDE );
290 2 : $$->PushSubExpression( $1 );
291 2 : $$->PushSubExpression( $3 );
292 : }
293 2 :
294 : | value_expr '%' value_expr
295 : {
296 0 : $$ = new ods_formula_node( ODS_MODULUS );
297 0 : $$->PushSubExpression( $1 );
298 0 : $$->PushSubExpression( $3 );
299 : }
300 0 :
301 : | '[' ODST_IDENTIFIER ']'
302 : {
303 28 : $$ = new ods_formula_node( ODS_CELL );
304 28 : $$->PushSubExpression( $2 );
305 : }
306 28 :
307 : value_expr_list:
308 : value_expr comma value_expr_list
309 : {
310 8 : $$ = $3;
311 8 : $3->PushSubExpression( $1 );
312 : }
313 8 :
314 : | value_expr
315 : {
316 8 : $$ = new ods_formula_node( ODS_LIST );
317 8 : $$->PushSubExpression( $1 );
318 : }
319 8 :
320 : value_expr_and_cell_range_list:
321 : value_expr comma value_expr_and_cell_range_list
322 : {
323 0 : $$ = $3;
324 0 : $3->PushSubExpression( $1 );
325 : }
326 0 :
327 : | value_expr
328 : {
329 1 : $$ = new ods_formula_node( ODS_LIST );
330 1 : $$->PushSubExpression( $1 );
331 : }
332 1 : | cell_range comma value_expr_and_cell_range_list
333 : {
334 1 : $$ = $3;
335 1 : $3->PushSubExpression( $1 );
336 : }
337 1 :
338 : | cell_range
339 : {
340 5 : $$ = new ods_formula_node( ODS_LIST );
341 5 : $$->PushSubExpression( $1 );
342 : }
343 5 :
344 : cell_range:
345 : '[' ODST_IDENTIFIER ':' ODST_IDENTIFIER ']'
346 : {
347 6 : $$ = new ods_formula_node( ODS_CELL_RANGE );
348 6 : $$->PushSubExpression( $2 );
349 6 : $$->PushSubExpression( $4 );
350 : }
|