3 %lex-param { yyscan_t scanner }
4 %parse-param { struct grub2_parser *parser }
5 %parse-param { void *scanner }
9 #include <talloc/talloc.h>
14 void yyerror(struct grub2_parser *parser, void *scanner, const char *fmt, ...);
18 struct grub2_word *word;
19 struct grub2_argv *argv;
20 struct grub2_statement *statement;
21 struct grub2_statements *statements;
24 %printer { fprintf(yyoutput, "%s%s:'%s'",
25 $$->type == GRUB2_WORD_VAR ? "var" : "text",
26 $$->type == GRUB2_WORD_VAR && !$$->split ? "[nosplit]" : "",
30 %token TOKEN_LDSQBRACKET "[["
31 %token TOKEN_RDSQBRACKET "]]"
32 %token TOKEN_CASE "case"
34 %token TOKEN_DONE "done"
35 %token TOKEN_ELIF "elif"
36 %token TOKEN_ELSE "else"
37 %token TOKEN_ESAC "esac"
39 %token TOKEN_FOR "for"
40 %token TOKEN_FUNCTION "function"
43 %token TOKEN_MENUENTRY "menuentry"
44 %token TOKEN_SELECT "select"
45 %token TOKEN_SUBMENU "submenu"
46 %token TOKEN_THEN "then"
47 %token TOKEN_TIME "time"
48 %token TOKEN_UTIL "until"
49 %token TOKEN_WHILE "while"
51 %type <statement> statement
52 %type <statements> statements
53 %type <statement> conditional
54 %type <statement> elif
55 %type <statements> elifs
62 %token <word> TOKEN_WORD
69 #include "grub2-lexer.h"
75 parser->script->statements = $1;
78 statements: statement {
79 $$ = create_statements(parser);
80 statement_append($$, $1);
82 | statements eol statement {
83 statement_append($1, $3);
87 conditional: statement eol "then" statements {
88 $$ = create_statement_conditional(parser, $1, $4);
91 elif: "elif" conditional {
96 $$ = create_statements(parser);
99 statement_append($1, $2);
107 $$ = create_statement_simple(parser, $1);
109 | '{' statements '}' {
110 $$ = create_statement_block(parser, $2);
112 | "if" conditional elifs "fi" {
113 $$ = create_statement_if(parser, $2, $3, NULL);
120 $$ = create_statement_if(parser, $2, $3, $5);
122 | "function" word delim '{' statements '}' {
123 $$ = create_statement_function(parser, $2, $5);
125 | "menuentry" words delim
127 $$ = create_statement_menuentry(parser, $2, $5);
129 | "submenu" words delim
131 /* we just flatten everything */
132 $$ = create_statement_block(parser, $5);
134 | "for" word delim "in" delim words eol
138 $$ = create_statement_for(parser, $2, $6, $9);
142 $$ = create_argv(parser);
156 delim0: /* empty */ |
164 void yyerror(struct grub2_parser *parser, void *scanner, const char *fmt, ...)
170 str = talloc_vasprintf(parser, fmt, ap);
173 pb_log("parse error: %d('%s'): %s\n", yyget_lineno(scanner),
174 yyget_text(scanner), str);
177 struct grub2_statements *create_statements(struct grub2_parser *parser)
179 struct grub2_statements *stmts = talloc(parser,
180 struct grub2_statements);
181 list_init(&stmts->list);
185 struct grub2_statement *create_statement_simple(struct grub2_parser *parser,
186 struct grub2_argv *argv)
188 struct grub2_statement_simple *stmt =
189 talloc(parser, struct grub2_statement_simple);
190 stmt->st.type = STMT_TYPE_SIMPLE;
191 stmt->st.exec = statement_simple_execute;
196 struct grub2_statement *create_statement_menuentry(struct grub2_parser *parser,
197 struct grub2_argv *argv, struct grub2_statements *stmts)
199 struct grub2_statement_menuentry *stmt =
200 talloc(parser, struct grub2_statement_menuentry);
201 stmt->st.type = STMT_TYPE_MENUENTRY;
202 stmt->st.exec = statement_menuentry_execute;
204 stmt->statements = stmts;
208 struct grub2_statement *create_statement_conditional(
209 struct grub2_parser *parser,
210 struct grub2_statement *condition,
211 struct grub2_statements *statements)
213 struct grub2_statement_conditional *stmt =
214 talloc(parser, struct grub2_statement_conditional);
215 stmt->st.type = STMT_TYPE_CONDITIONAL;
216 stmt->condition = condition;
217 stmt->statements = statements;
221 struct grub2_statement *create_statement_if(struct grub2_parser *parser,
222 struct grub2_statement *conditional,
223 struct grub2_statements *elifs,
224 struct grub2_statements *else_case)
226 struct grub2_statement_if *stmt =
227 talloc(parser, struct grub2_statement_if);
229 list_add(&elifs->list, &conditional->list);
231 stmt->st.type = STMT_TYPE_IF;
232 stmt->st.exec = statement_if_execute;
233 stmt->conditionals = elifs;
234 stmt->else_case = else_case;
238 struct grub2_statement *create_statement_block(struct grub2_parser *parser,
239 struct grub2_statements *stmts)
241 struct grub2_statement_block *stmt =
242 talloc(parser, struct grub2_statement_block);
243 stmt->st.type = STMT_TYPE_BLOCK;
244 stmt->st.exec = statement_block_execute;
245 stmt->statements = stmts;
249 struct grub2_statement *create_statement_function(struct grub2_parser *parser,
250 struct grub2_word *name, struct grub2_statements *body)
252 struct grub2_statement_function *stmt =
253 talloc(parser, struct grub2_statement_function);
254 stmt->st.exec = statement_function_execute;
260 struct grub2_statement *create_statement_for(struct grub2_parser *parser,
261 struct grub2_word *var, struct grub2_argv *list,
262 struct grub2_statements *body)
264 struct grub2_statement_for *stmt =
265 talloc(parser, struct grub2_statement_for);
266 stmt->st.exec = statement_for_execute;
273 void statement_append(struct grub2_statements *stmts,
274 struct grub2_statement *stmt)
277 list_add_tail(&stmts->list, &stmt->list);
280 struct grub2_word *create_word_text(struct grub2_parser *parser,
283 struct grub2_word *word = talloc(parser, struct grub2_word);
284 word->type = GRUB2_WORD_TEXT;
286 word->text = talloc_strdup(word, text);
292 struct grub2_word *create_word_var(struct grub2_parser *parser,
293 const char *name, bool split)
295 struct grub2_word *word = talloc(parser, struct grub2_word);
296 word->type = GRUB2_WORD_VAR;
297 word->name = talloc_strdup(word, name);
304 struct grub2_argv *create_argv(struct grub2_parser *parser)
306 struct grub2_argv *argv = talloc(parser, struct grub2_argv);
307 list_init(&argv->words);
311 void argv_append(struct grub2_argv *argv, struct grub2_word *word)
313 list_add_tail(&argv->words, &word->argv_list);
316 void word_append(struct grub2_word *w1, struct grub2_word *w2)
322 struct grub2_parser *grub2_parser_create(struct discover_context *ctx)
324 struct grub2_parser *parser;
326 parser = talloc(ctx, struct grub2_parser);
327 yylex_init_extra(parser, &parser->scanner);
328 parser->script = create_script(parser, ctx);
329 parser->inter_word = false;
334 void grub2_parser_parse(struct grub2_parser *parser, const char *filename,
337 YY_BUFFER_STATE bufstate;
343 parser->script->filename = filename;
345 bufstate = yy_scan_bytes(buf, len - 1, parser->scanner);
346 yyset_lineno(1, parser->scanner);
348 rc = yyparse(parser, parser->scanner);
350 yy_delete_buffer(bufstate, parser->scanner);
353 script_execute(parser->script);