summaryrefslogtreecommitdiffstats
path: root/discover/grub2/lexer.l
blob: 3e1f9fa148c62174acb30258328c578c231f954e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

%{
#include "grub2.h"
#include "parser.h"
#include <talloc/talloc.h>
%}

%option nounput noinput
%option batch never-interactive
%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;
"else"       return TOKEN_ELSE;
"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->word = create_word_text(yyget_extra(yyscanner), yytext);
		return TOKEN_WORD;
	}

\${VARNAME} |
\$\{{VARNAME}\} {
		if (yytext[1] == '{') {
			yytext[yyleng-1] = '\0';
			yytext++;
		}
		yytext++;
		yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
						true);
		return TOKEN_WORD;
	}

 /* single-quoted strings: return a single, non-expanded word token */
\'	{
		yy_push_state(sqstring, yyscanner);
	}
<sqstring>\' {
		yy_pop_state(yyscanner);
	}
<sqstring>[^']+ {
		yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
		return TOKEN_WORD;
	}

 /* double-quoted strings: return a single, expanded word token */
\"	{
		yy_push_state(dqstring, yyscanner);
	}
<dqstring>\" {
		yy_pop_state(yyscanner);
	}
<dqstring>([^"\$]|\\\")+ {
		yylval->word = create_word_text(yyget_extra(yyscanner), yytext);
		return TOKEN_WORD;
	}
<dqstring>\${VARNAME} |
<dqstring>\$\{{VARNAME}\} {
		if (yytext[1] == '{') {
			yytext[yyleng-1] = '\0';
			yytext++;
		}
		yytext++;
		yylval->word = create_word_var(yyget_extra(yyscanner), yytext,
						false);
		return TOKEN_WORD;
	}



 /* 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);
}
OpenPOWER on IntegriCloud