• 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 #ifdef _MSC_VER
38 #define YY_NO_UNISTD_H
39 #endif
40 
41 #define YY_NO_INPUT
42 
43 #define YY_USER_ACTION							\
44 	do {								\
45 		if (parser->has_new_line_number)			\
46 			yylineno = parser->new_line_number;		\
47 		if (parser->has_new_source_number)			\
48 			yylloc->source = parser->new_source_number;	\
49 		yylloc->first_column = yycolumn + 1;			\
50 		yylloc->first_line = yylineno;				\
51 		yycolumn += yyleng;					\
52 		parser->has_new_line_number = 0;			\
53 		parser->has_new_source_number = 0;			\
54  } while(0);
55 
56 #define YY_USER_INIT			\
57 	do {				\
58 		yylineno = 1;		\
59 		yycolumn = 1;		\
60 		yylloc->source = 0;	\
61 	} while(0)
62 %}
63 
64 %option bison-bridge bison-locations reentrant noyywrap
65 %option extra-type="glcpp_parser_t *"
66 %option prefix="glcpp_"
67 %option stack
68 %option never-interactive
69 
70 %x DONE COMMENT UNREACHABLE SKIP DEFINE
71 
72 SPACE		[[:space:]]
73 NONSPACE	[^[:space:]]
74 NEWLINE		[\n]
75 HSPACE		[ \t]
76 HASH		^{HSPACE}*#{HSPACE}*
77 IDENTIFIER	[_a-zA-Z][_a-zA-Z0-9]*
78 PUNCTUATION	[][(){}.&*~!/%<>^|;,=+-]
79 
80 /* The OTHER class is simply a catch-all for things that the CPP
81 parser just doesn't care about. Since flex regular expressions that
82 match longer strings take priority over those matching shorter
83 strings, we have to be careful to avoid OTHER matching and hiding
84 something that CPP does care about. So we simply exclude all
85 characters that appear in any other expressions. */
86 
87 OTHER		[^][_#[:space:]#a-zA-Z0-9(){}.&*~!/%<>^|;,=+-]
88 
89 DIGITS			[0-9][0-9]*
90 DECIMAL_INTEGER		[1-9][0-9]*[uU]?
91 OCTAL_INTEGER		0[0-7]*[uU]?
92 HEXADECIMAL_INTEGER	0[xX][0-9a-fA-F]+[uU]?
93 
94 %%
95 	/* Implicitly switch between SKIP and INITIAL (non-skipping);
96 	 * don't switch if some other state was explicitly set.
97 	 */
98 	glcpp_parser_t *parser = yyextra;
99 	if (YY_START == 0 || YY_START == SKIP) {
100 		if (parser->lexing_if || parser->skip_stack == NULL || parser->skip_stack->type == SKIP_NO_SKIP) {
101 			BEGIN 0;
102 		} else {
103 			BEGIN SKIP;
104 		}
105 	}
106 
107 	/* Single-line comments */
108 "//"[^\n]* {
109 }
110 
111 	/* Multi-line comments */
112 "/*"                    { yy_push_state(COMMENT, yyscanner); }
113 <COMMENT>[^*\n]*
114 <COMMENT>[^*\n]*\n      { yylineno++; yycolumn = 0; return NEWLINE; }
115 <COMMENT>"*"+[^*/\n]*
116 <COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; return NEWLINE; }
117 <COMMENT>"*"+"/"        {
118 	yy_pop_state(yyscanner);
119 	if (yyextra->space_tokens)
120 		return SPACE;
121 }
122 
123 {HASH}version {
124 	yylval->str = ralloc_strdup (yyextra, yytext);
125 	yyextra->space_tokens = 0;
126 	return HASH_VERSION;
127 }
128 
129 	/* glcpp doesn't handle #extension, #version, or #pragma directives.
130 	 * Simply pass them through to the main compiler's lexer/parser. */
131 {HASH}(extension|pragma)[^\n]+ {
132 	yylval->str = ralloc_strdup (yyextra, yytext);
133 	yylineno++;
134 	yycolumn = 0;
135 	return OTHER;
136 }
137 
138 {HASH}line {
139 	return HASH_LINE;
140 }
141 
142 <SKIP,INITIAL>{
143 {HASH}ifdef {
144 	yyextra->lexing_if = 1;
145 	yyextra->space_tokens = 0;
146 	return HASH_IFDEF;
147 }
148 
149 {HASH}ifndef {
150 	yyextra->lexing_if = 1;
151 	yyextra->space_tokens = 0;
152 	return HASH_IFNDEF;
153 }
154 
155 {HASH}if/[^_a-zA-Z0-9] {
156 	yyextra->lexing_if = 1;
157 	yyextra->space_tokens = 0;
158 	return HASH_IF;
159 }
160 
161 {HASH}elif {
162 	yyextra->lexing_if = 1;
163 	yyextra->space_tokens = 0;
164 	return HASH_ELIF;
165 }
166 
167 {HASH}else {
168 	yyextra->space_tokens = 0;
169 	return HASH_ELSE;
170 }
171 
172 {HASH}endif {
173 	yyextra->space_tokens = 0;
174 	return HASH_ENDIF;
175 }
176 }
177 
178 <SKIP>[^\n] ;
179 
180 {HASH}error.* {
181 	char *p;
182 	for (p = yytext; !isalpha(p[0]); p++); /* skip "  #   " */
183 	p += 5; /* skip "error" */
184 	glcpp_error(yylloc, yyextra, "#error%s", p);
185 }
186 
187 {HASH}define{HSPACE}+ {
188 	yyextra->space_tokens = 0;
189 	yy_push_state(DEFINE, yyscanner);
190 	return HASH_DEFINE;
191 }
192 
193 <DEFINE>{IDENTIFIER}/"(" {
194 	yy_pop_state(yyscanner);
195 	yylval->str = ralloc_strdup (yyextra, yytext);
196 	return FUNC_IDENTIFIER;
197 }
198 
199 <DEFINE>{IDENTIFIER} {
200 	yy_pop_state(yyscanner);
201 	yylval->str = ralloc_strdup (yyextra, yytext);
202 	return OBJ_IDENTIFIER;
203 }
204 
205 {HASH}undef {
206 	yyextra->space_tokens = 0;
207 	return HASH_UNDEF;
208 }
209 
210 {HASH} {
211 	yyextra->space_tokens = 0;
212 	return HASH;
213 }
214 
215 {DECIMAL_INTEGER} {
216 	yylval->str = ralloc_strdup (yyextra, yytext);
217 	return INTEGER_STRING;
218 }
219 
220 {OCTAL_INTEGER} {
221 	yylval->str = ralloc_strdup (yyextra, yytext);
222 	return INTEGER_STRING;
223 }
224 
225 {HEXADECIMAL_INTEGER} {
226 	yylval->str = ralloc_strdup (yyextra, yytext);
227 	return INTEGER_STRING;
228 }
229 
230 "<<"  {
231 	return LEFT_SHIFT;
232 }
233 
234 ">>" {
235 	return RIGHT_SHIFT;
236 }
237 
238 "<=" {
239 	return LESS_OR_EQUAL;
240 }
241 
242 ">=" {
243 	return GREATER_OR_EQUAL;
244 }
245 
246 "==" {
247 	return EQUAL;
248 }
249 
250 "!=" {
251 	return NOT_EQUAL;
252 }
253 
254 "&&" {
255 	return AND;
256 }
257 
258 "||" {
259 	return OR;
260 }
261 
262 "##" {
263 	return PASTE;
264 }
265 
266 "defined" {
267 	return DEFINED;
268 }
269 
270 {IDENTIFIER} {
271 	yylval->str = ralloc_strdup (yyextra, yytext);
272 	return IDENTIFIER;
273 }
274 
275 {PUNCTUATION} {
276 	return yytext[0];
277 }
278 
279 {OTHER}+ {
280 	yylval->str = ralloc_strdup (yyextra, yytext);
281 	return OTHER;
282 }
283 
284 {HSPACE}+ {
285 	if (yyextra->space_tokens) {
286 		return SPACE;
287 	}
288 }
289 
290 <SKIP,INITIAL>\n {
291 	yyextra->lexing_if = 0;
292 	yylineno++;
293 	yycolumn = 0;
294 	return NEWLINE;
295 }
296 
297 	/* Handle missing newline at EOF. */
298 <INITIAL><<EOF>> {
299 	BEGIN DONE; /* Don't keep matching this rule forever. */
300 	yyextra->lexing_if = 0;
301 	return NEWLINE;
302 }
303 
304 	/* We don't actually use the UNREACHABLE start condition. We
305 	only have this action here so that we can pretend to call some
306 	generated functions, (to avoid "defined but not used"
307 	warnings. */
308 <UNREACHABLE>. {
309 	unput('.');
310 	yy_top_state(yyextra);
311 }
312 
313 %%
314 
315 void
316 glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader)
317 {
318 	yy_scan_string(shader, parser->scanner);
319 }
320