summaryrefslogtreecommitdiffstats
path: root/discover/grub2/grub2-parser.y
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2014-12-01 11:47:16 +0800
committerJeremy Kerr <jk@ozlabs.org>2014-12-01 12:09:53 +0800
commit00a881a1adb6f656049939adecb9bf9edd29a658 (patch)
tree20fb132fd91c7ce718244ab9884efe0859e7eef0 /discover/grub2/grub2-parser.y
parent46fbb1e1e33b130284ec211f9c647268ff709ba7 (diff)
downloadtalos-petitboot-00a881a1adb6f656049939adecb9bf9edd29a658.tar.gz
talos-petitboot-00a881a1adb6f656049939adecb9bf9edd29a658.zip
discover/grub2: improve handling of word & delimiter tokens
Currently, the delimiter token handling is a little fragile: we try to ignore non-inter-word delimiters in the lexer with a selective set of regexes on the possible delimiter characters. This means we don't need to handle potential delimiters in every grammar rule, but there are other situations (not regex-able) where we may see delimters, and this will cause a parse error. Instead of relying on the regex behaviour, we have an 'inter_word' flag, which is set when we see the first word token, and cleared when we see an end-of-line token. We only emit TOKEN_DELIM when this flag is set. This means that we only get the delim tokens when they're required - when we're looking for word separators (becuase WORD DELIM WORD is distinct from WORD WORD - eg "linux /vmlinux" and "x$var"). We add a few new tests for the "menuentry" and "if" syntax, with different delimiter configurations. Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'discover/grub2/grub2-parser.y')
-rw-r--r--discover/grub2/grub2-parser.y76
1 files changed, 42 insertions, 34 deletions
diff --git a/discover/grub2/grub2-parser.y b/discover/grub2/grub2-parser.y
index 7f9961b..598f0fe 100644
--- a/discover/grub2/grub2-parser.y
+++ b/discover/grub2/grub2-parser.y
@@ -21,6 +21,11 @@ void yyerror(struct grub2_parser *parser, void *scanner, const char *fmt, ...);
struct grub2_statements *statements;
}
+%printer { fprintf(yyoutput, "%s%s:'%s'",
+ $$->type == GRUB2_WORD_VAR ? "var" : "text",
+ $$->type == GRUB2_WORD_VAR && !$$->split ? "[nosplit]" : "",
+ $$->name); } <word>
+
/* reserved words */
%token TOKEN_LDSQBRACKET "[["
%token TOKEN_RDSQBRACKET "]]"
@@ -70,27 +75,21 @@ script: statements {
parser->script->statements = $1;
}
-eol: TOKEN_EOL | TOKEN_EOF;
-
-statements: /* empty */ {
+statements: statement {
$$ = create_statements(parser);
+ statement_append($$, $1);
}
- | statements statement eol {
- statement_append($1, $2);
- $$ = $1;
- }
- | statements TOKEN_EOL {
+ | statements eol statement {
+ statement_append($1, $3);
$$ = $1;
}
-sep: TOKEN_DELIM | TOKEN_EOL;
-
-conditional: statement TOKEN_EOL "then" sep statements {
- $$ = create_statement_conditional(parser, $1, $5);
+conditional: statement eol "then" statements {
+ $$ = create_statement_conditional(parser, $1, $4);
}
-elif: "elif" TOKEN_DELIM conditional {
- $$ = $3;
+elif: "elif" conditional {
+ $$ = $2;
}
elifs: /* empty */ {
@@ -101,47 +100,49 @@ elifs: /* empty */ {
$$ = $1;
}
-statement:
- words {
+statement: {
+ $$ = NULL;
+ }
+ | words delim0 {
$$ = create_statement_simple(parser, $1);
}
| '{' statements '}' {
$$ = create_statement_block(parser, $2);
}
- | "if" TOKEN_DELIM conditional elifs "fi" {
- $$ = create_statement_if(parser, $3, $4, NULL);
+ | "if" conditional elifs "fi" {
+ $$ = create_statement_if(parser, $2, $3, NULL);
}
- | "if" TOKEN_DELIM conditional
+ | "if" conditional
elifs
- "else" sep
+ "else"
statements
"fi" {
- $$ = create_statement_if(parser, $3, $4, $7);
+ $$ = create_statement_if(parser, $2, $3, $5);
}
- | "function" TOKEN_DELIM word TOKEN_DELIM '{' statements '}' {
- $$ = create_statement_function(parser, $3, $6);
+ | "function" word delim '{' statements '}' {
+ $$ = create_statement_function(parser, $2, $5);
}
- | "menuentry" TOKEN_DELIM words TOKEN_DELIM
+ | "menuentry" words delim
'{' statements '}' {
- $$ = create_statement_menuentry(parser, $3, $6);
+ $$ = create_statement_menuentry(parser, $2, $5);
}
- | "submenu" TOKEN_DELIM words TOKEN_DELIM
+ | "submenu" words delim
'{' statements '}' {
/* we just flatten everything */
- $$ = create_statement_block(parser, $6);
+ $$ = create_statement_block(parser, $5);
}
- | "for" TOKEN_DELIM word TOKEN_DELIM "in" TOKEN_DELIM words TOKEN_EOL
- "do" sep
+ | "for" word delim "in" delim words eol
+ "do"
statements
"done" {
- $$ = create_statement_for(parser, $3, $7, $11);
+ $$ = create_statement_for(parser, $2, $6, $9);
}
words: word {
$$ = create_argv(parser);
argv_append($$, $1);
}
- | words TOKEN_DELIM word {
+ | words delim word {
argv_append($1, $3);
$$ = $1;
}
@@ -152,6 +153,13 @@ word: TOKEN_WORD
$$ = $1;
}
+delim0: /* empty */ |
+ delim
+
+delim: TOKEN_DELIM |
+ delim TOKEN_DELIM
+
+eol: TOKEN_EOL;
%%
void yyerror(struct grub2_parser *parser, void *scanner, const char *fmt, ...)
{
@@ -265,9 +273,8 @@ struct grub2_statement *create_statement_for(struct grub2_parser *parser,
void statement_append(struct grub2_statements *stmts,
struct grub2_statement *stmt)
{
- if (!stmt)
- return;
- list_add_tail(&stmts->list, &stmt->list);
+ if (stmt)
+ list_add_tail(&stmts->list, &stmt->list);
}
struct grub2_word *create_word_text(struct grub2_parser *parser,
@@ -319,6 +326,7 @@ struct grub2_parser *grub2_parser_create(struct discover_context *ctx)
parser = talloc(ctx, struct grub2_parser);
yylex_init_extra(parser, &parser->scanner);
parser->script = create_script(parser, ctx);
+ parser->inter_word = false;
return parser;
}
OpenPOWER on IntegriCloud