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 #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