From: Jo-Philipp Wich Date: Sun, 29 Dec 2013 18:03:10 +0000 (+0000) Subject: eliminate global variables and use a private parser/lexer state X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fjsonpath.git;a=commitdiff_plain;h=bb372e308e2332766d038cef7bcdf74df7b0e31c eliminate global variables and use a private parser/lexer state --- diff --git a/lexer.l b/lexer.l index e3467bc..a480ca7 100644 --- a/lexer.l +++ b/lexer.l @@ -19,18 +19,19 @@ #include "parser.h" -static char *str_ptr; -static char str_buf[128]; +int yylex(struct jp_state *s); + +#define YY_DECL int yylex(struct jp_state *s) static void -str_put(char c) +str_put(struct jp_state *s, char c) { - if ((str_ptr - str_buf + 1) < sizeof(str_buf)) - *str_ptr++ = c; + if ((s->str_ptr - s->str_buf + 1) < sizeof(s->str_buf)) + *s->str_ptr++ = c; } static void -str_decode(const char *input, int base) +str_decode(struct jp_state *s, const char *input, int base) { int code; char *end; @@ -42,25 +43,25 @@ str_decode(const char *input, int base) if (code > 0 && code <= 0x7F) { - str_put(code); + str_put(s, code); } else if (code > 0 && code <= 0x7FF) { - str_put(((code >> 6) & 0x1F) | 0xC0); - str_put(( code & 0x3F) | 0x80); + str_put(s, ((code >> 6) & 0x1F) | 0xC0); + str_put(s, ( code & 0x3F) | 0x80); } else if (code > 0 && code <= 0xFFFF) { - str_put(((code >> 12) & 0x0F) | 0xE0); - str_put(((code >> 6) & 0x3F) | 0x80); - str_put(( code & 0x3F) | 0x80); + str_put(s, ((code >> 12) & 0x0F) | 0xE0); + str_put(s, ((code >> 6) & 0x3F) | 0x80); + str_put(s, ( code & 0x3F) | 0x80); } else if (code > 0 && code <= 0x10FFFF) { - str_put(((code >> 18) & 0x07) | 0xF0); - str_put(((code >> 12) & 0x3F) | 0x80); - str_put(((code >> 6) & 0x3F) | 0x80); - str_put(( code & 0x3F) | 0x80); + str_put(s, ((code >> 18) & 0x07) | 0xF0); + str_put(s, ((code >> 12) & 0x3F) | 0x80); + str_put(s, ((code >> 6) & 0x3F) | 0x80); + str_put(s, ( code & 0x3F) | 0x80); } } @@ -101,31 +102,31 @@ WS [ \t\n]* %% \" { - str_ptr = str_buf; - memset(str_buf, 0, sizeof(str_buf)); + s->str_ptr = s->str_buf; + memset(s->str_buf, 0, sizeof(s->str_buf)); BEGIN(STRING); } { \" { BEGIN(INITIAL); - yylval.op = jp_alloc_op(T_STRING, 0, str_buf); + yylval.op = jp_alloc_op(T_STRING, 0, s->str_buf); return T_STRING; } - \\([0-3][0-7]{1,2}|[0-7]{0,2}) { str_decode(yytext + 1, 8); } - \\x[A-Fa-f0-9]{2} { str_decode(yytext + 2, 16); } - \\u[A-Fa-f0-9]{4} { str_decode(yytext + 2, 16); } - \\a { str_put('\a'); } - \\b { str_put('\b'); } - \\e { str_put('\e'); } - \\f { str_put('\f'); } - \\n { str_put('\n'); } - \\r { str_put('\r'); } - \\t { str_put('\t'); } - \\v { str_put('\v'); } - \\. { str_put(*yytext); } - [^\\"]+ { while (*yytext) str_put(*yytext++); } + \\([0-3][0-7]{1,2}|[0-7]{0,2}) { str_decode(s, yytext + 1, 8); } + \\x[A-Fa-f0-9]{2} { str_decode(s, yytext + 2, 16); } + \\u[A-Fa-f0-9]{4} { str_decode(s, yytext + 2, 16); } + \\a { str_put(s, '\a'); } + \\b { str_put(s, '\b'); } + \\e { str_put(s, '\e'); } + \\f { str_put(s, '\f'); } + \\n { str_put(s, '\n'); } + \\r { str_put(s, '\r'); } + \\t { str_put(s, '\t'); } + \\v { str_put(s, '\v'); } + \\. { str_put(s, *yytext); } + [^\\"]+ { while (*yytext) str_put(s, *yytext++); } } {BOOL} { diff --git a/main.c b/main.c index 7a19091..05e445c 100644 --- a/main.c +++ b/main.c @@ -76,23 +76,25 @@ static void export_json(struct json_object *jsobj, char *expr) { bool first; - struct jp_opcode *tree; + struct jp_state *state; struct json_object *res; - const char *error, *prefix; + const char *prefix; - tree = jp_parse(expr, &error); + state = jp_parse(expr); - if (error) + if (!state || state->error) { - fprintf(stderr, "In expression '%s': %s\n", expr, error); - return; + fprintf(stderr, "In expression '%s': %s\n", + expr, state ? state->error : "Out of memory"); + + goto out; } - res = jp_match(tree, jsobj); + res = jp_match(state->path, jsobj); - if (tree->type == T_LABEL) + if (state->path->type == T_LABEL) { - prefix = tree->str; + prefix = state->path->str; switch (json_object_get_type(res)) { @@ -163,7 +165,9 @@ export_json(struct json_object *jsobj, char *expr) printf("%s\n", json_object_to_json_string(res)); } - jp_free(); +out: + if (state) + jp_free(state); } int main(int argc, char **argv) diff --git a/parser.y b/parser.y index 40b25f5..bdfc1f2 100644 --- a/parser.y +++ b/parser.y @@ -15,45 +15,61 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include #include +#include + #include -#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); +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_opcode **expr } -%parse-param { const char **error } +%parse-param { struct jp_state *s } +%lex-param { struct jp_state *s } %code provides { -#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 +#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(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_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_opcode *jp_parse(const char *expr, const char **error); -void jp_free(void); +struct jp_state *jp_parse(const char *expr); +void jp_free(struct jp_state *s); + +#endif } @@ -74,7 +90,7 @@ void jp_free(void); %% input - : expr { *expr = $1; } + : expr { s->path = $1; } ; expr @@ -139,10 +155,9 @@ unary_exp %% void -yyerror(struct jp_opcode **expr, const char **error, const char *msg) +yyerror(struct jp_state *s, const char *msg) { - *error = msg; - jp_free(); + s->error = msg; } static struct jp_opcode * @@ -159,7 +174,7 @@ append_op(struct jp_opcode *a, struct jp_opcode *b) } struct jp_opcode * -_jp_alloc_op(int type, int num, char *str, ...) +_jp_alloc_op(struct jp_state *s, int type, int num, char *str, ...) { va_list ap; char *ptr; @@ -190,42 +205,43 @@ _jp_alloc_op(int type, int num, char *str, ...) va_end(ap); - newop->next = op_pool; - op_pool = newop; + newop->next = s->pool; + s->pool = newop; return newop; } -struct jp_opcode * -jp_parse(const char *expr, const char **error) +struct jp_state * +jp_parse(const char *expr) { - void *buf; - struct jp_opcode *tree; + struct jp_state *s; + + s = calloc(1, sizeof(*s)); + + if (!s) + return NULL; - buf = yy_scan_string(expr); + yy_scan_string(expr); - if (yyparse(&tree, error)) - tree = NULL; - else - *error = NULL; + if (yyparse(s)) + s->path = NULL; - yy_delete_buffer(buf); yylex_destroy(); - return tree; + return s; } void -jp_free(void) +jp_free(struct jp_state *s) { struct jp_opcode *op, *tmp; - for (op = op_pool; op;) + for (op = s->pool; op;) { tmp = op->next; free(op); op = tmp; } - op_pool = NULL; + free(s); }