OP_EQUALS = 0,
};
+static PakfireParser make_if_stmt(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);
%}
%token T_EOL
%token T_END
+%token T_IF
+%token T_ELSE
+%token T_EQUALS
%token T_ASSIGN
%token T_APPEND
%token <string> T_SUBPARSER
%type <parser> grammar
+%type <parser> subgrammar
%type <parser> subparser
+%type <parser> if_stmt
+%type <parser> else_stmt
%type <string> key
%type <string> value
| grammar declaration
| grammar subparser
{
- $$ = pakfire_parser_merge($1, $2);
- pakfire_parser_unref($2);
+ if ($2) {
+ $$ = pakfire_parser_merge($1, $2);
+ //pakfire_parser_unref($2);
+ }
+ }
+ | grammar if_stmt
+ {
+ if ($2) {
+ $$ = pakfire_parser_merge($1, $2);
+ //pakfire_parser_unref($2);
+ }
}
| grammar empty
+ {
+ $$ = $1;
+ }
+ ;
+
+subgrammar : T_INDENT grammar T_OUTDENT
+ {
+ $$ = $2;
+ }
;
declaration : key T_ASSIGN value T_EOL
parser = pakfire_parser_get_parent(parser);
// Merge block into the parent parser
- pakfire_parser_merge(parser, $3);
+ $$ = pakfire_parser_merge(parser, $3);
// Free block parser
pakfire_parser_unref($3);
}
;
-subparser_close : T_END;
+subparser_close : T_END T_EOL;
+
+if : T_IF
+ {
+ // Open a new block
+ parser = make_child(parser, NULL);
+ };
+
+else : T_ELSE T_EOL
+ {
+ // 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;
+ }
+ | %empty
+ {
+ $$ = NULL;
+ }
+ ;
%%
pakfire_unref(pakfire);
}
+static PakfireParser make_if_stmt(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);
+
+ // Expand values
+ char* v1 = pakfire_parser_expand(parser, val1);
+ char* v2 = pakfire_parser_expand(parser, val2);
+
+ PakfireParser result = NULL;
+
+ switch (op) {
+ case OP_EQUALS:
+ DEBUG(pakfire, " '%s' == '%s'?\n", v1, v2);
+
+ if (strcmp(v1, v2) == 0)
+ result = if_block;
+ else
+ result = else_block;
+
+ break;
+ }
+
+ pakfire_unref(pakfire);
+ free(v1);
+ free(v2);
+
+ return pakfire_parser_ref(result);
+}
+
static PakfireParser make_child(PakfireParser parent, const char* namespace) {
PakfireParser parser = pakfire_parser_create_child(parent, namespace);
pakfire_parser_unref(parent);
unsigned int current_indent = 0;
unsigned int readline_indent = 0;
+static char* unquote(const char* input) {
+ size_t length = strlen(input);
+
+ // Check whether the first character is "
+ if (*input != '"')
+ goto COPY;
+
+ // Check whether the last characters is "
+ if (input[length] != '"')
+ goto COPY;
+
+ char* output = malloc(length - 1);
+ if (!output)
+ return NULL;
+
+ // Copy everything except the first and last character
+ snprintf(output, length - 2, "%s", input + 1);
+
+ return output;
+COPY:
+ return strdup(input);
+}
+
%}
%x INDENT
digit [0-9]
underscore _
whitespace [ \t]+
+quoted_string \"([^\"])*\"
key ({letter}|{underscore})(({letter}|{digit}|{underscore})*({letter}|{digit}))?
return T_SUBPARSER;
}
+{quoted_string} {
+ // Remove quotes
+ yylval.string = unquote(yytext);
+
+ return T_STRING;
+ }
+
+"if" { return T_IF; }
+"else" { return T_ELSE; }
+
+"==" { return T_EQUALS; }
+
"=" {
// Read everything after this
yy_push_state(READLINE);