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;
67 struct jp_opcode *_jp_alloc_op(struct jp_state *s, int type, int num, char *str, ...);
68 #define jp_alloc_op(type, num, str, ...) _jp_alloc_op(s, type, num, str, ##__VA_ARGS__, NULL)
70 struct jp_state *jp_parse(const char *expr);
71 void jp_free(struct jp_state *s);
82 %token T_ROOT T_THIS T_DOT T_BROPEN T_BRCLOSE
83 %token T_OR T_AND T_LT T_LE T_GT T_GE T_EQ T_NE T_POPEN T_PCLOSE T_NOT
85 %token <op> T_BOOL T_NUMBER T_STRING T_LABEL T_WILDCARD
87 %type <op> expr path segments segment or_exps or_exp and_exps and_exp cmp_exp unary_exp
94 : expr { s->path = $1; }
98 : T_LABEL T_EQ path { $1->down = $3; $$ = $1; }
103 : T_ROOT segments { $$ = jp_alloc_op(T_ROOT, 0, NULL, $2); }
104 | T_THIS segments { $$ = jp_alloc_op(T_THIS, 0, NULL, $2); }
108 : segments segment { $$ = append_op($1, $2); }
109 | segment { $$ = $1; }
113 : T_DOT T_LABEL { $$ = $2; }
114 | T_DOT T_WILDCARD { $$ = $2; }
115 | T_BROPEN or_exps T_BRCLOSE { $$ = $2; }
119 : or_exp { $$ = $1->sibling ? jp_alloc_op(T_OR, 0, NULL, $1) : $1; }
123 : or_exp T_OR and_exps { $$ = append_op($1, $3); }
124 | and_exps { $$ = $1; }
128 : and_exp { $$ = $1->sibling ? jp_alloc_op(T_AND, 0, NULL, $1) : $1; }
132 : and_exp T_AND cmp_exp { $$ = append_op($1, $3); }
133 | cmp_exp { $$ = $1; }
137 : unary_exp T_LT unary_exp { $$ = jp_alloc_op(T_LT, 0, NULL, $1, $3); }
138 | unary_exp T_LE unary_exp { $$ = jp_alloc_op(T_LE, 0, NULL, $1, $3); }
139 | unary_exp T_GT unary_exp { $$ = jp_alloc_op(T_GT, 0, NULL, $1, $3); }
140 | unary_exp T_GE unary_exp { $$ = jp_alloc_op(T_GE, 0, NULL, $1, $3); }
141 | unary_exp T_EQ unary_exp { $$ = jp_alloc_op(T_EQ, 0, NULL, $1, $3); }
142 | unary_exp T_NE unary_exp { $$ = jp_alloc_op(T_NE, 0, NULL, $1, $3); }
143 | unary_exp { $$ = $1; }
147 : T_BOOL { $$ = $1; }
148 | T_NUMBER { $$ = $1; }
149 | T_STRING { $$ = $1; }
150 | T_WILDCARD { $$ = $1; }
151 | T_POPEN or_exps T_PCLOSE { $$ = $2; }
152 | T_NOT unary_exp { $$ = jp_alloc_op(T_NOT, 0, NULL, $2); }
159 yyerror(struct jp_state *s, const char *msg)
164 static struct jp_opcode *
165 append_op(struct jp_opcode *a, struct jp_opcode *b)
167 struct jp_opcode *tail = a;
169 while (tail->sibling)
170 tail = tail->sibling;
178 _jp_alloc_op(struct jp_state *s, int type, int num, char *str, ...)
182 struct jp_opcode *newop, *child;
184 newop = calloc_a(sizeof(*newop),
185 str ? &ptr : NULL, str ? strlen(str) + 1 : 0);
189 fprintf(stderr, "Out of memory\n");
197 newop->str = strcpy(ptr, str);
201 while ((child = va_arg(ap, void *)) != NULL)
205 append_op(newop->down, child);
209 newop->next = s->pool;
216 jp_parse(const char *expr)
220 s = calloc(1, sizeof(*s));
225 yy_scan_string(expr);
236 jp_free(struct jp_state *s)
238 struct jp_opcode *op, *tmp;
240 for (op = s->pool; op;)