diff options
Diffstat (limited to 'mesalib/src/glsl/glcpp/glcpp-lex.l')
-rw-r--r-- | mesalib/src/glsl/glcpp/glcpp-lex.l | 79 |
1 files changed, 69 insertions, 10 deletions
diff --git a/mesalib/src/glsl/glcpp/glcpp-lex.l b/mesalib/src/glsl/glcpp/glcpp-lex.l index a029f6203..f1fa192c5 100644 --- a/mesalib/src/glsl/glcpp/glcpp-lex.l +++ b/mesalib/src/glsl/glcpp/glcpp-lex.l @@ -67,7 +67,7 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner); %option stack %option never-interactive -%x DONE COMMENT UNREACHABLE SKIP DEFINE +%x DONE COMMENT UNREACHABLE SKIP DEFINE NEWLINE_CATCHUP SPACE [[:space:]] NONSPACE [^[:space:]] @@ -92,13 +92,62 @@ OCTAL_INTEGER 0[0-7]*[uU]? HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? %% - /* Implicitly switch between SKIP and INITIAL (non-skipping); - * don't switch if some other state was explicitly set. - */ + glcpp_parser_t *parser = yyextra; - if (YY_START == 0 || YY_START == SKIP) { - if (parser->lexing_if || parser->skip_stack == NULL || parser->skip_stack->type == SKIP_NO_SKIP) { - BEGIN 0; + + /* When we lex a multi-line comment, we replace it (as + * specified) with a single space. But if the comment spanned + * multiple lines, then subsequent parsing stages will not + * count correct line numbers. To avoid this problem we keep + * track of all newlines that were commented out by a + * multi-line comment, and we emit a NEWLINE token for each at + * the next legal opportunity, (which is when the lexer would + * be emitting a NEWLINE token anyway). + */ + if (YY_START == NEWLINE_CATCHUP) { + if (parser->commented_newlines) + parser->commented_newlines--; + if (parser->commented_newlines == 0) + BEGIN INITIAL; + return NEWLINE; + } + + /* The handling of the SKIP vs INITIAL start states requires + * some special handling. Typically, a lexer would change + * start states with statements like "BEGIN SKIP" within the + * lexer rules. We can't get away with that here, since we + * need the parser to actually evaluate expressions for + * directives like "#if". + * + * So, here, in code that will be executed on every call to + * the lexer,and before any rules, we examine the skip_stack + * as set by the parser to know whether to change from INITIAL + * to SKIP or from SKIP back to INITIAL. + * + * Three cases cause us to switch out of the SKIP state and + * back to the INITIAL state: + * + * 1. The top of the skip_stack is of type SKIP_NO_SKIP + * This means we're still evaluating some #if + * hierarchy, but we're on a branch of it where + * content should not be skipped (such as "#if 1" or + * "#else" or so). + * + * 2. The skip_stack is NULL meaning that we've reached + * the last #endif. + * + * 3. The lexing_if bit is set. This indicates that we + * are lexing the expression following an "#if" of + * "#elif". Even inside an "#if 0" we need to lex this + * expression so the parser can correctly update the + * skip_stack state. + */ + if (YY_START == INITIAL || YY_START == SKIP) { + if (parser->lexing_if || + parser->skip_stack == NULL || + parser->skip_stack->type == SKIP_NO_SKIP) + { + BEGIN INITIAL; } else { BEGIN SKIP; } @@ -106,14 +155,16 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? /* Single-line comments */ "//"[^\n]* { + if (parser->commented_newlines) + BEGIN NEWLINE_CATCHUP; } /* Multi-line comments */ "/*" { yy_push_state(COMMENT, yyscanner); } <COMMENT>[^*\n]* -<COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; return NEWLINE; } +<COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; parser->commented_newlines++; } <COMMENT>"*"+[^*/\n]* -<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; return NEWLINE; } +<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; parser->commented_newlines++; } <COMMENT>"*"+"/" { yy_pop_state(yyscanner); if (yyextra->space_tokens) @@ -129,6 +180,8 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? /* glcpp doesn't handle #extension, #version, or #pragma directives. * Simply pass them through to the main compiler's lexer/parser. */ {HASH}(extension|pragma)[^\n]+ { + if (parser->commented_newlines) + BEGIN NEWLINE_CATCHUP; yylval->str = ralloc_strdup (yyextra, yytext); yylineno++; yycolumn = 0; @@ -175,7 +228,10 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? } } -<SKIP>[^\n] ; +<SKIP>[^\n] { + if (parser->commented_newlines) + BEGIN NEWLINE_CATCHUP; +} {HASH}error.* { char *p; @@ -290,6 +346,9 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]? } <SKIP,INITIAL>\n { + if (parser->commented_newlines) { + BEGIN NEWLINE_CATCHUP; + } yyextra->lexing_if = 0; yylineno++; yycolumn = 0; |