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