%option reentrant noyywrap
%option extra-type="glcpp_parser_t *"
+ /* This lexer has two states:
+ *
+ * The CONTROL state is for control lines (directives)
+ * It lexes exactly as specified in the C99 specification.
+ *
+ * The INITIAL state is for input lines. In this state, we
+ * make the OTHER token much more broad in that it now
+ * includes tokens consisting entirely of whitespace. This
+ * allows us to pass text through verbatim. It avoids the
+ * "inadvertent token pasting" problem that would occur if we
+ * just printed tokens, while also avoiding excess whitespace
+ * insertion in the output.*/
+
+%x CONTROL
+
SPACE [[:space:]]
NONSPACE [^[:space:]]
NEWLINE [\n]
%%
{HASH}define{HSPACE}+/{IDENTIFIER}"(" {
+ BEGIN CONTROL;
return HASH_DEFINE_FUNC;
}
{HASH}define {
+ BEGIN CONTROL;
return HASH_DEFINE_OBJ;
}
{HASH}undef {
+ BEGIN CONTROL;
return HASH_UNDEF;
}
{HASH} {
+ BEGIN CONTROL;
return HASH;
}
-{IDENTIFIER} {
+<CONTROL>{IDENTIFIER} {
yylval.str = xtalloc_strdup (yyextra, yytext);
return IDENTIFIER;
}
-"<<" {
+<CONTROL>"<<" {
return LEFT_SHIFT;
}
-">>" {
+<CONTROL>">>" {
return RIGHT_SHIFT;
}
-"<=" {
+<CONTROL>"<=" {
return LESS_OR_EQUAL;
}
-">=" {
+<CONTROL>">=" {
return GREATER_OR_EQUAL;
}
-"==" {
+<CONTROL>"==" {
return EQUAL;
}
-"!=" {
+<CONTROL>"!=" {
return NOT_EQUAL;
}
-"&&" {
+<CONTROL>"&&" {
return AND;
}
-"||" {
+<CONTROL>"||" {
return OR;
}
-"##" {
+<CONTROL>"##" {
return PASTE;
}
-{PUNCTUATION} {
+<CONTROL>{PUNCTUATION} {
return yytext[0];
}
-\n {
+<CONTROL>{OTHER} {
+ yylval.str = xtalloc_strdup (yyextra, yytext);
+ return OTHER;
+}
+
+<CONTROL>{HSPACE}+
+
+<CONTROL>\n {
+ BEGIN INITIAL;
return NEWLINE;
}
-{OTHER} {
+{IDENTIFIER} {
+ yylval.str = xtalloc_strdup (yyextra, yytext);
+ return IDENTIFIER;
+}
+
+{OTHER}+ {
+ yylval.str = xtalloc_strdup (yyextra, yytext);
+ return OTHER;
+}
+
+{HSPACE}+ {
yylval.str = xtalloc_strdup (yyextra, yytext);
return OTHER;
}
-{HSPACE}+
+\n {
+ return NEWLINE;
+}
+
+. {
+ yylval.str = xtalloc_strdup (yyextra, yytext);
+ return OTHER;
+}
%%
gcc -E $test -o $test.gcc
# grep -v '^#' < $test.gcc > $test.expected
grep -v '^[ ]*#' < $test > $test.expected
- diff -w -u $test.expected $test.out
+ diff -u $test.expected $test.out
done