]> git.ipfire.org Git - people/ms/pakfire.git/commitdiff
parser: Introduce new data type for declarations
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 25 Feb 2021 11:17:24 +0000 (11:17 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 25 Feb 2021 11:17:24 +0000 (11:17 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/include/pakfire/parser.h
src/libpakfire/parser.c
src/libpakfire/parser/grammar.y

index 98e4ba81cc5a351020ba08cb895a910fef6c22a5..299d63bf5848f494405e52fca1fe8290f1a6b74c 100644 (file)
@@ -58,6 +58,9 @@ struct pakfire_parser_declaration {
        char* value;
 };
 
+int pakfire_parser_apply_declaration(
+       PakfireParser parser, struct pakfire_parser_declaration* declaration);
+
 int pakfire_parser_parse_data(PakfireParser parser, const char* data, size_t len);
 
 #endif /* PAKFIRE_PRIVATE */
index 06a78e49e8ccce345e4cf6140244523c881d01f7..3f530810d62a1853527c2f1d05561b1eb371ffcc 100644 (file)
@@ -187,8 +187,8 @@ static int pakfire_parser_set_declaration(PakfireParser parser,
                if (value)
                        d->value = strdup(value);
 
-               DEBUG(parser->pakfire, "Updated declaration: %s = %s\n",
-                       d->name, d->value);
+               DEBUG(parser->pakfire, "%p: Updated declaration: %s = %s\n",
+                       parser, d->name, d->value);
 
                // All done
                return 0;
@@ -204,7 +204,7 @@ static int pakfire_parser_set_declaration(PakfireParser parser,
        if (value)
                d->value = strdup(value);
 
-       DEBUG(parser->pakfire, "New declaration: %s = %s\n", d->name, d->value);
+       DEBUG(parser->pakfire, "%p: New declaration: %s = %s\n", parser, d->name, d->value);
 
        // Assign new declaration to array
        parser->declarations = reallocarray(parser->declarations,
@@ -223,6 +223,11 @@ PAKFIRE_EXPORT int pakfire_parser_set(PakfireParser parser, const char* name, co
        return r;
 }
 
+int pakfire_parser_apply_declaration(PakfireParser parser,
+               struct pakfire_parser_declaration* declaration) {
+       return pakfire_parser_set(parser, declaration->name, declaration->value);
+}
+
 static const char* pakfire_parser_get_raw(PakfireParser parser, const char* name) {
        struct pakfire_parser_declaration* d = pakfire_parser_get_declaration(parser, name);
 
index 7885ed07ce493b30b29e913885796cba7c60cb4a..e8b3e80c20c52efd5a8884af5f04cdd276dadef1 100644 (file)
 #                                                                             #
 #############################################################################*/
 
-%parse-param {PakfireParser parser}
+%parse-param {Pakfire pakfire} {PakfireParser* result}
 
 // Generate verbose error messages
 %define parse.error verbose
 
 %{
+
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
@@ -49,7 +51,7 @@ extern int yylex();
 extern int yyparse();
 
 extern int num_lines;
-static void yyerror(PakfireParser parser, const char* s);
+static void yyerror(Pakfire pakfire, PakfireParser* result, const char* s);
 
 #define ABORT do { YYABORT; } while (0);
 
@@ -57,10 +59,42 @@ enum operator {
        OP_EQUALS = 0,
 };
 
-static PakfireParser make_if_stmt(PakfireParser parser, const enum operator op,
+static PakfireParser make_if_stmt(Pakfire pakfire, PakfireParser* parser, const enum operator op,
                const char* val1, const char* val2, PakfireParser if_block, PakfireParser else_block);
 static PakfireParser make_child(PakfireParser parent, const char* namespace);
 
+static inline int pakfire_parser_new_declaration(
+               struct pakfire_parser_declaration** declaration, const char* name, const char* value) {
+       if (!name)
+               return EINVAL;
+
+       struct pakfire_parser_declaration* d = malloc(sizeof(*d));
+       if (!d)
+               return ENOMEM;
+
+       // Copy name
+       d->name = strdup(name);
+
+       // Copy value
+       if (value)
+               d->value = strdup(value);
+       else
+               d->value = NULL;
+
+       *declaration = d;
+
+       return 0;
+}
+
+static void pakfire_parser_free_declaration(struct pakfire_parser_declaration* declaration) {
+       free(declaration->name);
+
+       if (declaration->value)
+               free(declaration->value);
+
+       free(declaration);
+}
+
 %}
 
 %token                                         T_INDENT
@@ -89,6 +123,7 @@ static PakfireParser make_child(PakfireParser parent, const char* namespace);
 
 %type <string>                         key
 %type <string>                         value
+%type <declaration>                    declaration
 
 %type <string>                         lines
 %type <string>                         line
@@ -96,58 +131,71 @@ static PakfireParser make_child(PakfireParser parent, const char* namespace);
 %union {
        PakfireParser parser;
        char* string;
+       struct pakfire_parser_declaration* declaration;
 }
 
+%destructor { pakfire_parser_unref($$); } <parser>
+%destructor { pakfire_parser_free_declaration($$); } <declaration>
+
 %start grammar
 
 %%
 
 grammar                                                : %empty
                                                        {
-                                                               $$ = make_child(parser, NULL);
+                                                               $$ = pakfire_parser_create(pakfire, NULL, NULL);
+                                                               if (!$$)
+                                                                       ABORT;
+
+                                                               if (!*result)
+                                                                       *result = $$;
                                                        }
                                                        | grammar declaration
+                                                       {
+                                                               int r = pakfire_parser_apply_declaration($1, $2);
+                                                               if (r)
+                                                                       ABORT;
+
+                                                               $$ = pakfire_parser_ref($1);
+                                                       }
                                                        | grammar subparser
                                                        {
-                                                               if ($2) {
-                                                                       $$ = pakfire_parser_merge($1, $2);
-                                                                       //pakfire_parser_unref($2);
-                                                               }
+                                                               pakfire_parser_merge($1, $2);
+                                                               $$ = pakfire_parser_ref($1);
                                                        }
                                                        | grammar if_stmt
                                                        {
-                                                               if ($2) {
-                                                                       $$ = pakfire_parser_merge($1, $2);
-                                                                       //pakfire_parser_unref($2);
-                                                               }
+                                                               pakfire_parser_merge($1, $2);
+                                                               $$ = pakfire_parser_ref($1);
                                                        }
                                                        | grammar empty
                                                        {
-                                                               $$ = $1;
+                                                               $$ = pakfire_parser_ref($1);
                                                        }
                                                        ;
 
 subgrammar                                     : T_INDENT grammar T_OUTDENT
                                                        {
-                                                               $$ = $2;
+                                                               $$ = pakfire_parser_ref($2);
                                                        }
                                                        ;
 
 declaration                                    : key T_ASSIGN value T_EOL
                                                        {
-                                                               int r = pakfire_parser_set(parser, $1, $3);
+                                                               int r = pakfire_parser_new_declaration(&$$, $1, $3);
                                                                if (r)
                                                                        ABORT;
                                                        }
                                                        | key T_APPEND value T_EOL
                                                        {
-                                                               int r = pakfire_parser_append(parser, $1, $3);
+                                                               // XXX HANDLE APPEND PROPERLY
+                                                               int r = pakfire_parser_new_declaration(&$$, $1, $3);
                                                                if (r)
                                                                        ABORT;
                                                        }
                                                        | key T_EOL T_INDENT lines T_OUTDENT T_END T_EOL
                                                        {
-                                                               int r = pakfire_parser_set(parser, $1, $4);
+                                                               int r = pakfire_parser_new_declaration(&$$, $1, $4);
                                                                if (r)
                                                                        ABORT;
                                                        }                                                       
@@ -184,55 +232,22 @@ line                                              : T_STRING T_EOL
                                                        }
                                                        ;
 
-subparser                                      : subparser_open T_INDENT grammar T_OUTDENT subparser_close
+subparser                                      : T_SUBPARSER T_EOL subgrammar T_END T_EOL
                                                        {
-                                                               // Move back to the parent parser
-                                                               parser = pakfire_parser_get_parent(parser);
-
-                                                               // Merge block into the parent parser
-                                                               $$ = pakfire_parser_merge(parser, $3);
-
-                                                               // Free block parser
-                                                               pakfire_parser_unref($3);
+                                                               // XXX HANDLE NAMESPACE
+                                                               $$ = pakfire_parser_ref($3);
                                                        }
                                                        ;
 
-subparser_open                         : T_SUBPARSER T_EOL
+if_stmt                                                : T_IF T_STRING T_EQUALS T_STRING T_EOL subgrammar else_stmt T_END T_EOL
                                                        {
-                                                               // Create a new sub-parser which opens a new namespace
-                                                               parser = make_child(parser, $1);
+                                                               $$ = make_if_stmt(pakfire, result, OP_EQUALS, $2, $4, $6, $7);
                                                        }
                                                        ;
 
-subparser_close                                : T_END T_EOL;
-
-if                                                     : T_IF
-                                                       {
-                                                               // Open a new block
-                                                               parser = make_child(parser, NULL);
-                                                       };
-
-else                                           : T_ELSE T_EOL
+else_stmt                                      : T_ELSE T_EOL subgrammar
                                                        {
-                                                               // Close the if block
-                                                               parser = pakfire_parser_get_parent(parser);
-
-                                                               // Open a new else block
-                                                               parser = make_child(parser, NULL);
-                                                       };
-
-if_stmt                                                : if T_STRING T_EQUALS T_STRING T_EOL subgrammar else_stmt T_END T_EOL
-                                                       {
-                                                               $$ = make_if_stmt(parser, OP_EQUALS, $2, $4, $6, $7);
-
-                                                               //pakfire_parser_unref($6);
-                                                               //pakfire_parser_unref($7);
-                                                       }
-                                                       ;
-
-else_stmt                                      : else subgrammar
-                                                       {
-                                                               $$ = $2;
+                                                               $$ = pakfire_parser_ref($3);
                                                        }
                                                        | %empty
                                                        {
@@ -254,12 +269,12 @@ int pakfire_parser_parse_data(PakfireParser parent, const char* data, size_t len
 #endif
 
        // Create a new sub-parser
-       PakfireParser parser = pakfire_parser_create(pakfire, parent, NULL);
+       PakfireParser parser = NULL;
 
        num_lines = 1;
 
        YY_BUFFER_STATE buffer = yy_scan_bytes(data, len);
-       int r = yyparse(parser);
+       int r = yyparse(pakfire, &parser);
        yy_delete_buffer(buffer);
 
        // If everything was parsed successfully, we merge the sub-parser into
@@ -293,29 +308,23 @@ int pakfire_parser_parse_data(PakfireParser parent, const char* data, size_t len
        return r;
 }
 
-void yyerror(PakfireParser parser, const char* s) {
-       Pakfire pakfire = pakfire_parser_get_pakfire(parser);
-
+void yyerror(Pakfire pakfire, PakfireParser* result, const char* s) {
        ERROR(pakfire, "Error (line %d): %s\n", num_lines, s);
-
-       pakfire_unref(pakfire);
 }
 
-static PakfireParser make_if_stmt(PakfireParser parser, const enum operator op,
+static PakfireParser make_if_stmt(Pakfire pakfire, PakfireParser* parser, const enum operator op,
                const char* val1, const char* val2, PakfireParser if_block, PakfireParser else_block) {
-       Pakfire pakfire = pakfire_parser_get_pakfire(parser);
-
        switch (op) {
                case OP_EQUALS:
                        DEBUG(pakfire, "Evaluating if statement: %s == %s?\n", val1, val2);
                        break;
        }
 
-       DEBUG(pakfire, "  parser = %p, if = %p, else = %p\n", parser, if_block, else_block);
+       DEBUG(pakfire, "  parser = %p, if = %p, else = %p\n", *parser, if_block, else_block);
 
        // Expand values
-       char* v1 = pakfire_parser_expand(parser, val1);
-       char* v2 = pakfire_parser_expand(parser, val2);
+       char* v1 = pakfire_parser_expand(*parser, val1);
+       char* v2 = pakfire_parser_expand(*parser, val2);
 
        PakfireParser result = NULL;
 
@@ -331,7 +340,6 @@ static PakfireParser make_if_stmt(PakfireParser parser, const enum operator op,
                        break;
        }
 
-       pakfire_unref(pakfire);
        free(v1);
        free(v2);