glsl/glcpp: Swallow empty #pragma directives.
[mesa.git] / src / glsl / glcpp / glcpp-lex.l
index d0894c1515b38349a6cfbbd3acc0c0306e58612b..aeaf8abdf8a8851a96f9c2410cec0e090de54d1f 100644 (file)
@@ -160,12 +160,16 @@ glcpp_lex_update_state_per_token (glcpp_parser_t *parser, int token)
 %option prefix="glcpp_"
 %option stack
 %option never-interactive
+%option warn nodefault
 
-%x DONE COMMENT HASH UNREACHABLE DEFINE NEWLINE_CATCHUP
+       /* Note: When adding any start conditions to this list, you must also
+        * update the "Internal compiler error" catch-all rule near the end of
+        * this file. */
+
+%x COMMENT DEFINE DONE HASH NEWLINE_CATCHUP UNREACHABLE
 
 SPACE          [[:space:]]
 NONSPACE       [^[:space:]]
-NEWLINE                [\n]
 HSPACE         [ \t]
 HASH           #
 IDENTIFIER     [_a-zA-Z][_a-zA-Z0-9]*
@@ -246,15 +250,15 @@ HEXADECIMAL_INTEGER       0[xX][0-9a-fA-F]+[uU]?
        }
 
        /* Single-line comments */
-"//"[^\n]* {
+<INITIAL,DEFINE,HASH>"//"[^\r\n]* {
 }
 
        /* Multi-line comments */
-<DEFINE,HASH,INITIAL>"/*"                    { yy_push_state(COMMENT, yyscanner); }
-<COMMENT>[^*\n]*
-<COMMENT>[^*\n]*\n      { yylineno++; yycolumn = 0; parser->commented_newlines++; }
-<COMMENT>"*"+[^*/\n]*
-<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; parser->commented_newlines++; }
+<INITIAL,DEFINE,HASH>"/*"   { yy_push_state(COMMENT, yyscanner); }
+<COMMENT>[^*\r\n]*
+<COMMENT>[^*\r\n]*[\r\n]    { yylineno++; yycolumn = 0; parser->commented_newlines++; }
+<COMMENT>"*"+[^*/\r\n]*
+<COMMENT>"*"+[^*/\r\n]*[\r\n] { yylineno++; yycolumn = 0; parser->commented_newlines++; }
 <COMMENT>"*"+"/"        {
        yy_pop_state(yyscanner);
        /* In the <HASH> start condition, we don't want any SPACE token. */
@@ -283,12 +287,16 @@ HEXADECIMAL_INTEGER       0[xX][0-9a-fA-F]+[uU]?
        RETURN_STRING_TOKEN (VERSION_TOKEN);
 }
 
+       /* Swallow empty #pragma directives, (to avoid confusing the
+        * downstream compiler). */
+<HASH>pragma{HSPACE}*/[\r\n] {
+       BEGIN INITIAL;
+}
+
        /* glcpp doesn't handle #extension, #version, or #pragma directives.
         * Simply pass them through to the main compiler's lexer/parser. */
-<HASH>(extension|pragma)[^\n]* {
+<HASH>(extension|pragma)[^\r\n]* {
        BEGIN INITIAL;
-       yylineno++;
-       yycolumn = 0;
        RETURN_STRING_TOKEN (PRAGMA);
 }
 
@@ -346,7 +354,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
 
 <HASH>error.* {
        BEGIN INITIAL;
-       RETURN_STRING_TOKEN (ERROR);
+       RETURN_STRING_TOKEN (ERROR_TOKEN);
 }
 
        /* After we see a "#define" we enter the <DEFINE> start state
@@ -367,7 +375,7 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
         *      * Anything else, (not an identifier, not a comment,
         *        and not whitespace). This will generate an error.
         */
-<HASH>define{HSPACE}+ {
+<HASH>define{HSPACE}* {
        if (! parser->skipping) {
                BEGIN DEFINE;
                yyextra->space_tokens = 0;
@@ -513,9 +521,11 @@ HEXADECIMAL_INTEGER        0[xX][0-9a-fA-F]+[uU]?
 
        /* We preserve all newlines, even between #if 0..#endif, so no
        skipping.. */
-\n {
+<*>[\r\n] {
        if (parser->commented_newlines) {
                BEGIN NEWLINE_CATCHUP;
+       } else {
+               BEGIN INITIAL;
        }
        yyextra->space_tokens = 1;
        yyextra->lexing_directive = 0;
@@ -527,21 +537,28 @@ HEXADECIMAL_INTEGER       0[xX][0-9a-fA-F]+[uU]?
 <INITIAL,COMMENT,DEFINE,HASH><<EOF>> {
        if (YY_START == COMMENT)
                glcpp_error(yylloc, yyextra, "Unterminated comment");
-       if (YY_START == DEFINE)
-               glcpp_error(yylloc, yyextra, "#define without macro name");
        BEGIN DONE; /* Don't keep matching this rule forever. */
        yyextra->lexing_directive = 0;
        if (! parser->last_token_was_newline)
                RETURN_TOKEN (NEWLINE);
 }
 
+       /* This is a catch-all to avoid the annoying default flex action which
+        * matches any character and prints it. If any input ever matches this
+        * rule, then we have made a mistake above and need to fix one or more
+        * of the preceding patterns to match that input. */
+
+<*>. {
+       glcpp_error(yylloc, yyextra, "Internal compiler error: Unexpected character: %s", yytext);
+
        /* We don't actually use the UNREACHABLE start condition. We
-       only have this action here so that we can pretend to call some
+       only have this block here so that we can pretend to call some
        generated functions, (to avoid "defined but not used"
        warnings. */
-<UNREACHABLE>. {
-       unput('.');
-       yy_top_state(yyextra);
+        if (YY_START == UNREACHABLE) {
+               unput('.');
+               yy_top_state(yyextra);
+       }
 }
 
 %%