# #
#############################################################################*/
-%glr-parser
-
%parse-param {PakfireParser parser}
// Generate verbose error messages
#define YYERROR_VERBOSE 1
-#define YYDEBUG 0
+#define YYDEBUG 1
#if ENABLE_DEBUG && YYDEBUG
int yydebug = 1;
#endif
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 <string> T_KEY
+%token <string> T_STRING
-%}
+%token T_EOL
-%token T_APPEND
-%token T_ASSIGN
-%token T_DEFINE
-%token T_END
-%token T_EQUALS
-%token T_IF
-%token T_ELSE
-%token T_EOL
-%token <string> T_WORD
-
-%type <string> define;
-%type <string> line;
-%type <string> text;
-%type <string> variable;
-%type <string> value;
-%type <string> word;
-%type <string> words;
-
-%type <parser> grammar;
-
-%type <parser> if_stmt;
-%type <parser> else_stmt;
+%token T_ASSIGN
+
+%type <string> key
+%type <string> value
%union {
PakfireParser parser;
char* string;
}
-%%
-
-grammar : grammar statements
- | statements
- {
- $$ = parser;
- }
- ;
+%start grammar
-statements : statement
- | if_stmt
- | block
- | empty;
+%%
-empty : T_EOL
+grammar : declarations
;
-variable : T_WORD;
+declarations : declarations declaration
+ | declaration;
-value : words
- | %empty
+declaration : key T_ASSIGN value T_EOL
{
- $$ = NULL;
- };
-
-word : T_WORD;
-
-words : word
- | words word
- {
- int r = asprintf(&$$, "%s %s", $1, $2);
- if (r < 0) {
- Pakfire pakfire = pakfire_parser_get_pakfire(parser);
- ERROR(pakfire, "Could not allocate memory");
- pakfire_unref(pakfire);
- ABORT;
- }
- };
-
-line : words T_EOL
- {
- // Only forward words
- $$ = $1;
- }
- | T_EOL {
- $$ = "";
- };
-
-text : text line
- {
- int r = asprintf(&$$, "%s\n%s", $1, $2);
- if (r < 0) {
- Pakfire pakfire = pakfire_parser_get_pakfire(parser);
- ERROR(pakfire, "Could not allocate memory");
- pakfire_unref(pakfire);
+ int r = pakfire_parser_set(parser, $1, $3);
+ if (r)
ABORT;
- }
}
- | line
;
-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);
- };
-
-end : T_END T_EOL;
-
-if_stmt : if variable T_EQUALS variable T_EOL grammar else_stmt end
+key : T_KEY
{
- PakfireParser result = make_if_stmt(parser, OP_EQUALS, $2, $4, $6, $7);
+ printf("KEY = %s\n", $1);
- // Close the whole if/else block
- parser = pakfire_parser_get_parent(parser);
-
- if (result)
- pakfire_parser_merge(parser, result);
-
- pakfire_parser_unref($6);
- pakfire_parser_unref($7);
+ $$ = $1;
}
;
-else_stmt : else grammar
- {
- $$ = $2;
- }
- | %empty
+value : T_STRING
{
- $$ = NULL;
+ $$ = $1;
}
;
-block : block_opening grammar end
- {
- // Move back to the parent parser
- parser = pakfire_parser_get_parent(parser);
-
- // Merge block into the parent parser
- pakfire_parser_merge(parser, $2);
-
- // Free block parser
- pakfire_parser_unref($2);
- };
-
-block_opening : variable T_EOL
- {
- // Create a new sub-parser which opens a new namespace
- parser = make_child(parser, $1);
- };
-
-statement : variable T_ASSIGN value T_EOL
- {
- int r = pakfire_parser_set(parser, $1, $3);
- if (r < 0)
- ABORT;
- }
- | variable T_APPEND value T_EOL
- {
- int r = pakfire_parser_append(parser, $1, $3);
- if (r < 0)
- ABORT;
- }
- | define text end
- {
- int r = pakfire_parser_set(parser, $1, $2);
- if (r < 0)
- ABORT;
- };
-
-define : T_DEFINE variable T_EOL
- {
- $$ = $2;
- };
-
%%
int pakfire_parser_parse_data(PakfireParser parent, const char* data, size_t len) {
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 result;
-}
-
-static PakfireParser make_child(PakfireParser parent, const char* namespace) {
- PakfireParser parser = pakfire_parser_create_child(parent, namespace);
- pakfire_parser_unref(parent);
-
- return parser;
-}
#############################################################################*/
%option noinput noyywrap yylineno
+%option nodefault
+%option stack noyy_top_state
+%option warn
+
+/* Do not let unput() trash yytext */
+%array
+
+/* %option verbose */
+%option debug
%{
#define YY_DECL int yylex()
int num_lines;
+#include <assert.h>
+
#include <ctype.h>
#include <stdlib.h>
+
#include <pakfire/parser.h>
-#include <pakfire/util.h>
+
#include "grammar.h"
-static char* find_name(const char* s, const char* prefix) {
- // Find the name of the package
- const char* name = NULL;
- for (unsigned int i = strlen(s); i > 0; i--) {
- if (isspace(s[i]))
- break;
+%}
- name = s + i;
- }
+%x READLINE
- // New length
- size_t length = strlen(prefix) + strlen(name);
+letter [A-Za-z]
+digit [0-9]
+underscore _
+whitespace [ \t]+
- // Allocate a new buffer and write the string into it
- char* buffer = malloc(length + 1);
- if (!buffer)
- abort();
+key ({letter}|{underscore})(({letter}|{digit}|{underscore})*({letter}|{digit}))?
- snprintf(buffer, length + 1, "%s%s", prefix, name);
+%%
- return buffer;
-}
-%}
+<*>\n {
+ // Handles line numbers without consuming the newline character
+ num_lines++; REJECT;
+ }
-digit [0-9]
-letter [A-Za-z]
-underscore _
-special [/\"'!@$%&*(){}+=:<>,;_\?\.\[\]\-\\\|]+
-whitespace ([ \t])+
+#.*$ {
+ /* ignore comments */
+ }
-quoted_string \"([^\"])*\"
-word ({quoted_string}|({digit}|{letter}|{special})+)
+\n {
+ return T_EOL;
+ }
-/*
- Compatibility for the old python parser.
+{whitespace} { /* consume any whitespace */ }
- We automatically prepend "define" in front of some keywords, because
- generally the language requires it.
-*/
-keywords (description|{whitespace}(description|build(_cmds)?|files|filter_(provides|requires)|install(_cmds)?|prepare_cmds|provides|(pre)?requires|_posttrans))
-package {whitespace}package.*$
-script {whitespace}script.*$
+{key} {
+ // Copy the value
+ yylval.string = strdup(yytext);
-/* Template definitions are indented once */
-template1 \ttemplate.*
+ return T_KEY;
+ }
-/* In a package block, the template line is indented more than once */
-template2 {whitespace}template.*
+"=" {
+ // Read everything after this
+ yy_push_state(READLINE);
-%s DEFINE
+ return T_ASSIGN;
+ }
-%%
+(.|\n) {
+ // Unexpected character
+ fprintf(stderr, "Unexpected character: %s\n", yytext);
+ abort();
+ }
+
+<READLINE>{whitespace} {
+ // consume any leading whitespace
+ }
+<READLINE>.*$ {
+ // Return to caller
+ yy_pop_state();
+
+ // Copy the entire string
+ yylval.string = strdup(yytext);
-#.*$ { /* ignore comments */ }
-{whitespace} {}
-\n { num_lines++; return T_EOL; }
-
-<INITIAL>^{package} {
- char* buffer = find_name(yytext, "package:");
-
- // Put the whole string back onto the stack (backwards)
- for (int i = strlen(buffer) - 1; i >= 0; i--) {
- unput(buffer[i]);
- }
-
- free(buffer);
- }
-
-<INITIAL>^{template1}$ {
- char* buffer = find_name(yytext, "template:");
-
- // Put the whole string back onto the stack (backwards)
- for (int i = strlen(buffer) - 1; i >= 0; i--) {
- unput(buffer[i]);
- }
-
- free(buffer);
- }
-
-<INITIAL>^{template2}$ {
- char* buffer = find_name(yytext, "template = ");
-
- // Put the whole string back onto the stack (backwards)
- for (int i = strlen(buffer) - 1; i >= 0; i--) {
- unput(buffer[i]);
- }
-
- free(buffer);
- }
-
-<INITIAL>^{script} {
- char* buffer = find_name(yytext, "define script:");
-
- // Put the whole string back onto the stack (backwards)
- for (int i = strlen(buffer) - 1; i >= 0; i--) {
- unput(buffer[i]);
- }
-
- free(buffer);
- }
-
-<INITIAL>^{keywords}$ {
- // Determine the length of the string
- size_t length = strlen("define ") + yyleng;
-
- // Make a copy because unput touches yytext
- char* buffer = malloc(length + 1);
- if (!buffer)
- abort();
-
- snprintf(buffer, length + 1, "define %s", yytext);
-
- // Put the whole string back onto the stack (backwards)
- for (int i = length - 1; i >= 0; i--) {
- unput(buffer[i]);
- }
-
- free(buffer);
- }
-
-<INITIAL>"==" { return T_EQUALS; }
-<INITIAL>"=" { return T_ASSIGN; }
-<INITIAL>"+=" { return T_APPEND; }
-
-<INITIAL>"if" { return T_IF; }
-<INITIAL>"else" { return T_ELSE; }
-
-<INITIAL>"define" {
- BEGIN(DEFINE);
- return T_DEFINE;
- }
-<INITIAL>"def" {
- BEGIN(DEFINE);
- return T_DEFINE;
- }
-<INITIAL>"end" {
- return T_END;
- }
-
-<DEFINE>"end" {
- BEGIN(0);
- return T_END;
- }
-
-{quoted_string} {
- // Remove quotes
- size_t len = strlen(yytext);
- yytext[len-1] = '\0';
-
- yylval.string = strdup(yytext + 1);
- return T_WORD;
- }
-
-{word} {
- yylval.string = strdup(yytext);
- return T_WORD;
- }
+ return T_STRING;
+ }
%%