diff options
author | Carl Worth <cworth@cworth.org> | 2010-05-24 10:37:38 -0700 |
---|---|---|
committer | Carl Worth <cworth@cworth.org> | 2010-05-24 10:37:38 -0700 |
commit | bcbd587b0f5312d85307785ee2df6e5906af4f7b (patch) | |
tree | b44d1115168ddf3bb401c56a1938a6813718cbdc | |
parent | b20d33c5c6fea8e392c26e9ab060efd14034f1f9 (diff) |
Implement all operators specified for GLSL #if expressions (with tests).
The operator coverage here is quite complete. The one big thing
missing is that we are not yet doing macro expansion in #if
lines. This makes the whole support fairly useless, so we plan to fix
that shortcoming right away.
-rw-r--r-- | glcpp-lex.l | 45 | ||||
-rw-r--r-- | glcpp-parse.y | 97 | ||||
-rw-r--r-- | tests/049-if-expression-precedence.c | 6 | ||||
-rw-r--r-- | tests/050-if-defined.c | 19 | ||||
-rw-r--r-- | tests/051-if-relational.c | 35 |
5 files changed, 195 insertions, 7 deletions
diff --git a/glcpp-lex.l b/glcpp-lex.l index 825ce3d370..84166fb76f 100644 --- a/glcpp-lex.l +++ b/glcpp-lex.l @@ -66,6 +66,51 @@ TOKEN [^[:space:](),]+ return INTEGER; } +<ST_IF>"defined" { + return DEFINED; +} + +<ST_IF>"<<" { + return LEFT_SHIFT; +} + +<ST_IF>">>" { + return RIGHT_SHIFT; +} + +<ST_IF>"<=" { + return LESS_OR_EQUAL; +} + +<ST_IF>">=" { + return GREATER_OR_EQUAL; +} + +<ST_IF>"==" { + return EQUAL; +} + +<ST_IF>"!=" { + return NOT_EQUAL; +} + +<ST_IF>"&&" { + return AND; +} + +<ST_IF>"||" { + return OR; +} + +<ST_IF>[-+*/%<>&^|()] { + return yytext[0]; +} + +<ST_IF>{IDENTIFIER} { + yylval.str = xtalloc_strdup (yyextra, yytext); + return IDENTIFIER; +} + <ST_IF>{HSPACE}+ <ST_IF>\n { diff --git a/glcpp-parse.y b/glcpp-parse.y index 26432f2032..0d3afa7af6 100644 --- a/glcpp-parse.y +++ b/glcpp-parse.y @@ -118,13 +118,24 @@ glcpp_parser_lex (glcpp_parser_t *parser); %parse-param {glcpp_parser_t *parser} %lex-param {glcpp_parser_t *parser} -%token DEFINE ELIF ELSE ENDIF FUNC_MACRO IDENTIFIER IDENTIFIER_FINALIZED IF IFDEF IFNDEF INTEGER OBJ_MACRO NEWLINE SEPARATOR SPACE TOKEN UNDEF +%token DEFINE DEFINED ELIF ELSE ENDIF FUNC_MACRO IDENTIFIER IDENTIFIER_FINALIZED IF IFDEF IFNDEF INTEGER OBJ_MACRO NEWLINE SPACE TOKEN UNDEF %type <ival> expression INTEGER punctuator %type <str> content FUNC_MACRO IDENTIFIER IDENTIFIER_FINALIZED OBJ_MACRO %type <argument_list> argument_list %type <string_list> macro parameter_list %type <token> TOKEN argument_word argument_word_or_comma %type <token_list> argument argument_or_comma replacement_list pp_tokens +%left OR +%left AND +%left '|' +%left '^' +%left '&' +%left EQUAL NOT_EQUAL +%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL +%left LEFT_SHIFT RIGHT_SHIFT +%left '+' '-' +%left '*' '/' '%' +%right UNARY /* Hard to remove shift/reduce conflicts documented as follows: * @@ -142,11 +153,7 @@ glcpp_parser_lex (glcpp_parser_t *parser); %% - /* We do all printing at the input level. - * - * The value for "input" is simply TOKEN or SEPARATOR so we - * can decide whether it's necessary to print a space - * character between any two. */ + /* We do all printing at the input level. */ input: /* empty */ { parser->just_printed_separator = 1; @@ -350,11 +357,87 @@ directive: } ; -/* XXX: Need to fill out with all operators. */ expression: INTEGER { $$ = $1; } +| expression OR expression { + $$ = $1 || $3; + } +| expression AND expression { + $$ = $1 && $3; + } +| expression '|' expression { + $$ = $1 | $3; + } +| expression '^' expression { + $$ = $1 ^ $3; + } +| expression '&' expression { + $$ = $1 & $3; + } +| expression NOT_EQUAL expression { + $$ = $1 != $3; + } +| expression EQUAL expression { + $$ = $1 == $3; + } +| expression GREATER_OR_EQUAL expression { + $$ = $1 >= $3; + } +| expression LESS_OR_EQUAL expression { + $$ = $1 <= $3; + } +| expression '>' expression { + $$ = $1 > $3; + } +| expression '<' expression { + $$ = $1 < $3; + } +| expression RIGHT_SHIFT expression { + $$ = $1 >> $3; + } +| expression LEFT_SHIFT expression { + $$ = $1 << $3; + } +| expression '-' expression { + $$ = $1 - $3; + } +| expression '+' expression { + $$ = $1 + $3; + } +| expression '%' expression { + $$ = $1 % $3; + } +| expression '/' expression { + $$ = $1 / $3; + } +| expression '*' expression { + $$ = $1 * $3; + } +| '!' expression %prec UNARY { + $$ = ! $2; + } +| '~' expression %prec UNARY { + $$ = ~ $2; + } +| '-' expression %prec UNARY { + $$ = - $2; + } +| '+' expression %prec UNARY { + $$ = + $2; + } +| DEFINED IDENTIFIER %prec UNARY { + string_list_t *macro = hash_table_find (parser->defines, $2); + talloc_free ($2); + if (macro) + $$ = 1; + else + $$ = 0; + } +| '(' expression ')' { + $$ = $2; + } ; parameter_list: diff --git a/tests/049-if-expression-precedence.c b/tests/049-if-expression-precedence.c new file mode 100644 index 0000000000..cea935220f --- /dev/null +++ b/tests/049-if-expression-precedence.c @@ -0,0 +1,6 @@ +#if 1 + 2 * 3 + - (25 % 17 - + 1) +failure with operator precedence +#else +success +#endif + diff --git a/tests/050-if-defined.c b/tests/050-if-defined.c new file mode 100644 index 0000000000..9838cc747d --- /dev/null +++ b/tests/050-if-defined.c @@ -0,0 +1,19 @@ +#if defined foo +failure_1 +#else +success_1 +#endif +#define foo +#if defined foo +success_2 +#else +failure_2 +#endif +#undef foo +#if defined foo +failure_3 +#else +success_3 +#endif + + diff --git a/tests/051-if-relational.c b/tests/051-if-relational.c new file mode 100644 index 0000000000..c3db488e0d --- /dev/null +++ b/tests/051-if-relational.c @@ -0,0 +1,35 @@ +#if 3 < 2 +failure_1 +#else +success_1 +#endif + +#if 3 >= 2 +success_2 +#else +failure_2 +#endif + +#if 2 + 3 <= 5 +success_3 +#else +failure_3 +#endif + +#if 3 - 2 == 1 +success_3 +#else +failure_3 +#endif + +#if 1 > 3 +failure_4 +#else +success_4 +#endif + +#if 1 != 5 +success_5 +#else +failure_5 +#endif |