1 /* parser.y - The scripting parser. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/script_sh.h>
24 #define YYFREE grub_free
25 #define YYMALLOC grub_malloc
26 #define YYLTYPE_IS_TRIVIAL 0
27 #define YYENABLE_NLS 0
32 struct grub_script_cmd
*cmd
;
33 struct grub_script_arglist
*arglist
;
34 struct grub_script_arg
*arg
;
38 %token GRUB_PARSER_TOKEN_IF
"if"
39 %token GRUB_PARSER_TOKEN_WHILE
"while"
40 %token GRUB_PARSER_TOKEN_FUNCTION
"function"
41 %token GRUB_PARSER_TOKEN_MENUENTRY
"menuentry"
42 %token GRUB_PARSER_TOKEN_ELSE
"else"
43 %token GRUB_PARSER_TOKEN_THEN
"then"
44 %token GRUB_PARSER_TOKEN_FI
"fi"
45 %token GRUB_PARSER_TOKEN_NAME
46 %token GRUB_PARSER_TOKEN_VAR
47 %type
<cmd
> script_init script grubcmd command commands commandblock menuentry if
48 %type
<arglist
> arguments
;
50 %type
<string> "if" "while" "function" "else" "then" "fi"
51 %type
<string> text GRUB_PARSER_TOKEN_NAME GRUB_PARSER_TOKEN_VAR
54 %lex
-param
{ struct grub_parser_param
*state
};
55 %parse
-param
{ struct grub_parser_param
*state
};
58 /* It should be possible to do this in a clean way... */
59 script_init: { state
->err
= 0; } script
65 script: commands
{ $$
= $1; }
66 | function
'\n' { $$
= 0; }
67 | menuentry
'\n' { $$
= $1; }
79 /* Some tokens are both used as token or as plain text. XXX: Add all
80 tokens without causing conflicts. */
81 text: GRUB_PARSER_TOKEN_NAME
95 /* An argument can consist of some static text mixed with variables,
96 for example: `foo${bar}baz'. */
97 argument: GRUB_PARSER_TOKEN_VAR
99 $$
= grub_script_arg_add
(state
, 0, GRUB_SCRIPT_ARG_TYPE_VAR
, $1);
103 $$
= grub_script_arg_add
(state
, 0, GRUB_SCRIPT_ARG_TYPE_STR
, $1);
105 /* XXX: Currently disabled to simplify the parser. This should be
106 parsed by yet another parser for readability. */
107 /* | argument GRUB_PARSER_TOKEN_VAR */
109 /* $$ = grub_script_arg_add ($1, GRUB_SCRIPT_ARG_TYPE_VAR, $2); */
111 /* | argument text */
113 /* $$ = grub_script_arg_add ($1, GRUB_SCRIPT_ARG_TYPE_STR, $2); */
119 $$
= grub_script_add_arglist
(state
, 0, $1);
123 $$
= grub_script_add_arglist
(state
, $1, $2);
127 grubcmd: GRUB_PARSER_TOKEN_NAME arguments
129 $$
= grub_script_create_cmdline
(state
, $1, $2);
131 | GRUB_PARSER_TOKEN_NAME
133 $$
= grub_script_create_cmdline
(state
, $1, 0);
137 /* A single command. */
138 command: grubcmd delimiter
{ $$
= $1; }
139 | if delimiter
{ $$
= $1; }
140 | commandblock delimiter
{ $$
= $1; }
144 yyerror (state
, "Incorrect command");
150 /* A block of commands. */
153 $$
= grub_script_add_cmd
(state
, 0, $1);
157 struct grub_script_cmdblock
*cmd
;
158 cmd
= (struct grub_script_cmdblock
*) $2;
159 $$
= grub_script_add_cmd
(state
, cmd
, $1);
163 /* A function. Carefully save the memory that is allocated. Don't
164 change any stuff because it might seem like a fun thing to do!
165 Special care was take to make sure the mid-rule actions are
166 executed on the right moment. So the `commands' rule should be
167 recognized after executing the `grub_script_mem_record; and before
168 `grub_script_mem_record_stop'. */
169 function: "function" GRUB_PARSER_TOKEN_NAME
171 grub_script_lexer_ref
(state
->lexerstate
);
174 /* The first part of the function was recognized.
175 Now start recording the memory usage to store
177 state
->func_mem
= grub_script_mem_record
(state
);
178 } newlines commands
'}'
180 struct grub_script
*script
;
182 /* All the memory usage for parsing this function
184 state
->func_mem
= grub_script_mem_record_stop
(state
,
186 script
= grub_script_create
($8, state
->func_mem
);
188 grub_script_function_create
($2, script
);
189 grub_script_lexer_deref
(state
->lexerstate
);
193 /* Carefully designed, together with `menuentry' so everything happens
194 just in the expected order. */
197 grub_script_lexer_ref
(state
->lexerstate
);
199 newlines commands
'}'
201 grub_script_lexer_deref
(state
->lexerstate
);
206 /* A menu entry. Carefully save the memory that is allocated. */
207 menuentry: "menuentry" arguments
209 grub_script_lexer_ref
(state
->lexerstate
);
212 grub_script_lexer_record_start
(state
->lexerstate
);
213 } newlines commands
'}'
216 menu_entry
= grub_script_lexer_record_stop
(state
->lexerstate
);
217 grub_script_lexer_deref
(state
->lexerstate
);
218 $$
= grub_script_create_cmdmenu
(state
, $2, menu_entry
, 0);
222 /* The first part of the if statement. It's used to switch the lexer
223 to a state in which it demands more tokens. */
224 if_statement: "if" { grub_script_lexer_ref
(state
->lexerstate
); }
227 /* The if statement. */
228 if: if_statement commands
"then" newlines commands
"fi"
230 $$
= grub_script_create_cmdif
(state
, $2, $5, 0);
231 grub_script_lexer_deref
(state
->lexerstate
);
233 | if_statement commands
"then" newlines commands
"else" newlines commands
"fi"
235 $$
= grub_script_create_cmdif
(state
, $2, $5, $8);
236 grub_script_lexer_deref
(state
->lexerstate
);