summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2013-12-29 18:03:10 +0000
committerJo-Philipp Wich <jow@openwrt.org>2013-12-29 18:03:10 +0000
commitbb372e308e2332766d038cef7bcdf74df7b0e31c (patch)
tree3193b449d204cd4467fdc5d9fbbd595a127a94ad
parent054eb236c524a237f7cd156e8e71151b1b4e0ace (diff)
downloadjsonpath-bb372e308e2332766d038cef7bcdf74df7b0e31c.tar.gz
eliminate global variables and use a private parser/lexer state
-rw-r--r--lexer.l65
-rw-r--r--main.c24
-rw-r--r--parser.y100
3 files changed, 105 insertions, 84 deletions
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);
}
<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 <stdio.h>
+#include <stdlib.h>
#include <stdarg.h>
+#include <string.h>
+
#include <libubox/utils.h>
-#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);
}