Home | History | Annotate | Download | only in glcpp
      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