eliminate global variables and use a private parser/lexer state
authorJo-Philipp Wich <jow@openwrt.org>
Sun, 29 Dec 2013 18:03:10 +0000 (18:03 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Sun, 29 Dec 2013 18:03:10 +0000 (18:03 +0000)
lexer.l
main.c
parser.y

diff --git a/lexer.l b/lexer.l
index e3467bc93bc1be54c2094aeaa7377ff30cccd75b..a480ca7d1bb01ff035c00bf9d9984bd2fe0eb4e1 100644 (file)
--- a/lexer.l
+++ b/lexer.l
 
 #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 7a19091900573f656617c5ea699afac7c45eff7a..05e445c1569353f666aac89a2c872409e3c57b03 100644 (file)
--- 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)
index 40b25f5e1fa2237df1b692ee264bd8ff5df73a15..bdfc1f24a22f8408a7f9513be433ea1de017e6dc 100644 (file)
--- a/parser.y
+++ b/parser.y
  * 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);
 }