Fix parsing of object-like macro with a definition that begins with '('.

Previously our parser was incorrectly treating this case as a
function-like macro. We fix this by conditionally passing a SPACE
token from the lexer, (but only immediately after the identifier
immediately after #define).
This commit is contained in:
Carl Worth 2010-05-13 10:29:07 -07:00
parent 67c27afc16
commit 0a93cbbe4f
2 changed files with 60 additions and 17 deletions

View file

@ -32,6 +32,9 @@
%option reentrant noyywrap
%option extra-type="glcpp_parser_t *"
%x ST_DEFINE
%x ST_DEFVAL
SPACE [[:space:]]
NONSPACE [^[:space:]]
NEWLINE [\n]
@ -42,16 +45,42 @@ TOKEN [^[:space:](),]+
%%
{HASH}define{HSPACE}* {
return DEFINE;
}
{HASH}undef{HSPACE}* {
{HASH}undef{HSPACE}* {
return UNDEF;
}
/* We use the ST_DEFINE and ST_DEFVAL states so that we can
* pass a space token, (yes, a token for whitespace!), since
* the preprocessor specification requires distinguishing
* "#define foo()" from "#define foo ()".
*/
{HASH}define{HSPACE}* {
BEGIN ST_DEFINE;
return DEFINE;
}
{IDENTIFIER} {
<ST_DEFINE>{IDENTIFIER} {
BEGIN ST_DEFVAL;
yylval.str = xtalloc_strdup (yyextra, yytext);
return IDENTIFIER;
}
<ST_DEFVAL>\n {
BEGIN INITIAL;
return NEWLINE;
}
<ST_DEFVAL>{HSPACE}+ {
BEGIN INITIAL;
return SPACE;
}
<ST_DEFVAL>"(" {
BEGIN INITIAL;
return '(';
}
{IDENTIFIER} {
yylval.str = xtalloc_strdup (yyextra, yytext);
switch (glcpp_parser_macro_type (yyextra, yylval.str))
{
@ -67,7 +96,9 @@ TOKEN [^[:space:](),]+
}
}
[(),] { return yytext[0]; }
[(),] {
return yytext[0];
}
{TOKEN} {
yylval.str = xtalloc_strdup (yyextra, yytext);

View file

@ -83,8 +83,8 @@ _list_append_list (list_t *list, list_t *tail);
%parse-param {glcpp_parser_t *parser}
%lex-param {void *scanner}
%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO TOKEN UNDEF
%type <str> FUNC_MACRO IDENTIFIER OBJ_MACRO TOKEN string
%token DEFINE FUNC_MACRO IDENTIFIER NEWLINE OBJ_MACRO SPACE TOKEN UNDEF
%type <str> FUNC_MACRO IDENTIFIER OBJ_MACRO TOKEN word word_or_symbol
%type <list> argument argument_list parameter_list replacement_list
%%
@ -105,9 +105,10 @@ content:
}
| macro
| directive_with_newline
| NEWLINE {
printf ("\n");
}
| NEWLINE { printf ("\n"); }
| '(' { printf ("("); }
| ')' { printf (")"); }
| ',' { printf (","); }
;
macro:
@ -135,7 +136,7 @@ argument:
/* empty */ {
$$ = _list_create (parser);
}
| argument string {
| argument word {
_list_append_item ($1, $2);
talloc_free ($2);
}
@ -149,8 +150,12 @@ directive_with_newline:
;
directive:
DEFINE IDENTIFIER replacement_list {
_define_object_macro (parser, $2, $3);
DEFINE IDENTIFIER {
list_t *list = _list_create (parser);
_define_object_macro (parser, $2, list);
}
| DEFINE IDENTIFIER SPACE replacement_list {
_define_object_macro (parser, $2, $4);
}
| DEFINE IDENTIFIER '(' parameter_list ')' replacement_list {
_define_function_macro (parser, $2, $4, $6);
@ -183,7 +188,7 @@ replacement_list:
/* empty */ {
$$ = _list_create (parser);
}
| replacement_list string {
| replacement_list word_or_symbol {
_list_append_item ($1, $2);
talloc_free ($2);
$$ = $1;
@ -206,7 +211,14 @@ parameter_list:
}
;
string:
word_or_symbol:
word { $$ = $1; }
| '(' { $$ = xtalloc_strdup (parser, "("); }
| ')' { $$ = xtalloc_strdup (parser, ")"); }
| ',' { $$ = xtalloc_strdup (parser, ","); }
;
word:
IDENTIFIER { $$ = $1; }
| FUNC_MACRO { $$ = $1; }
| OBJ_MACRO { $$ = $1; }