From: Michael Tremer Date: Thu, 25 Feb 2021 11:17:24 +0000 (+0000) Subject: parser: Introduce new data type for declarations X-Git-Tag: 0.9.28~1285^2~702 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=79fd37b57f2af83c08061c639fb8666260b2e4e7;p=pakfire.git parser: Introduce new data type for declarations Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/include/pakfire/parser.h b/src/libpakfire/include/pakfire/parser.h index 98e4ba81c..299d63bf5 100644 --- a/src/libpakfire/include/pakfire/parser.h +++ b/src/libpakfire/include/pakfire/parser.h @@ -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 */ diff --git a/src/libpakfire/parser.c b/src/libpakfire/parser.c index 06a78e49e..3f530810d 100644 --- a/src/libpakfire/parser.c +++ b/src/libpakfire/parser.c @@ -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); diff --git a/src/libpakfire/parser/grammar.y b/src/libpakfire/parser/grammar.y index 7885ed07c..e8b3e80c2 100644 --- a/src/libpakfire/parser/grammar.y +++ b/src/libpakfire/parser/grammar.y @@ -18,12 +18,14 @@ # # #############################################################################*/ -%parse-param {PakfireParser parser} +%parse-param {Pakfire pakfire} {PakfireParser* result} // Generate verbose error messages %define parse.error verbose %{ + +#include #include #include #include @@ -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 key %type value +%type declaration %type lines %type 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($$); } +%destructor { pakfire_parser_free_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);