From 0ac0cc8dbd8c3687880f3115ae41f9903e9f2333 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 10 Sep 2013 11:01:55 +0800 Subject: [PATCH] discover/grub2: Initial grub2 lexer Add a simple flex lexer to tokenise our grub2 config files. Signed-off-by: Jeremy Kerr --- discover/grub2/grub2.h | 10 ++++ discover/grub2/lexer.l | 127 ++++++++++++++++++++++++++++++++++++++++ discover/grub2/parser.y | 49 ++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 discover/grub2/grub2.h create mode 100644 discover/grub2/lexer.l create mode 100644 discover/grub2/parser.y diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h new file mode 100644 index 0000000..f2a780d --- /dev/null +++ b/discover/grub2/grub2.h @@ -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 index 0000000..18d1667 --- /dev/null +++ b/discover/grub2/lexer.l @@ -0,0 +1,127 @@ + +%{ +#include "parser.h" +#include +%} + +%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); + } +\' { + yy_pop_state(yyscanner); + return TOKEN_WORD; + } +[^']+ { + 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); + } +\" { + yy_pop_state(yyscanner); + return TOKEN_WORD; + } +([^"]|\\\")+ { + 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 index 0000000..2af2132 --- /dev/null +++ b/discover/grub2/parser.y @@ -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 */ + +%% -- 2.39.2