discover/grub2: Initial grub2 lexer
authorJeremy Kerr <jk@ozlabs.org>
Tue, 10 Sep 2013 03:01:55 +0000 (11:01 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Tue, 24 Sep 2013 05:14:59 +0000 (13:14 +0800)
Add a simple flex lexer to tokenise our grub2 config files.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
discover/grub2/grub2.h [new file with mode: 0644]
discover/grub2/lexer.l [new file with mode: 0644]
discover/grub2/parser.y [new file with mode: 0644]

diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h
new file mode 100644 (file)
index 0000000..f2a780d
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef GRUB2_H
+#define GRUB2_H
+
+struct grub2_parser {
+       void    *scanner;
+};
+
+
+#endif /* GRUB2_H */
+
diff --git a/discover/grub2/lexer.l b/discover/grub2/lexer.l
new file mode 100644 (file)
index 0000000..18d1667
--- /dev/null
@@ -0,0 +1,127 @@
+
+%{
+#include "parser.h"
+#include <talloc/talloc.h>
+%}
+
+%option nounput noinput
+%option warn
+%option noyywrap
+%option stack noyy_top_state
+%option reentrant
+%option bison-bridge
+%option noyyalloc noyyfree noyyrealloc
+%option extra-type="struct grub2_parser *"
+%option header-file="lexer.h"
+%option outfile="lexer.c"
+
+%x sqstring
+%x dqstring
+
+WORD   [^{}|&$;<> \t\n'"]+
+VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
+
+%%
+
+ /* discard leading & trailing whitespace, but keep inter-word delimeters */
+^[ \t]+        ;
+[ \t]+$        ;
+[ \t]* return TOKEN_DELIM;
+
+ /* reserved words */
+"[["         return TOKEN_LDSQBRACKET;
+"]]"         return TOKEN_RDSQBRACKET;
+"case"       return TOKEN_CASE;
+"do"         return TOKEN_DO;
+"done"       return TOKEN_DONE;
+"elif"       return TOKEN_ELIF;
+"esac"       return TOKEN_ESAC;
+"fi"         return TOKEN_FI;
+"for"        return TOKEN_FOR;
+"function"   return TOKEN_FUNCTION;
+"if"         return TOKEN_IF;
+"in"         return TOKEN_IN;
+"menuentry"  return TOKEN_MENUENTRY;
+"select"     return TOKEN_SELECT;
+"then"       return TOKEN_THEN;
+"time"       return TOKEN_TIME;
+"until"      return TOKEN_UTIL;
+"while"      return TOKEN_WHILE;
+
+ /* anything that's not a metachar: return as a plain word */
+{WORD} {
+               yylval->strval = talloc_strdup(yyscanner, yytext);
+               yylval->expand = 0;
+               return TOKEN_WORD;
+       }
+
+\${VARNAME} |
+\$\{{VARNAME}\} {
+               yylval->strval = talloc_strdup(yyscanner, yytext);
+               yylval->expand = 1;
+               yylval->split = 1;
+               return TOKEN_WORD;
+       }
+
+ /* single-quoted strings: return a single, non-expanded word token */
+\'     {
+               yy_push_state(sqstring, yyscanner);
+       }
+<sqstring>\' {
+               yy_pop_state(yyscanner);
+               return TOKEN_WORD;
+       }
+<sqstring>[^']+ {
+               yylval->expand = 0;
+               yylval->split = 0;
+               yylval->strval = talloc_strdup(yyscanner, yytext);
+       }
+
+ /* double-quoted strings: return a single, expanded word token */
+\"     {
+               yy_push_state(dqstring, yyscanner);
+       }
+<dqstring>\" {
+               yy_pop_state(yyscanner);
+               return TOKEN_WORD;
+       }
+<dqstring>([^"]|\\\")+ {
+               yylval->expand = 1;
+               yylval->split = 0;
+               yylval->strval = talloc_strdup(yyscanner, yytext);
+       }
+
+
+ /* blocks */
+"{"    return '{';
+"}"    return '}';
+
+ /* end-of-line */
+[ \t]*(;|\n)[ \t]*     return TOKEN_EOL;
+
+ /* strip comments */
+#.*$   ;
+
+
+.      printf("unknown token '%s'\n", yytext); exit(1);
+
+%%
+
+struct grub2_parser;
+
+void *yyalloc(size_t bytes, void *yyscanner)
+{
+       struct grub2_parser *parser = yyget_extra(yyscanner);
+       return talloc_size(parser, bytes);
+}
+
+void *yyrealloc(void *ptr, size_t bytes, void *yyscanner)
+{
+       struct grub2_parser *parser = yyget_extra(yyscanner);
+       return talloc_realloc_size(parser, ptr, bytes);
+}
+
+void yyfree(void *ptr, void *yyscanner __attribute__((unused)))
+{
+       talloc_free(ptr);
+}
diff --git a/discover/grub2/parser.y b/discover/grub2/parser.y
new file mode 100644 (file)
index 0000000..2af2132
--- /dev/null
@@ -0,0 +1,49 @@
+
+%pure-parser
+%lex-param { yyscan_t scanner }
+%parse-param { struct grub2_parser *parser }
+
+%{
+#include "lexer.h"
+%}
+
+%union {
+       struct {
+               char    *strval;
+               int     expand;
+               int     split;
+       };
+}
+
+/* reserved words */
+%token TOKEN_LDSQBRACKET       "[["
+%token TOKEN_RDSQBRACKET       "]]"
+%token TOKEN_CASE              "case"
+%token TOKEN_DO                "do"
+%token TOKEN_DONE              "done"
+%token TOKEN_ELIF              "elif"
+%token TOKEN_ESAC              "esac"
+%token TOKEN_FI                "fi"
+%token TOKEN_FOR               "for"
+%token TOKEN_FUNCTION          "function"
+%token TOKEN_IF                "if"
+%token TOKEN_IN                "in"
+%token TOKEN_MENUENTRY         "menuentry"
+%token TOKEN_SELECT            "select"
+%token TOKEN_THEN              "then"
+%token TOKEN_TIME              "time"
+%token TOKEN_UTIL              "until"
+%token TOKEN_WHILE             "while"
+
+/* syntax */
+%token TOKEN_EOL
+%token TOKEN_DELIM
+%token TOKEN_WORD
+
+%start script
+
+%%
+
+script: /* empty */
+
+%%