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