From 9f3d2c4e3dff3eb4f5820a034426056bf66b3015 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 20 May 2010 08:42:02 -0700 Subject: [PATCH] Add support for commas within parenthesized groups in function arguments. The specification says that commas within a parenthesized group, (that's not a function-like macro invocation), are passed through literally and not considered argument separators in any outer macro invocation. Add support and a test for this case. This support makes a third occurrence of the same "FUNC_MACRO (" shift/reduce conflict appear, so expect that. This change does introduce a fairly large copy/paste block in the grammar which is unfortunate. Perhaps if I were more clever I'd find a way to share the common pieces between argument and argument_or_comma. --- glcpp-parse.y | 44 +++++++++++++++++++++++++++++--- tests/038-func-arg-with-commas.c | 2 ++ 2 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 tests/038-func-arg-with-commas.c diff --git a/glcpp-parse.y b/glcpp-parse.y index 28e79ebf9f7..c9edc5c3040 100644 --- a/glcpp-parse.y +++ b/glcpp-parse.y @@ -119,8 +119,8 @@ glcpp_parser_lex (glcpp_parser_t *parser); %type FUNC_MACRO IDENTIFIER IDENTIFIER_FINALIZED OBJ_MACRO %type argument_list %type macro parameter_list -%type TOKEN argument_word -%type argument replacement_list pp_tokens +%type TOKEN argument_word argument_word_or_comma +%type argument argument_or_comma replacement_list pp_tokens /* Hard to remove shift/reduce conflicts documented as follows: * @@ -131,8 +131,10 @@ glcpp_parser_lex (glcpp_parser_t *parser); * 2. Similarly, '(' after FUNC_MACRO which is correctly resolved to * shift to form macro invocation rather than reducing directly to * argument. + * + * 3. Similarly again now that we added argument_or_comma as well. */ -%expect 2 +%expect 3 %% @@ -202,7 +204,7 @@ argument: talloc_free ($2.value); $$ = $1; } -| argument '(' argument ')' { +| argument '(' argument_or_comma ')' { _token_list_append ($1, '(', "("); _token_list_append_list ($1, $3); _token_list_append ($1, ')', ")"); @@ -218,6 +220,40 @@ argument_word: | macro { $$.type = TOKEN; $$.value = xtalloc_strdup (parser, ""); } ; + /* XXX: The body of argument_or_comma is the same as the body + * of argument, but with "argument" and "argument_word" + * changed to "argument_or_comma" and + * "argument_word_or_comma". It would be nice to have less + * redundancy here, but I'm not sure how. + * + * It would also be nice to have a less ugly grammar to have + * to implement, but such is the C preprocessor. + */ +argument_or_comma: + argument_word_or_comma { + $$ = _token_list_create (parser); + _token_list_append ($$, $1.type, $1.value); + } +| argument_or_comma argument_word_or_comma { + _token_list_append ($1, $2.type, $2.value); + $$ = $1; + } +| argument_or_comma '(' argument_or_comma ')' { + _token_list_append ($1, '(', "("); + _token_list_append_list ($1, $3); + _token_list_append ($1, ')', ")"); + $$ = $1; + } +; + +argument_word_or_comma: + IDENTIFIER { $$.type = IDENTIFIER; $$.value = $1; } +| IDENTIFIER_FINALIZED { $$.type = IDENTIFIER_FINALIZED; $$.value = $1; } +| TOKEN { $$ = $1; } +| FUNC_MACRO { $$.type = FUNC_MACRO; $$.value = $1; } +| macro { $$.type = TOKEN; $$.value = xtalloc_strdup (parser, ""); } +| ',' { $$.type = ','; $$.value = xtalloc_strdup (parser, ","); } +; directive: DEFINE IDENTIFIER NEWLINE { diff --git a/tests/038-func-arg-with-commas.c b/tests/038-func-arg-with-commas.c new file mode 100644 index 00000000000..1407c7d6e3c --- /dev/null +++ b/tests/038-func-arg-with-commas.c @@ -0,0 +1,2 @@ +#define foo(x) success +foo(argument (with,embedded , commas) -- tricky) -- 2.30.2