discover/grub2: Implement statement blocks
[petitboot] / discover / grub2 / parser.y
index 2af213218070a0be6cac707b5e51e8fd9a569785..d57c732a8382152c690fbabad381b5b266c0f509 100644 (file)
@@ -4,15 +4,20 @@
 %parse-param { struct grub2_parser *parser }
 
 %{
+#include "grub2.h"
+#include "parser.h"
 #include "lexer.h"
+
+#define YYLEX_PARAM parser->scanner
+
+static void yyerror(struct grub2_parser *, char const *s);
 %}
 
 %union {
-       struct {
-               char    *strval;
-               int     expand;
-               int     split;
-       };
+       struct grub2_word       *word;
+       struct grub2_argv       *argv;
+       struct grub2_statement  *statement;
+       struct grub2_statements *statements;
 }
 
 /* reserved words */
 %token TOKEN_UTIL              "until"
 %token TOKEN_WHILE             "while"
 
+%type <statement>      statement
+%type <statements>     statements
+%type <argv>           words
+%type <word>           word
+
 /* syntax */
 %token TOKEN_EOL
 %token TOKEN_DELIM
-%token TOKEN_WORD
+%token <word> TOKEN_WORD
 
 %start script
+%debug
 
 %%
 
-script: /* empty */
+script: statements {
+               parser->statements = $1;
+       }
+
+statements: statement {
+               $$ = create_statements(parser);
+               statement_append($$, $1);
+       }
+       | statements statement {
+               statement_append($1, $2);
+       }
+
+statement: TOKEN_EOL {
+               $$ = NULL;
+       }
+       | words TOKEN_EOL {
+                  $$ = create_statement_simple(parser, $1);
+       }
+       | '{' statements '}' {
+               $$ = create_statement_block(parser, $2);
+       }
+       | "if" TOKEN_DELIM statement
+               "then" TOKEN_EOL
+               statements
+               "fi" TOKEN_EOL {
+               $$ = create_statement_if(parser, $3, $6, NULL);
+       }
+       | "menuentry" TOKEN_DELIM words TOKEN_DELIM
+               '{' statements '}'
+               TOKEN_EOL {
+               $$ = create_statement_menuentry(parser, $3, $6);
+       }
+
+words: word {
+               $$ = create_argv(parser);
+               argv_append($$, $1);
+       }
+       | words TOKEN_DELIM word {
+               argv_append($1, $3);
+               $$ = $1;
+       }
+
+word:  TOKEN_WORD
+       | word TOKEN_WORD {
+               word_append($1, $2);
+               $$ = $1;
+       }
 
 %%
+void yyerror(struct grub2_parser *parser, char const *s)
+{
+       fprintf(stderr, "%d: error: %s '%s'\n",
+                       yyget_lineno(parser->scanner),
+                       s, yyget_text(parser->scanner));
+}