X-Git-Url: http://git.openwrt.org//?a=blobdiff_plain;f=parser.y;h=29b43ba12af2248ee2701541daa5743f3f216a13;hb=181cf50743241895bf64ecc453033b7b0470d230;hp=bdfc1f24a22f8408a7f9513be433ea1de017e6dc;hpb=bb372e308e2332766d038cef7bcdf74df7b0e31c;p=project%2Fjsonpath.git diff --git a/parser.y b/parser.y index bdfc1f2..29b43ba 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,233 +14,85 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +%token_type {struct jp_opcode *} +%extra_argument {struct jp_state *s} + +%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. + +%include { +#include +#include #include -#include #include -#include - +#include "ast.h" +#include "lexer.h" #include "parser.h" -static struct jp_opcode *append_op(struct jp_opcode *a, struct jp_opcode *b); - -int yylex(struct jp_state *s); -void *yy_scan_string (const char *str); -int yylex_destroy(void); - -int yyparse(struct jp_state *s); -void yyerror(struct jp_state *s, const char *msg); - -%} - -%output "parser.c" -%defines "parser.h" - -%parse-param { struct jp_state *s } -%lex-param { struct jp_state *s } - -%code provides { - -#ifndef __PARSER_H_ -#define __PARSER_H_ - -struct jp_opcode { - int type; - struct jp_opcode *next; - struct jp_opcode *down; - struct jp_opcode *sibling; - char *str; - int num; -}; - -struct jp_state { - struct jp_opcode *pool; - struct jp_opcode *path; - const char *error; - char str_buf[128]; - char *str_ptr; -}; - -struct jp_opcode *_jp_alloc_op(struct jp_state *s, int type, int num, char *str, ...); -#define jp_alloc_op(type, num, str, ...) _jp_alloc_op(s, type, num, str, ##__VA_ARGS__, NULL) - -struct jp_state *jp_parse(const char *expr); -void jp_free(struct jp_state *s); - -#endif +#define alloc_op(type, num, str, ...) \ + jp_alloc_op(s, type, num, str, ##__VA_ARGS__, NULL) } -%union { - struct jp_opcode *op; -} - - -%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 { s->path = $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_state *s, const char *msg) -{ - s->error = msg; -} +%syntax_error { + int i; -static struct jp_opcode * -append_op(struct jp_opcode *a, struct jp_opcode *b) -{ - struct jp_opcode *tail = a; + for (i = 0; i < sizeof(tokennames) / sizeof(tokennames[0]); i++) + if (yy_find_shift_action(yypParser, (YYCODETYPE)i) < YYNSTATE + YYNRULE) + s->error_code |= (1 << i); - while (tail->sibling) - tail = tail->sibling; - - tail->sibling = b; - - return a; + s->error_pos = s->off; } -struct jp_opcode * -_jp_alloc_op(struct jp_state *s, int type, int num, char *str, ...) -{ - va_list ap; - char *ptr; - struct jp_opcode *newop, *child; - newop = calloc_a(sizeof(*newop), - str ? &ptr : NULL, str ? strlen(str) + 1 : 0); +input ::= expr(A). { s->path = A; } - if (!newop) - { - fprintf(stderr, "Out of memory\n"); - exit(1); - } +expr(A) ::= T_LABEL(B) T_EQ path(C). { A = B; B->down = C; } +expr(A) ::= path(B). { A = B; } - newop->type = type; - newop->num = num; +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); } +path(A) ::= T_ROOT(B). { A = B; } +path(A) ::= T_THIS(B). { A = B; } - if (str) - newop->str = strcpy(ptr, str); +segments(A) ::= segments(B) segment(C). { A = append_op(B, C); } +segments(A) ::= segment(B). { A = B; } - va_start(ap, str); +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; } - while ((child = va_arg(ap, void *)) != NULL) - if (!newop->down) - newop->down = child; - else - append_op(newop->down, child); +union_exps(A) ::= union_exp(B). { A = B->sibling ? alloc_op(T_UNION, 0, NULL, B) : B; } - va_end(ap); +union_exp(A) ::= union_exp(B) T_UNION or_exps(C). { A = append_op(B, C); } +union_exp(A) ::= or_exps(B). { A = B; } - newop->next = s->pool; - s->pool = newop; - - return newop; -} +or_exps(A) ::= or_exp(B). { A = B->sibling ? alloc_op(T_OR, 0, NULL, B) : B; } -struct jp_state * -jp_parse(const char *expr) -{ - struct jp_state *s; +or_exp(A) ::= or_exp(B) T_OR and_exps(C). { A = append_op(B, C); } +or_exp(A) ::= and_exps(B). { A = B; } - s = calloc(1, sizeof(*s)); +and_exps(A) ::= and_exp(B). { A = B->sibling ? alloc_op(T_AND, 0, NULL, B) : B; } - if (!s) - return NULL; +and_exp(A) ::= and_exp(B) T_AND cmp_exp(C). { A = append_op(B, C); } +and_exp(A) ::= cmp_exp(B). { A = B; } - yy_scan_string(expr); +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; } - if (yyparse(s)) - s->path = NULL; - - yylex_destroy(); - - return s; -} - -void -jp_free(struct jp_state *s) -{ - struct jp_opcode *op, *tmp; - - for (op = s->pool; op;) - { - tmp = op->next; - free(op); - op = tmp; - } - - free(s); -} +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; }