X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=parser.y;h=9c06c07c4a90a1eeed05a9a072727576db6e346d;hb=f3830138661374ca10fe6a0b6f2f4b949dea3e5c;hp=40b25f5e1fa2237df1b692ee264bd8ff5df73a15;hpb=ba3e89199b78c33fc5b0dce6a4456096c71c2e19;p=project%2Fjsonpath.git diff --git a/parser.y b/parser.y index 40b25f5..9c06c07 100644 --- a/parser.y +++ b/parser.y @@ -1,6 +1,5 @@ -%{ /* - * Copyright (C) 2013 Jo-Philipp Wich + * Copyright (C) 2013-2014 Jo-Philipp Wich * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,217 +14,105 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include +%token_type {struct jp_opcode *} +%extra_argument {struct jp_state *s} -#include "lexer.h" -#include "parser.h" - -static struct jp_opcode *op_pool = NULL; -static struct jp_opcode *append_op(struct jp_opcode *a, struct jp_opcode *b); - -int yyparse(struct jp_opcode **tree, const char **error); -void yyerror(struct jp_opcode **expr, const char **error, const char *msg); - -%} - -%output "parser.c" -%defines "parser.h" - -%parse-param { struct jp_opcode **expr } -%parse-param { const char **error } +%left T_AND. +%left T_OR. +%left T_UNION. +%nonassoc T_EQ T_NE T_GT T_GE T_LT T_LE. +%right T_NOT. -%code provides { +%include { +#include +#include +#include +#include -#ifndef JP_OPCODE -# define JP_OPCODE - struct jp_opcode { - int type; - struct jp_opcode *next; - struct jp_opcode *down; - struct jp_opcode *sibling; - char *str; - int num; - }; -#endif - -struct jp_opcode *_jp_alloc_op(int type, int num, char *str, ...); -#define jp_alloc_op(type, num, str, ...) _jp_alloc_op(type, num, str, ##__VA_ARGS__, NULL) - -struct jp_opcode *jp_parse(const char *expr, const char **error); -void jp_free(void); - -} - -%union { - struct jp_opcode *op; -} +#include "ast.h" +#include "lexer.h" +#include "parser.h" +#define alloc_op(type, num, str, ...) \ + jp_alloc_op(s, type, num, str, ##__VA_ARGS__, NULL) -%token T_ROOT T_THIS T_DOT T_BROPEN T_BRCLOSE -%token T_OR T_AND T_LT T_LE T_GT T_GE T_EQ T_NE T_POPEN T_PCLOSE T_NOT - -%token T_BOOL T_NUMBER T_STRING T_LABEL T_WILDCARD - -%type expr path segments segment or_exps or_exp and_exps and_exp cmp_exp unary_exp - -%error-verbose - -%% - -input - : expr { *expr = $1; } - ; - -expr - : T_LABEL T_EQ path { $1->down = $3; $$ = $1; } - | path { $$ = $1; } - ; - -path - : T_ROOT segments { $$ = jp_alloc_op(T_ROOT, 0, NULL, $2); } - | T_THIS segments { $$ = jp_alloc_op(T_THIS, 0, NULL, $2); } - ; - -segments - : segments segment { $$ = append_op($1, $2); } - | segment { $$ = $1; } - ; - -segment - : T_DOT T_LABEL { $$ = $2; } - | T_DOT T_WILDCARD { $$ = $2; } - | T_BROPEN or_exps T_BRCLOSE { $$ = $2; } - ; - -or_exps - : or_exp { $$ = $1->sibling ? jp_alloc_op(T_OR, 0, NULL, $1) : $1; } - ; - -or_exp - : or_exp T_OR and_exps { $$ = append_op($1, $3); } - | and_exps { $$ = $1; } - ; - -and_exps - : and_exp { $$ = $1->sibling ? jp_alloc_op(T_AND, 0, NULL, $1) : $1; } - ; - -and_exp - : and_exp T_AND cmp_exp { $$ = append_op($1, $3); } - | cmp_exp { $$ = $1; } - ; - -cmp_exp - : unary_exp T_LT unary_exp { $$ = jp_alloc_op(T_LT, 0, NULL, $1, $3); } - | unary_exp T_LE unary_exp { $$ = jp_alloc_op(T_LE, 0, NULL, $1, $3); } - | unary_exp T_GT unary_exp { $$ = jp_alloc_op(T_GT, 0, NULL, $1, $3); } - | unary_exp T_GE unary_exp { $$ = jp_alloc_op(T_GE, 0, NULL, $1, $3); } - | unary_exp T_EQ unary_exp { $$ = jp_alloc_op(T_EQ, 0, NULL, $1, $3); } - | unary_exp T_NE unary_exp { $$ = jp_alloc_op(T_NE, 0, NULL, $1, $3); } - | unary_exp { $$ = $1; } - ; - -unary_exp - : T_BOOL { $$ = $1; } - | T_NUMBER { $$ = $1; } - | T_STRING { $$ = $1; } - | T_WILDCARD { $$ = $1; } - | T_POPEN or_exps T_PCLOSE { $$ = $2; } - | T_NOT unary_exp { $$ = jp_alloc_op(T_NOT, 0, NULL, $2); } - | path { $$ = $1; } - ; - -%% - -void -yyerror(struct jp_opcode **expr, const char **error, const char *msg) -{ - *error = msg; - jp_free(); } -static struct jp_opcode * -append_op(struct jp_opcode *a, struct jp_opcode *b) -{ - struct jp_opcode *tail = a; - - while (tail->sibling) - tail = tail->sibling; +%syntax_error { + int n = sizeof(tokennames) / sizeof(tokennames[0]); + int l = strlen("Expecting "); + int c = 0; + int i; - tail->sibling = b; - - return a; -} - -struct jp_opcode * -_jp_alloc_op(int type, int num, char *str, ...) -{ - va_list ap; - char *ptr; - struct jp_opcode *newop, *child; + for (i = 0; i < n; i++) + { + if (yy_find_shift_action(yypParser, (YYCODETYPE)i) < YYNSTATE + YYNRULE) + l += strlen(tokennames[i]) + 4; + } - newop = calloc_a(sizeof(*newop), - str ? &ptr : NULL, str ? strlen(str) + 1 : 0); + s->error = malloc(l); - if (!newop) + if (s->error) { - fprintf(stderr, "Out of memory\n"); - exit(1); + s->erroff = s->off; + strcpy(s->error, "Expecting "); + + for (i = 0; i < n; i++) + { + if (yy_find_shift_action(yypParser, (YYCODETYPE)i) < YYNSTATE + YYNRULE) + { + if (c++) + strcat(s->error, " or "); + + strcat(s->error, tokennames[i]); + } + } } +} - newop->type = type; - newop->num = num; - if (str) - newop->str = strcpy(ptr, str); +input ::= expr(A). { s->path = A; } - va_start(ap, str); +expr(A) ::= T_LABEL(B) T_EQ path(C). { A = B; B->down = C; } +expr(A) ::= path(B). { A = B; } - while ((child = va_arg(ap, void *)) != NULL) - if (!newop->down) - newop->down = child; - else - append_op(newop->down, child); +path(A) ::= T_ROOT segments(B). { A = alloc_op(T_ROOT, 0, NULL, B); } +path(A) ::= T_THIS segments(B). { A = alloc_op(T_THIS, 0, NULL, B); } - va_end(ap); +segments(A) ::= segments(B) segment(C). { A = append_op(B, C); } +segments(A) ::= segment(B). { A = B; } - newop->next = op_pool; - op_pool = newop; +segment(A) ::= T_DOT T_LABEL(B). { A = B; } +segment(A) ::= T_DOT T_WILDCARD(B). { A = B; } +segment(A) ::= T_BROPEN union_exps(B) T_BRCLOSE. { A = B; } - return newop; -} +union_exps(A) ::= union_exp(B). { A = B->sibling ? alloc_op(T_UNION, 0, NULL, B) : B; } -struct jp_opcode * -jp_parse(const char *expr, const char **error) -{ - void *buf; - struct jp_opcode *tree; +union_exp(A) ::= union_exp(B) T_UNION or_exps(C). { A = append_op(B, C); } +union_exp(A) ::= or_exps(B). { A = B; } - buf = yy_scan_string(expr); +or_exps(A) ::= or_exp(B). { A = B->sibling ? alloc_op(T_OR, 0, NULL, B) : B; } - if (yyparse(&tree, error)) - tree = NULL; - else - *error = NULL; +or_exp(A) ::= or_exp(B) T_OR and_exps(C). { A = append_op(B, C); } +or_exp(A) ::= and_exps(B). { A = B; } - yy_delete_buffer(buf); - yylex_destroy(); +and_exps(A) ::= and_exp(B). { A = B->sibling ? alloc_op(T_AND, 0, NULL, B) : B; } - return tree; -} +and_exp(A) ::= and_exp(B) T_AND cmp_exp(C). { A = append_op(B, C); } +and_exp(A) ::= cmp_exp(B). { A = B; } -void -jp_free(void) -{ - struct jp_opcode *op, *tmp; +cmp_exp(A) ::= unary_exp(B) T_LT unary_exp(C). { A = alloc_op(T_LT, 0, NULL, B, C); } +cmp_exp(A) ::= unary_exp(B) T_LE unary_exp(C). { A = alloc_op(T_LE, 0, NULL, B, C); } +cmp_exp(A) ::= unary_exp(B) T_GT unary_exp(C). { A = alloc_op(T_GT, 0, NULL, B, C); } +cmp_exp(A) ::= unary_exp(B) T_GE unary_exp(C). { A = alloc_op(T_GE, 0, NULL, B, C); } +cmp_exp(A) ::= unary_exp(B) T_EQ unary_exp(C). { A = alloc_op(T_EQ, 0, NULL, B, C); } +cmp_exp(A) ::= unary_exp(B) T_NE unary_exp(C). { A = alloc_op(T_NE, 0, NULL, B, C); } +cmp_exp(A) ::= unary_exp(B). { A = B; } - for (op = op_pool; op;) - { - tmp = op->next; - free(op); - op = tmp; - } - - op_pool = NULL; -} +unary_exp(A) ::= T_BOOL(B). { A = B; } +unary_exp(A) ::= T_NUMBER(B). { A = B; } +unary_exp(A) ::= T_STRING(B). { A = B; } +unary_exp(A) ::= T_WILDCARD(B). { A = B; } +unary_exp(A) ::= T_POPEN or_exps(B) T_PCLOSE. { A = B; } +unary_exp(A) ::= T_NOT unary_exp(B). { A = alloc_op(T_NOT, 0, NULL, B); } +unary_exp(A) ::= path(B). { A = B; }