#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#include "glcpp.h"
#include "glcpp-parse.h"
+/* Flex annoyingly generates some functions without making them
+ * static. Let's declare them here. */
+int glcpp_get_column (yyscan_t yyscanner);
+void glcpp_set_column (int column_no , yyscan_t yyscanner);
+
+#ifdef _MSC_VER
+#define YY_NO_UNISTD_H
+#endif
+
+#define YY_NO_INPUT
+
#define YY_USER_ACTION \
do { \
- yylloc->source = 0; \
yylloc->first_column = yycolumn + 1; \
yylloc->first_line = yylineno; \
yycolumn += yyleng; \
} while(0);
+
+#define YY_USER_INIT \
+ do { \
+ yylineno = 1; \
+ yycolumn = 1; \
+ yylloc->source = 0; \
+ } while(0)
%}
%option bison-bridge bison-locations reentrant noyywrap
%option extra-type="glcpp_parser_t *"
%option prefix="glcpp_"
%option stack
+%option never-interactive
-%x DONE COMMENT
+%x DONE COMMENT UNREACHABLE SKIP
SPACE [[:space:]]
NONSPACE [^[:space:]]
PUNCTUATION [][(){}.&*~!/%<>^|;,=+-]
OTHER [^][(){}.&*~!/%<>^|;,=#[:space:]+-]+
+DIGITS [0-9][0-9]*
DECIMAL_INTEGER [1-9][0-9]*[uU]?
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;
+ } else {
+ BEGIN SKIP;
+ }
+ }
/* Single-line comments */
-"//"[^\n]*\n {
- yylineno++;
- yycolumn = 0;
- return NEWLINE;
+"//"[^\n]* {
}
/* Multi-line comments */
"/*" { yy_push_state(COMMENT, yyscanner); }
<COMMENT>[^*\n]*
-<COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; }
+<COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; return NEWLINE; }
<COMMENT>"*"+[^*/\n]*
-<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; }
+<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; return NEWLINE; }
<COMMENT>"*"+"/" {
yy_pop_state(yyscanner);
if (yyextra->space_tokens)
return SPACE;
}
+{HASH}version {
+ yylval->str = ralloc_strdup (yyextra, yytext);
+ yyextra->space_tokens = 0;
+ return HASH_VERSION;
+}
+
/* glcpp doesn't handle #extension, #version, or #pragma directives.
* Simply pass them through to the main compiler's lexer/parser. */
-{HASH}(extension|version|pragma)[^\n]+ {
- yylval->str = xtalloc_strdup (yyextra, yytext);
+{HASH}(extension|pragma)[^\n]+ {
+ yylval->str = ralloc_strdup (yyextra, yytext);
yylineno++;
yycolumn = 0;
return OTHER;
}
-{HASH}ifdef/.*\n {
+{HASH}line{HSPACE}+{DIGITS}{HSPACE}+{DIGITS}{HSPACE}*$ {
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+ yylloc->source = strtol(ptr, NULL, 0);
+}
+
+{HASH}line{HSPACE}+{DIGITS}{HSPACE}*$ {
+ /* Eat characters until the first digit is
+ * encountered
+ */
+ char *ptr = yytext;
+ while (!isdigit(*ptr))
+ ptr++;
+
+ /* Subtract one from the line number because
+ * yylineno is zero-based instead of
+ * one-based.
+ */
+ yylineno = strtol(ptr, &ptr, 0) - 1;
+}
+
+<SKIP,INITIAL>{
+{HASH}ifdef {
+ yyextra->lexing_if = 1;
yyextra->space_tokens = 0;
return HASH_IFDEF;
}
-{HASH}ifndef/.*\n {
+{HASH}ifndef {
+ yyextra->lexing_if = 1;
yyextra->space_tokens = 0;
return HASH_IFNDEF;
}
-{HASH}if{HSPACE}/.*\n {
+{HASH}if/[^_a-zA-Z0-9] {
yyextra->lexing_if = 1;
yyextra->space_tokens = 0;
return HASH_IF;
}
-{HASH}elif/.*\n {
+{HASH}elif {
yyextra->lexing_if = 1;
yyextra->space_tokens = 0;
return HASH_ELIF;
}
-{HASH}else/.*\n {
+{HASH}else {
yyextra->space_tokens = 0;
return HASH_ELSE;
}
-{HASH}endif/.*\n {
+{HASH}endif {
yyextra->space_tokens = 0;
return HASH_ENDIF;
}
+}
- /* When skipping (due to an #if 0 or similar) consume anything
- * up to a newline. We do this less priroty than any
- * #if-related directive (#if, #elif, #else, #endif), but with
- * more priority than any other directive or token to avoid
- * any side-effects from skipped content.
- *
- * We use the lexing_if flag to avoid skipping any part of an
- * if conditional expression. */
-[^\n]+/\n {
- /* Since this rule always matches, YY_USER_ACTION gets called for it,
- * wrongly incrementing yycolumn. We undo that effect here. */
- yycolumn -= yyleng;
- if (yyextra->lexing_if ||
- yyextra->skip_stack == NULL ||
- yyextra->skip_stack->type == SKIP_NO_SKIP)
- {
- REJECT;
- }
+<SKIP>[^\n] ;
+
+{HASH}error.* {
+ char *p;
+ for (p = yytext; !isalpha(p[0]); p++); /* skip " # " */
+ p += 5; /* skip "error" */
+ glcpp_error(yylloc, yyextra, "#error%s", p);
}
{HASH}define{HSPACE}+/{IDENTIFIER}"(" {
}
{DECIMAL_INTEGER} {
- yylval->str = xtalloc_strdup (yyextra, yytext);
+ yylval->str = ralloc_strdup (yyextra, yytext);
return INTEGER_STRING;
}
{OCTAL_INTEGER} {
- yylval->str = xtalloc_strdup (yyextra, yytext);
+ yylval->str = ralloc_strdup (yyextra, yytext);
return INTEGER_STRING;
}
{HEXADECIMAL_INTEGER} {
- yylval->str = xtalloc_strdup (yyextra, yytext);
+ yylval->str = ralloc_strdup (yyextra, yytext);
return INTEGER_STRING;
}
}
{IDENTIFIER} {
- yylval->str = xtalloc_strdup (yyextra, yytext);
+ yylval->str = ralloc_strdup (yyextra, yytext);
return IDENTIFIER;
}
}
{OTHER}+ {
- yylval->str = xtalloc_strdup (yyextra, yytext);
+ yylval->str = ralloc_strdup (yyextra, yytext);
return OTHER;
}
}
}
-\n {
+<SKIP,INITIAL>\n {
yyextra->lexing_if = 0;
yylineno++;
yycolumn = 0;
return NEWLINE;
}
+ /* We don't actually use the UNREACHABLE start condition. We
+ only have this action here so that we can pretend to call some
+ generated functions, (to avoid "defined but not used"
+ warnings. */
+<UNREACHABLE>. {
+ unput('.');
+ yy_top_state(yyextra);
+}
+
%%
void