libamxp  1.4.0
Patterns C Implementation
amxp_expression.y
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (c) 2020 SoftAtHome
4 **
5 ** Redistribution and use in source and binary forms, with or
6 ** without modification, are permitted provided that the following
7 ** conditions are met:
8 **
9 ** 1. Redistributions of source code must retain the above copyright
10 ** notice, this list of conditions and the following disclaimer.
11 **
12 ** 2. Redistributions in binary form must reproduce the above
13 ** copyright notice, this list of conditions and the following
14 ** disclaimer in the documentation and/or other materials provided
15 ** with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each
18 ** copyright holder and contributor hereby grants to those receiving
19 ** rights under this license a perpetual, worldwide, non-exclusive,
20 ** no-charge, royalty-free, irrevocable (except for failure to
21 ** satisfy the conditions of this license) patent license to make,
22 ** have made, use, offer to sell, sell, import, and otherwise
23 ** transfer this software, where such license applies only to those
24 ** patent claims, already acquired or hereafter acquired, licensable
25 ** by such copyright holder or contributor that are necessarily
26 ** infringed by:
27 **
28 ** (a) their Contribution(s) (the licensed copyrights of copyright
29 ** holders and non-copyrightable additions of contributors, in
30 ** source or binary form) alone; or
31 **
32 ** (b) combination of their Contribution(s) with the work of
33 ** authorship to which such Contribution(s) was added by such
34 ** copyright holder or contributor, if, at the time the Contribution
35 ** is added, such addition causes such combination to be necessarily
36 ** infringed. The patent license shall not apply to any other
37 ** combinations which include the Contribution.
38 **
39 ** Except as expressly stated above, no rights or licenses from any
40 ** copyright holder or contributor is granted under this license,
41 ** whether expressly, by implication, estoppel or otherwise.
42 **
43 ** DISCLAIMER
44 **
45 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
46 ** CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
47 ** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
48 ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
49 ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
50 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
52 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
53 ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
54 ** AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
56 ** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 ** POSSIBILITY OF SUCH DAMAGE.
58 **
59 ****************************************************************************/
60 %define api.pure full
61 %locations
62 %defines
63 %define parse.error verbose
64 %parse-param {void *ctx}
65 %lex-param {void *ctx}
66 
67 %{
68 #ifndef _GNU_SOURCE
69 #define _GNU_SOURCE
70 #endif
71 
72 #include <stdlib.h>
73 #include <stdio.h>
74 #include <string.h>
75 #include <sys/types.h>
76 #include <dlfcn.h>
77 #include <amxc/amxc.h>
78 
79 #include "amxp_expr_priv.h"
80 #include "amxp_expr.tab.h"
81 
82 %}
83 
84 
85 %union
86 {
87  amxp_expr_node_t* node;
88  int64_t integer;
89  amxp_txt_t cptr;
90  bool boolean;
91  amxc_var_t *ptrval;
92  amxp_expr_comp_t comp;
93  amxc_string_t *ptrstr;
94 }
95 
96 %token <cptr> MULTILINECOMMENT
97 %token <node> EOF_TOKEN
98 %token <cptr> STRING
99 %token <cptr> TEXT
100 %token <cptr> FIELD
101 %token <boolean> BOOL
102 %token <integer> DIGIT
103 
104 %token <comp> COMPERATOR
105 
106 %type <node> stream expr conditional_expr logical_or_expr logical_and_expr
107 %type <node> primary value list_values
108 %type <ptrstr> path
109 %type <cptr> function_header
110 
111 %left LAND LOR LNOT
112 
113 %{
114  int yylex(YYSTYPE* lvalp, YYLTYPE* llocp, void * yyscanner);
115  void yyerror(YYLTYPE* locp, void* scanner, const char* err);
116  void yywarning(YYLTYPE* locp, void* scanner, const char* err);
117  amxp_expr_t *yyget_extra ( void * yyscanner );
118 
119  void yyerror(YYLTYPE* locp, void* scanner, const char* err) {
120  amxp_expr_t *context = (amxp_expr_t *)yyget_extra(scanner);
121  amxp_expr_printf("ERROR (%s@%d) - %s\n",
122  err,
123  locp->first_line,
124  amxc_string_get(&context->msg, 0));
125  amxc_string_clean(&context->msg);
126  }
127 
128  void yywarning(YYLTYPE* locp, void* scanner, const char* err) {
129  amxp_expr_t *context = (amxp_expr_t *)yyget_extra(scanner);
130  amxp_expr_printf("WARNING (%s@%d) - %s\n",
131  err,
132  locp->first_line,
133  amxc_string_get(&context->msg, 0));
134  amxc_string_clean(&context->msg);
135  }
136 
137  #define scanner x->scanner
138  #define parser_ctx ((amxp_expr_t *)yyget_extra(ctx))
139  #define NOOP
140 
141 %}
142 
143 %start stream
144 
145 %%
146 
147 stream
148  : expr ';' {
149  $$ = $1;
150  }
151  | EOF_TOKEN { $$ = NULL; }
152  ;
153 
154 expr: /* empty */ {
155  amxp_expr_node_t* node = NULL;
156  amxc_var_t* value = NULL;
157  amxp_expr_node_new(&node, amxp_expr_value);
158  amxc_var_new(&value);
159  amxc_var_set(bool, value, true);
160  amxp_expr_node_set_value(node, value);
161  amxp_expr_node_push(&parser_ctx->nodes, node);
162  $$ = node;
163  }
164  | conditional_expr
165  ;
166 
167 conditional_expr
168  : logical_or_expr
169  ;
170 
171 logical_or_expr
172  : logical_and_expr
173  | logical_or_expr LOR logical_and_expr {
174  amxp_expr_node_t* node = NULL;
175  amxp_expr_node_new(&node, amxp_expr_or);
176  amxp_expr_node_set_left(node, $1);
177  amxp_expr_node_set_right(node, $3);
178  amxp_expr_node_push(&parser_ctx->nodes, node);
179  $$ = node;
180  }
181  ;
182 
183 logical_and_expr
184  : primary
185  | logical_and_expr LAND primary {
186  amxp_expr_node_t* node = NULL;
187  amxp_expr_node_new(&node, amxp_expr_and);
188  amxp_expr_node_set_left(node, $1);
189  amxp_expr_node_set_right(node, $3);
190  amxp_expr_node_push(&parser_ctx->nodes, node);
191  $$ = node;
192  }
193  ;
194 
195 primary
196  : '(' expr ')' {
197  $$ = $2;
198  }
199  | LNOT primary {
200  amxp_expr_node_t* node = NULL;
201  amxp_expr_node_new(&node, amxp_expr_not);
202  amxp_expr_node_set_left(node, $2);
203  amxp_expr_node_push(&parser_ctx->nodes, node);
204  $$ = node;
205  }
206  | value
207  | value primary {
208  amxp_expr_node_t* node = NULL;
209  amxp_expr_node_new(&node, amxp_expr_and);
210  amxp_expr_node_set_left(node, $1);
211  amxp_expr_node_set_right(node, $2);
212  amxp_expr_node_push(&parser_ctx->nodes, node);
213  $$ = node;
214  }
215  | value COMPERATOR value {
216  amxp_expr_node_t* node = NULL;
217  amxp_expr_node_new(&node, amxp_expr_compare_oper);
218  amxp_expr_node_set_compop(node, $2);
219  amxp_expr_node_set_left(node, $1);
220  amxp_expr_node_set_right(node, $3);
221  amxp_expr_node_push(&parser_ctx->nodes, node);
222  $$ = node;
223  }
224  | function_header '(' list_values ')' {
225  amxp_expr_node_t* node = NULL;
226  amxp_expr_node_new(&node, amxp_expr_bool_func);
227  amxp_expr_node_set_function(node, strdup($1.txt));
228  amxc_llist_for_each(it, &$3->right.args) {
229  amxp_expr_node_t* arg = amxc_container_of(it, amxp_expr_node_t, it);
230  amxp_expr_node_add_value(node, arg);
231  }
232  amxp_expr_node_delete(&$3);
233  amxp_expr_node_push(&parser_ctx->nodes, node);
234  $$ = node;
235  }
236  ;
237 
238 value
239  : TEXT {
240  amxc_var_t* value = NULL;
241  amxp_expr_node_t* node = NULL;
242  amxc_string_t txt;
243 
244  $1.txt[$1.length] = 0;
245  amxc_string_init(&txt, 0);
246  amxc_string_push_buffer(&txt, $1.txt, $1.length + 1);
247  amxc_string_trim(&txt, NULL);
248  amxc_var_new(&value);
249  amxp_expr_node_new(&node, amxp_expr_value);
250  amxc_var_set(cstring_t, value, amxc_string_take_buffer(&txt));
251  amxp_expr_node_set_value(node, value);
252  amxp_expr_node_push(&parser_ctx->nodes, node);
253  $$ = node;
254  }
255  | DIGIT {
256  amxc_var_t* value = NULL;
257  amxp_expr_node_t* node = NULL;
258  amxc_var_new(&value);
259  amxp_expr_node_new(&node, amxp_expr_value);
260  amxc_var_set(int64_t, value, $1);
261  amxp_expr_node_set_value(node, value);
262  amxp_expr_node_push(&parser_ctx->nodes, node);
263  $$ = node;
264  }
265  | BOOL {
266  amxc_var_t* value = NULL;
267  amxp_expr_node_t* node = NULL;
268  amxc_var_new(&value);
269  amxp_expr_node_new(&node, amxp_expr_value);
270  amxc_var_set(bool, value, $1);
271  amxp_expr_node_set_value(node, value);
272  amxp_expr_node_push(&parser_ctx->nodes, node);
273  $$ = node;
274  }
275  | path {
276  amxp_expr_node_t* node = NULL;
277  amxp_expr_node_new(&node, amxp_expr_field);
278  amxp_expr_node_set_field(node, amxc_string_take_buffer($1));
279  $$ = node;
280  amxp_expr_node_push(&parser_ctx->nodes, node);
281  amxc_string_delete(&$1);
282  }
283  | '[' list_values ']' {
284  amxp_expr_node_get_value(parser_ctx, $2);
285  $$ = $2;
286  }
287  | function_header '(' list_values ')' {
288  amxp_expr_node_t* node = NULL;
289  amxp_expr_node_new(&node, amxp_expr_value_func);
290  amxp_expr_node_set_function(node, strdup($1.txt));
291  amxc_llist_for_each(it, &$3->right.args) {
292  amxp_expr_node_t* arg = amxc_container_of(it, amxp_expr_node_t, it);
293  amxp_expr_node_add_value(node, arg);
294  }
295  amxp_expr_node_delete(&$3);
296  amxp_expr_node_push(&parser_ctx->nodes, node);
297  $$ = node;
298  }
299  ;
300 
301 function_header
302  : STRING {
303  $1.txt[$1.length] = 0;
304  $$ = $1;
305  }
306  ;
307 
308 list_values
309  : {
310  amxp_expr_node_t* node = NULL;
311  amxp_expr_node_new(&node, amxp_expr_value);
312  amxp_expr_node_push(&parser_ctx->nodes, node);
313  $$ = node;
314  }
315  | list_values ',' value {
316  amxp_expr_node_add_value($1, $3);
317  $$ = $1;
318  }
319  | value {
320  amxp_expr_node_t* node = NULL;
321  amxp_expr_node_new(&node, amxp_expr_value);
322  amxp_expr_node_add_value(node, $1);
323  amxp_expr_node_push(&parser_ctx->nodes, node);
324  $$ = node;
325  }
326  ;
327 
328 path
329  : path '.' STRING {
330  $3.txt[$3.length] = 0;
331  amxc_string_appendf($1, ".%s", $3.txt);
332  }
333  | path '.' DIGIT {
334  amxc_string_appendf($1, ".%" PRId64, $3);
335  }
336  | STRING {
337  amxc_string_new(&$$,0);
338  $1.txt[$1.length] = 0;
339  amxc_string_appendf($$, "%s", $1.txt);
340  }
341  | '.' STRING {
342  amxc_string_new(&$$,0);
343  $2.txt[$2.length] = 0;
344  amxc_string_appendf($$, ".%s", $2.txt);
345  }
346  | '.' DIGIT {
347  amxc_string_new(&$$,0);
348  amxc_string_appendf($$, ".%" PRId64, $2);
349  }
350  | FIELD {
351  amxc_string_new(&$$,0);
352  $1.txt[$1.length] = 0;
353  amxc_string_appendf($$, "%s", $1.txt);
354  }
355  ;
356 
357 %%