%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;
+ yyextra->space_tokens = 0;
return HASH_DEFINE_FUNC;
}
{HASH}define {
- BEGIN CONTROL;
+ yyextra->space_tokens = 0;
return HASH_DEFINE_OBJ;
}
{HASH}undef {
- BEGIN CONTROL;
+ yyextra->space_tokens = 0;
return HASH_UNDEF;
}
{HASH} {
- BEGIN CONTROL;
+ yyextra->space_tokens = 0;
return HASH;
}
-<CONTROL>{IDENTIFIER} {
+{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;
}
-<CONTROL>{PUNCTUATION} {
+{PUNCTUATION} {
return yytext[0];
}
-<CONTROL>{OTHER} {
- yylval.str = xtalloc_strdup (yyextra, yytext);
- return OTHER;
-}
-
-<CONTROL>{HSPACE}+
-
-<CONTROL>\n {
- BEGIN INITIAL;
- return NEWLINE;
-}
-
-{IDENTIFIER} {
- yylval.str = xtalloc_strdup (yyextra, yytext);
- return IDENTIFIER;
-}
-
-"(" {
- return '(';
-}
-
-")" {
- return ')';
-}
-
-"," {
- return ',';
-}
-
{OTHER}+ {
yylval.str = xtalloc_strdup (yyextra, yytext);
return OTHER;
}
{HSPACE}+ {
- yylval.str = xtalloc_strdup (yyextra, yytext);
- return SPACE;
+ if (yyextra->space_tokens) {
+ yylval.str = xtalloc_strdup (yyextra, yytext);
+ return SPACE;
+ }
}
\n {
return NEWLINE;
}
-. {
- yylval.str = xtalloc_strdup (yyextra, yytext);
- return OTHER;
-}
-
%%
;
control_line:
- HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
+ HASH_DEFINE_OBJ IDENTIFIER replacement_list NEWLINE {
_define_object_macro (parser, $2, $3);
}
| HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE {
pp_tokens:
preprocessing_token {
+ parser->space_tokens = 1;
$$ = _token_list_create (parser);
_token_list_append ($$, $1);
talloc_unlink (parser, $1);
$$ = _token_create_str (parser, OTHER, $1);
}
| SPACE {
- $$ = _token_create_str (parser, OTHER, $1);
+ $$ = _token_create_str (parser, SPACE, $1);
}
;
switch (token->type) {
case IDENTIFIER:
case OTHER:
+ case SPACE:
printf ("%s", token->value.str);
break;
case LEFT_SHIFT:
parser->defines = hash_table_ctor (32, hash_table_string_hash,
hash_table_string_compare);
parser->active = _string_list_create (parser);
+ parser->space_tokens = 1;
parser->expansions = NULL;
parser->just_printed_separator = 1;
for (node = list->head; node; node = node->next) {
if (_glcpp_parser_print_expanded_token (parser, node->token))
_glcpp_parser_print_expanded_function (parser, &node);
-
- if (node->next)
- printf (" ");
}
}