preserve the indentation in the ouput

Preserve the actions' initial indentation.  For instance, on

    | %define api.value.type {int}
    | %%
    | exp: exp '/' exp { if ($3)
    |                     $$ = $1 + $3;
    |                   else
    |                     $$ = 0; }

we used to generate

    |     { if (yyvsp[0])
    |                     yyval = yyvsp[-2] + yyvsp[0];
    |                   else
    |                    yyval = 0; }

now we produce

    |                  { if (yyvsp[0])
    |                     yyval = yyvsp[-2] + yyvsp[0];
    |                   else
    |                     yyval = 0; }

See https://lists.gnu.org/archive/html/bison-patches/2019-06/msg00012.html.

* data/skeletons/bison.m4 (b4_symbol_action): Output the code in
column 0, leave indentation matters to the C code.
* src/output.c (user_actions_output): Preserve the incoming
indentation in the output.
(prepare_symbol_definitions): Likewise for %printer/%destructor.
* tests/synclines.at (Output columns): New.
This commit is contained in:
Akim Demaille
2019-06-09 09:11:54 +02:00
parent 13577a809e
commit 1161649446
3 changed files with 84 additions and 9 deletions

View File

@@ -359,9 +359,9 @@ symbol_numbers_output (FILE *out)
}
/*---------------------------------.
| Output the user actions to OUT. |
`---------------------------------*/
/*-------------------------------------------.
| Output the user reduction actions to OUT. |
`-------------------------------------------*/
static void
user_actions_output (FILE *out)
@@ -370,11 +370,19 @@ user_actions_output (FILE *out)
for (rule_number r = 0; r < nrules; ++r)
if (rules[r].action)
{
fprintf (out, "%s(%d, [b4_syncline(%d, ",
fprintf (out, "%s(%d, [",
rules[r].is_predicate ? "b4_predicate_case" : "b4_case",
r + 1, rules[r].action_loc.start.line);
r + 1);
if (!no_lines_flag)
{
fprintf (out, "b4_syncline(%d, ",
rules[r].action_loc.start.line);
string_output (out, rules[r].action_loc.start.file);
fprintf (out, ")dnl\n[ %s]])\n\n", rules[r].action);
fprintf (out, ")dnl\n");
}
fprintf (out, "[%*s%s]])\n\n",
rules[r].action_loc.start.column - 1, "",
rules[r].action);
}
fputs ("])\n\n", out);
}
@@ -482,7 +490,9 @@ prepare_symbol_definitions (void)
muscle_location_grow (key, p->location);
SET_KEY (pname);
MUSCLE_INSERT_STRING_RAW (key, p->code);
obstack_printf (&muscle_obstack,
"%*s%s", p->location.start.column - 1, "", p->code);
muscle_insert (key, obstack_finish0 (&muscle_obstack));
}
}
#undef SET_KEY2

View File

@@ -497,3 +497,68 @@ AT_CLEANUP
m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc])
m4_popdef([AT_TEST])
## ---------------- ##
## Output columns. ##
## ---------------- ##
AT_SETUP([Output columns])
# This test is fragile: its point is to check the compiler's error
# message, but it seems too hard to do portability (even between
# version of GCC). So instead, let's just check the generated code
# itself.
AT_BISON_OPTION_PUSHDEFS
AT_DATA([input.y],
[[%{
]AT_YYERROR_DECLARE_EXTERN[
]AT_YYLEX_DECLARE_EXTERN[
%}
%define api.value.type union
%type <int> '0' exp
%destructor { /* --BEGIN */
destructor
/* --END */ } <*>
%printer { /* --BEGIN */
printer
/* --END */ } <*>
%left '+'
%%
exp: exp '+' exp { /* --BEGIN */
$$ = $1 + $3;
@$ = @1 + @3;
/* --END */ }
| '0'
]])
AT_BISON_CHECK([-o input.c input.y])
AT_CHECK([[sed -ne '/--BEGIN/,/--END/{' \
-e '/input.c/s/ [0-9]* / LINE /;' \
-e 'p;}' \
input.c]], 0,
[[ { /* --BEGIN */
printer
/* --END */ }
{ /* --BEGIN */
printer
/* --END */ }
{ /* --BEGIN */
destructor
/* --END */ }
{ /* --BEGIN */
destructor
/* --END */ }
{ /* --BEGIN */
(yyval.exp) = (yyvsp[-2].exp) + (yyvsp[0].exp);
(yyloc) = (yylsp[-2]) + (yylsp[0]);
/* --END */ }
]])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP