X-Git-Url: http://git.openwrt.org/?p=project%2Fjsonpath.git;a=blobdiff_plain;f=ast.c;fp=ast.c;h=5093e8b5167b61f19473e7536ab80d530ff36536;hp=0000000000000000000000000000000000000000;hb=f3830138661374ca10fe6a0b6f2f4b949dea3e5c;hpb=960dafd0b61eb14032d13c1562566618be55133f diff --git a/ast.c b/ast.c new file mode 100644 index 0000000..5093e8b --- /dev/null +++ b/ast.c @@ -0,0 +1,132 @@ +/* + * 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ast.h" +#include "lexer.h" + +#include +#include +#include +#include +#include + +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); + + if (!newop) + { + fprintf(stderr, "Out of memory\n"); + exit(127); + } + + newop->type = type; + newop->num = num; + + if (str) + newop->str = strcpy(ptr, str); + + va_start(ap, str); + + while ((child = va_arg(ap, void *)) != NULL) + if (!newop->down) + newop->down = child; + else + append_op(newop->down, child); + + va_end(ap); + + newop->next = s->pool; + s->pool = newop; + + return newop; +} + +void +jp_free(struct jp_state *s) +{ + struct jp_opcode *op, *tmp; + + for (op = s->pool; op;) + { + tmp = op->next; + free(op); + op = tmp; + } + + if (s->error) + free(s->error); + + free(s); +} + +struct jp_state * +jp_parse(const char *expr) +{ + struct jp_state *s; + struct jp_opcode *op; + const char *ptr = expr; + void *pParser; + int len = strlen(expr); + int mlen = 0; + + s = calloc(1, sizeof(*s)); + + if (!s) + return NULL; + + pParser = ParseAlloc(malloc); + + if (!pParser) + return NULL; + + while (len > 0) + { + s->off = (ptr - expr); + + op = jp_get_token(s, ptr, &mlen); + + if (mlen < 0) + { + s->erroff = s->off; + s->error = strdup((mlen == -3) ? "String too long" : + (mlen == -2) ? "Invalid escape sequence" : + (mlen == -1) ? "Unterminated string" : + "Unknown error"); + + goto out; + } + + if (op) + Parse(pParser, op->type, op, s); + + len -= mlen; + ptr += mlen; + } + + Parse(pParser, 0, NULL, s); + +out: + ParseFree(pParser, free); + + return s; +}