• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 %{
2 /*
3  * Copyright © 2010 Intel Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <stdio.h>
26 #include <string.h>
27 #include <ctype.h>
28 
29 #include "glcpp.h"
30 #include "glcpp-parse.h"
31 
32 /* Flex annoyingly generates some functions without making them
33  * static. Let's declare them here. */
34 int glcpp_get_column  (yyscan_t yyscanner);
35 void glcpp_set_column (int  column_no , yyscan_t yyscanner);
36 
37 #define YY_NO_INPUT
38 
39 #define YY_USER_ACTION                                          \
40    do {                                                         \
41       yylloc->first_column = yycolumn + 1;                      \
42       yylloc->first_line = yylineno;                            \
43       yycolumn += yyleng;                                       \
44    } while(0);
45 
46 #define YY_USER_INIT			\
47 	do {				\
48 		yylineno = 1;		\
49 		yycolumn = 1;		\
50 		yylloc->source = 0;	\
51 	} while(0)
52 %}
53 
54 %option bison-bridge bison-locations reentrant noyywrap
55 %option extra-type="glcpp_parser_t *"
56 %option prefix="glcpp_"
57 %option stack
58 %option never-interactive
59 
60 %x DONE COMMENT UNREACHABLE
61 
62 SPACE		[[:space:]]
63 NONSPACE	[^[:space:]]
64 NEWLINE		[\n]
65 HSPACE		[ \t]
66 HASH		^{HSPACE}*#{HSPACE}*
67 IDENTIFIER	[_a-zA-Z][_a-zA-Z0-9]*
68 PUNCTUATION	[][(){}.&*~!/%<>^|;,=+-]
69 OTHER		[^][(){}.&*~!/%<>^|;,=#[:space:]+-]+
70 
71 DIGITS			[0-9][0-9]*
72 DECIMAL_INTEGER		[1-9][0-9]*[uU]?
73 OCTAL_INTEGER		0[0-7]*[uU]?
74 HEXADECIMAL_INTEGER	0[xX][0-9a-fA-F]+[uU]?
75 
76 %%
77 
78 	/* Single-line comments */
79 "//"[^\n]* {
80 }
81 
82 	/* Multi-line comments */
83 "/*"                    { yy_push_state(COMMENT, yyscanner); }
84 <COMMENT>[^*\n]*
85 <COMMENT>[^*\n]*\n      { yylineno++; yycolumn = 0; return NEWLINE; }
86 <COMMENT>"*"+[^*/\n]*
87 <COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; return NEWLINE; }
88 <COMMENT>"*"+"/"        {
89 	yy_pop_state(yyscanner);
90 	if (yyextra->space_tokens)
91 		return SPACE;
92 }
93 
94 {HASH}version {
95 	yylval->str = talloc_strdup (yyextra, yytext);
96 	yyextra->space_tokens = 0;
97 	return HASH_VERSION;
98 }
99 
100 	/* glcpp doesn't handle #extension, #version, or #pragma directives.
101 	 * Simply pass them through to the main compiler's lexer/parser. */
102 {HASH}(extension|pragma)[^\n]+ {
103 	yylval->str = talloc_strdup (yyextra, yytext);
104 	yylineno++;
105 	yycolumn = 0;
106 	return OTHER;
107 }
108 
109 {HASH}line{HSPACE}+{DIGITS}{HSPACE}+{DIGITS}{HSPACE}*$ {
110 	/* Eat characters until the first digit is
111 	 * encountered
112 	 */
113 	char *ptr = yytext;
114 	while (!isdigit(*ptr))
115 		ptr++;
116 
117 	/* Subtract one from the line number because
118 	 * yylineno is zero-based instead of
119 	 * one-based.
120 	 */
121 	yylineno = strtol(ptr, &ptr, 0) - 1;
122 	yylloc->source = strtol(ptr, NULL, 0);
123 }
124 
125 {HASH}line{HSPACE}+{DIGITS}{HSPACE}*$ {
126 	/* Eat characters until the first digit is
127 	 * encountered
128 	 */
129 	char *ptr = yytext;
130 	while (!isdigit(*ptr))
131 		ptr++;
132 
133 	/* Subtract one from the line number because
134 	 * yylineno is zero-based instead of
135 	 * one-based.
136 	 */
137 	yylineno = strtol(ptr, &ptr, 0) - 1;
138 }
139 
140 {HASH}ifdef/.*\n {
141 	yyextra->lexing_if = 1;
142 	yyextra->space_tokens = 0;
143 	return HASH_IFDEF;
144 }
145 
146 {HASH}ifndef/.*\n {
147 	yyextra->lexing_if = 1;
148 	yyextra->space_tokens = 0;
149 	return HASH_IFNDEF;
150 }
151 
152 {HASH}if/[^_a-zA-Z0-9].*\n {
153 	yyextra->lexing_if = 1;
154 	yyextra->space_tokens = 0;
155 	return HASH_IF;
156 }
157 
158 {HASH}elif/.*\n {
159 	yyextra->lexing_if = 1;
160 	yyextra->space_tokens = 0;
161 	return HASH_ELIF;
162 }
163 
164 {HASH}else/.*\n {
165 	yyextra->space_tokens = 0;
166 	return HASH_ELSE;
167 }
168 
169 {HASH}endif/.*\n {
170 	yyextra->space_tokens = 0;
171 	return HASH_ENDIF;
172 }
173 
174 	/* When skipping (due to an #if 0 or similar) consume anything
175 	 * up to a newline. We do this with less priority than any
176 	 * #if-related directive (#if, #elif, #else, #endif), but with
177 	 * more priority than any other directive or token to avoid
178 	 * any side-effects from skipped content.
179 	 *
180 	 * We use the lexing_if flag to avoid skipping any part of an
181 	 * if conditional expression. */
182 [^\n]+/\n {
183 	/* Since this rule always matches, YY_USER_ACTION gets called for it,
184 	 * wrongly incrementing yycolumn.  We undo that effect here. */
185 	yycolumn -= yyleng;
186 	if (yyextra->lexing_if ||
187 	    yyextra->skip_stack == NULL ||
188 	    yyextra->skip_stack->type == SKIP_NO_SKIP)
189 	{
190 		REJECT;
191 	}
192 }
193 
194 {HASH}error.* {
195 	char *p;
196 	for (p = yytext; !isalpha(p[0]); p++); /* skip "  #   " */
197 	p += 5; /* skip "error" */
198 	glcpp_error(yylloc, yyextra, "#error%s", p);
199 }
200 
201 {HASH}define{HSPACE}+/{IDENTIFIER}"(" {
202 	yyextra->space_tokens = 0;
203 	return HASH_DEFINE_FUNC;
204 }
205 
206 {HASH}define {
207 	yyextra->space_tokens = 0;
208 	return HASH_DEFINE_OBJ;
209 }
210 
211 {HASH}undef {
212 	yyextra->space_tokens = 0;
213 	return HASH_UNDEF;
214 }
215 
216 {HASH} {
217 	yyextra->space_tokens = 0;
218 	return HASH;
219 }
220 
221 {DECIMAL_INTEGER} {
222 	yylval->str = talloc_strdup (yyextra, yytext);
223 	return INTEGER_STRING;
224 }
225 
226 {OCTAL_INTEGER} {
227 	yylval->str = talloc_strdup (yyextra, yytext);
228 	return INTEGER_STRING;
229 }
230 
231 {HEXADECIMAL_INTEGER} {
232 	yylval->str = talloc_strdup (yyextra, yytext);
233 	return INTEGER_STRING;
234 }
235 
236 "<<"  {
237 	return LEFT_SHIFT;
238 }
239 
240 ">>" {
241 	return RIGHT_SHIFT;
242 }
243 
244 "<=" {
245 	return LESS_OR_EQUAL;
246 }
247 
248 ">=" {
249 	return GREATER_OR_EQUAL;
250 }
251 
252 "==" {
253 	return EQUAL;
254 }
255 
256 "!=" {
257 	return NOT_EQUAL;
258 }
259 
260 "&&" {
261 	return AND;
262 }
263 
264 "||" {
265 	return OR;
266 }
267 
268 "##" {
269 	return PASTE;
270 }
271 
272 "defined" {
273 	return DEFINED;
274 }
275 
276 {IDENTIFIER} {
277 	yylval->str = talloc_strdup (yyextra, yytext);
278 	return IDENTIFIER;
279 }
280 
281 {PUNCTUATION} {
282 	return yytext[0];
283 }
284 
285 {OTHER}+ {
286 	yylval->str = talloc_strdup (yyextra, yytext);
287 	return OTHER;
288 }
289 
290 {HSPACE}+ {
291 	if (yyextra->space_tokens) {
292 		return SPACE;
293 	}
294 }
295 
296 \n {
297 	yyextra->lexing_if = 0;
298 	yylineno++;
299 	yycolumn = 0;
300 	return NEWLINE;
301 }
302 
303 	/* Handle missing newline at EOF. */
304 <INITIAL><<EOF>> {
305 	BEGIN DONE; /* Don't keep matching this rule forever. */
306 	yyextra->lexing_if = 0;
307 	return NEWLINE;
308 }
309 
310 	/* We don't actually use the UNREACHABLE start condition. We
311 	only have this action here so that we can pretend to call some
312 	generated functions, (to avoid "defined but not used"
313 	warnings. */
314 <UNREACHABLE>. {
315 	unput('.');
316 	yy_top_state(yyextra);
317 }
318 
319 %%
320 
321 void
322 glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader)
323 {
324 	yy_scan_string(shader, parser->scanner);
325 }
326