discover/grub2: Initial grub2 lexer
[petitboot] / discover / grub2 / lexer.l
1
2 %{
3 #include "parser.h"
4 #include <talloc/talloc.h>
5 %}
6
7 %option nounput noinput
8 %option warn
9 %option noyywrap
10 %option stack noyy_top_state
11 %option reentrant
12 %option bison-bridge
13 %option noyyalloc noyyfree noyyrealloc
14 %option extra-type="struct grub2_parser *"
15 %option header-file="lexer.h"
16 %option outfile="lexer.c"
17
18 %x sqstring
19 %x dqstring
20
21 WORD    [^{}|&$;<> \t\n'"]+
22 VARNAME ([[:alpha:]][_[:alnum:]]*|[0-9]|[\?@\*#])
23
24 %%
25
26  /* discard leading & trailing whitespace, but keep inter-word delimeters */
27 ^[ \t]+ ;
28 [ \t]+$ ;
29 [ \t]*  return TOKEN_DELIM;
30
31  /* reserved words */
32 "[["         return TOKEN_LDSQBRACKET;
33 "]]"         return TOKEN_RDSQBRACKET;
34 "case"       return TOKEN_CASE;
35 "do"         return TOKEN_DO;
36 "done"       return TOKEN_DONE;
37 "elif"       return TOKEN_ELIF;
38 "esac"       return TOKEN_ESAC;
39 "fi"         return TOKEN_FI;
40 "for"        return TOKEN_FOR;
41 "function"   return TOKEN_FUNCTION;
42 "if"         return TOKEN_IF;
43 "in"         return TOKEN_IN;
44 "menuentry"  return TOKEN_MENUENTRY;
45 "select"     return TOKEN_SELECT;
46 "then"       return TOKEN_THEN;
47 "time"       return TOKEN_TIME;
48 "until"      return TOKEN_UTIL;
49 "while"      return TOKEN_WHILE;
50
51  /* anything that's not a metachar: return as a plain word */
52 {WORD}  {
53                 yylval->strval = talloc_strdup(yyscanner, yytext);
54                 yylval->expand = 0;
55                 return TOKEN_WORD;
56         }
57
58 \${VARNAME} |
59 \$\{{VARNAME}\} {
60                 yylval->strval = talloc_strdup(yyscanner, yytext);
61                 yylval->expand = 1;
62                 yylval->split = 1;
63                 return TOKEN_WORD;
64         }
65
66  /* single-quoted strings: return a single, non-expanded word token */
67 \'      {
68                 yy_push_state(sqstring, yyscanner);
69         }
70 <sqstring>\' {
71                 yy_pop_state(yyscanner);
72                 return TOKEN_WORD;
73         }
74 <sqstring>[^']+ {
75                 yylval->expand = 0;
76                 yylval->split = 0;
77                 yylval->strval = talloc_strdup(yyscanner, yytext);
78         }
79
80  /* double-quoted strings: return a single, expanded word token */
81 \"      {
82                 yy_push_state(dqstring, yyscanner);
83         }
84 <dqstring>\" {
85                 yy_pop_state(yyscanner);
86                 return TOKEN_WORD;
87         }
88 <dqstring>([^"]|\\\")+ {
89                 yylval->expand = 1;
90                 yylval->split = 0;
91                 yylval->strval = talloc_strdup(yyscanner, yytext);
92         }
93
94
95  /* blocks */
96 "{"     return '{';
97 "}"     return '}';
98
99  /* end-of-line */
100 [ \t]*(;|\n)[ \t]*      return TOKEN_EOL;
101
102  /* strip comments */
103 #.*$    ;
104
105
106 .       printf("unknown token '%s'\n", yytext); exit(1);
107
108 %%
109
110 struct grub2_parser;
111
112 void *yyalloc(size_t bytes, void *yyscanner)
113 {
114         struct grub2_parser *parser = yyget_extra(yyscanner);
115         return talloc_size(parser, bytes);
116 }
117
118 void *yyrealloc(void *ptr, size_t bytes, void *yyscanner)
119 {
120         struct grub2_parser *parser = yyget_extra(yyscanner);
121         return talloc_realloc_size(parser, ptr, bytes);
122 }
123
124 void yyfree(void *ptr, void *yyscanner __attribute__((unused)))
125 {
126         talloc_free(ptr);
127 }