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.
23 #include <libubox/utils.h>
27 static struct jp_opcode *append_op(struct jp_opcode *a, struct jp_opcode *b);
29 int yylex(struct jp_state *s);
30 void *yy_scan_string (const char *str);
31 int yylex_destroy(void);
33 int yyparse(struct jp_state *s);
34 void yyerror(struct jp_state *s, const char *msg);
41 %parse-param { struct jp_state *s }
42 %lex-param { struct jp_state *s }
51 struct jp_opcode *next;
52 struct jp_opcode *down;
53 struct jp_opcode *sibling;
59 struct jp_opcode *pool;
60 struct jp_opcode *path;
66 struct jp_opcode *_jp_alloc_op(struct jp_state *s, int type, int num, char *str, ...);
67 #define jp_alloc_op(type, num, str, ...) _jp_alloc_op(s, type, num, str, ##__VA_ARGS__, NULL)
69 struct jp_state *jp_parse(const char *expr);
70 void jp_free(struct jp_state *s);
81 %token T_ROOT T_THIS T_DOT T_BROPEN T_BRCLOSE
82 %token T_OR T_AND T_LT T_LE T_GT T_GE T_EQ T_NE T_POPEN T_PCLOSE T_NOT
84 %token <op> T_BOOL T_NUMBER T_STRING T_LABEL T_WILDCARD
86 %type <op> expr path segments segment or_exps or_exp and_exps and_exp cmp_exp unary_exp
93 : expr { s->path = $1; }
97 : T_LABEL T_EQ path { $1->down = $3; $$ = $1; }
102 : T_ROOT segments { $$ = jp_alloc_op(T_ROOT, 0, NULL, $2); }
103 | T_THIS segments { $$ = jp_alloc_op(T_THIS, 0, NULL, $2); }
107 : segments segment { $$ = append_op($1, $2); }
108 | segment { $$ = $1; }
112 : T_DOT T_LABEL { $$ = $2; }
113 | T_DOT T_WILDCARD { $$ = $2; }
114 | T_BROPEN or_exps T_BRCLOSE { $$ = $2; }
118 : or_exp { $$ = $1->sibling ? jp_alloc_op(T_OR, 0, NULL, $1) : $1; }
122 : or_exp T_OR and_exps { $$ = append_op($1, $3); }
123 | and_exps { $$ = $1; }
127 : and_exp { $$ = $1->sibling ? jp_alloc_op(T_AND, 0, NULL, $1) : $1; }
131 : and_exp T_AND cmp_exp { $$ = append_op($1, $3); }
132 | cmp_exp { $$ = $1; }
136 : unary_exp T_LT unary_exp { $$ = jp_alloc_op(T_LT, 0, NULL, $1, $3); }
137 | unary_exp T_LE unary_exp { $$ = jp_alloc_op(T_LE, 0, NULL, $1, $3); }
138 | unary_exp T_GT unary_exp { $$ = jp_alloc_op(T_GT, 0, NULL, $1, $3); }
139 | unary_exp T_GE unary_exp { $$ = jp_alloc_op(T_GE, 0, NULL, $1, $3); }
140 | unary_exp T_EQ unary_exp { $$ = jp_alloc_op(T_EQ, 0, NULL, $1, $3); }
141 | unary_exp T_NE unary_exp { $$ = jp_alloc_op(T_NE, 0, NULL, $1, $3); }
142 | unary_exp { $$ = $1; }
146 : T_BOOL { $$ = $1; }
147 | T_NUMBER { $$ = $1; }
148 | T_STRING { $$ = $1; }
149 | T_WILDCARD { $$ = $1; }
150 | T_POPEN or_exps T_PCLOSE { $$ = $2; }
151 | T_NOT unary_exp { $$ = jp_alloc_op(T_NOT, 0, NULL, $2); }
158 yyerror(struct jp_state *s, const char *msg)
163 static struct jp_opcode *
164 append_op(struct jp_opcode *a, struct jp_opcode *b)
166 struct jp_opcode *tail = a;
168 while (tail->sibling)
169 tail = tail->sibling;
177 _jp_alloc_op(struct jp_state *s, int type, int num, char *str, ...)
181 struct jp_opcode *newop, *child;
183 newop = calloc_a(sizeof(*newop),
184 str ? &ptr : NULL, str ? strlen(str) + 1 : 0);
188 fprintf(stderr, "Out of memory\n");
196 newop->str = strcpy(ptr, str);
200 while ((child = va_arg(ap, void *)) != NULL)
204 append_op(newop->down, child);
208 newop->next = s->pool;
215 jp_parse(const char *expr)
219 s = calloc(1, sizeof(*s));
224 yy_scan_string(expr);
235 jp_free(struct jp_state *s)
237 struct jp_opcode *op, *tmp;
239 for (op = s->pool; op;)