From: Michael Tremer Date: Fri, 17 May 2019 17:30:09 +0000 (+0100) Subject: libpakfire: parser: Add compatibility for older pakfire files X-Git-Tag: 0.9.28~1285^2~1033 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a714578c3ecbe0de62b67bd80b7e3866467cb2b8;p=pakfire.git libpakfire: parser: Add compatibility for older pakfire files This patch moves the keyword handling out of the parser and puts it into the lexer where the "define" keyword is added where it is needed. That way, we have a clear definition of a clean syntax without any shift/reduce or reduce/reduce errors, but remain compatible to the current pakfire files. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/parser/grammar.y b/src/libpakfire/parser/grammar.y index 00eedc25c..0b00e4140 100644 --- a/src/libpakfire/parser/grammar.y +++ b/src/libpakfire/parser/grammar.y @@ -72,7 +72,6 @@ char* current_block = NULL; %token T_WORD %type define; -%type keyword; %type line; %type text; %type variable; @@ -108,14 +107,9 @@ value : words $$ = NULL; }; - // XXX T_DEFINE is sort of missing here, but adding it - // generates a highly ambiguous grammar -keyword : T_IF; - // IF can show up in values and therefore this // hack is needed to parse those properly -word : T_WORD - | keyword; +word : T_WORD; words : word | words word @@ -196,10 +190,6 @@ assignment : variable T_ASSIGN value T_EOL define : T_DEFINE variable T_EOL { $$ = $2; - } - | variable T_EOL - { - $$ = $1; }; %% diff --git a/src/libpakfire/parser/scanner.l b/src/libpakfire/parser/scanner.l index c7756a5b0..442c751bd 100644 --- a/src/libpakfire/parser/scanner.l +++ b/src/libpakfire/parser/scanner.l @@ -18,7 +18,7 @@ # # #############################################################################*/ -%option nounput noinput noyywrap yylineno +%option noinput noyywrap yylineno %{ #define YY_DECL int yylex() @@ -39,20 +39,59 @@ whitespace ([ \t])+ quoted_string \"([^\"])*\" word ({quoted_string}|({digit}|{letter}|{special})+) +/* + Compatibility for the old python parser. + + We automatically prepend "define" in front of some keywords, because + generally the language requires it. +*/ +keywords (description|{whitespace}(build(_cmds)?|install(_cmds)?|prepare_cmds|requires)) + +%s DEFINE + %% #.*$ { /* ignore comments */ } {whitespace} {} \n { num_lines++; return T_EOL; } -"==" { return T_EQUALS; } -"=" { return T_ASSIGN; } -"+=" { return T_APPEND; } +^{keywords}$ { + // Determine the length of the string + size_t length = strlen("define ") + yyleng; + + // Make a copy because unput touches yytext + char* buffer = pakfire_malloc(length + 1); + 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]); + } + + pakfire_free(buffer); + } -"if" { return T_IF; } -"define" { return T_DEFINE; } -"def" { return T_DEFINE; } -"end" { return T_END; } +"==" { return T_EQUALS; } +"=" { return T_ASSIGN; } +"+=" { return T_APPEND; } + +"if" { return T_IF; } +"define" { + BEGIN(DEFINE); + return T_DEFINE; + } +"def" { + BEGIN(DEFINE); + return T_DEFINE; + } +"end" { + return T_END; + } + +"end" { + BEGIN(0); + return T_END; + } {quoted_string} { // Remove quotes