3 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <libubox/utils.h>
24 static struct jp_opcode *op_pool = NULL;
25 static struct jp_opcode *append_op(struct jp_opcode *a, struct jp_opcode *b);
27 int yyparse(struct jp_opcode **tree, const char **error);
28 void yyerror(struct jp_opcode **expr, const char **error, const char *msg);
35 %parse-param { struct jp_opcode **expr }
36 %parse-param { const char **error }
44 struct jp_opcode *next;
45 struct jp_opcode *down;
46 struct jp_opcode *sibling;
52 struct jp_opcode *_jp_alloc_op(int type, int num, char *str, ...);
53 #define jp_alloc_op(type, num, str, ...) _jp_alloc_op(type, num, str, ##__VA_ARGS__, NULL)
55 struct jp_opcode *jp_parse(const char *expr, const char **error);
65 %token T_ROOT T_THIS T_DOT T_BROPEN T_BRCLOSE
66 %token T_OR T_AND T_LT T_LE T_GT T_GE T_EQ T_NE T_POPEN T_PCLOSE T_NOT
68 %token <op> T_BOOL T_NUMBER T_STRING T_LABEL T_WILDCARD
70 %type <op> expr path segments segment or_exps or_exp and_exps and_exp cmp_exp unary_exp
77 : expr { *expr = $1; }
81 : T_LABEL T_EQ path { $1->down = $3; $$ = $1; }
86 : T_ROOT segments { $$ = jp_alloc_op(T_ROOT, 0, NULL, $2); }
87 | T_THIS segments { $$ = jp_alloc_op(T_THIS, 0, NULL, $2); }
91 : segments segment { $$ = append_op($1, $2); }
92 | segment { $$ = $1; }
96 : T_DOT T_LABEL { $$ = $2; }
97 | T_DOT T_WILDCARD { $$ = $2; }
98 | T_BROPEN or_exps T_BRCLOSE { $$ = $2; }
102 : or_exp { $$ = $1->sibling ? jp_alloc_op(T_OR, 0, NULL, $1) : $1; }
106 : or_exp T_OR and_exps { $$ = append_op($1, $3); }
107 | and_exps { $$ = $1; }
111 : and_exp { $$ = $1->sibling ? jp_alloc_op(T_AND, 0, NULL, $1) : $1; }
115 : and_exp T_AND cmp_exp { $$ = append_op($1, $3); }
116 | cmp_exp { $$ = $1; }
120 : unary_exp T_LT unary_exp { $$ = jp_alloc_op(T_LT, 0, NULL, $1, $3); }
121 | unary_exp T_LE unary_exp { $$ = jp_alloc_op(T_LE, 0, NULL, $1, $3); }
122 | unary_exp T_GT unary_exp { $$ = jp_alloc_op(T_GT, 0, NULL, $1, $3); }
123 | unary_exp T_GE unary_exp { $$ = jp_alloc_op(T_GE, 0, NULL, $1, $3); }
124 | unary_exp T_EQ unary_exp { $$ = jp_alloc_op(T_EQ, 0, NULL, $1, $3); }
125 | unary_exp T_NE unary_exp { $$ = jp_alloc_op(T_NE, 0, NULL, $1, $3); }
126 | unary_exp { $$ = $1; }
130 : T_BOOL { $$ = $1; }
131 | T_NUMBER { $$ = $1; }
132 | T_STRING { $$ = $1; }
133 | T_WILDCARD { $$ = $1; }
134 | T_POPEN or_exps T_PCLOSE { $$ = $2; }
135 | T_NOT unary_exp { $$ = jp_alloc_op(T_NOT, 0, NULL, $2); }
142 yyerror(struct jp_opcode **expr, const char **error, const char *msg)
148 static struct jp_opcode *
149 append_op(struct jp_opcode *a, struct jp_opcode *b)
151 struct jp_opcode *tail = a;
153 while (tail->sibling)
154 tail = tail->sibling;
162 _jp_alloc_op(int type, int num, char *str, ...)
166 struct jp_opcode *newop, *child;
168 newop = calloc_a(sizeof(*newop),
169 str ? &ptr : NULL, str ? strlen(str) + 1 : 0);
173 fprintf(stderr, "Out of memory\n");
181 newop->str = strcpy(ptr, str);
185 while ((child = va_arg(ap, void *)) != NULL)
189 append_op(newop->down, child);
193 newop->next = op_pool;
200 jp_parse(const char *expr, const char **error)
203 struct jp_opcode *tree;
205 buf = yy_scan_string(expr);
207 if (yyparse(&tree, error))
212 yy_delete_buffer(buf);
221 struct jp_opcode *op, *tmp;
223 for (op = op_pool; op;)