graphs: style: use left justification for states

The label text of nodes is centered "by default" (by the use of '\n' as
a line feed). This gives bad readability to the grammar rules shown in
state nodes, a left justification is much nicer. This is done by using '\l'
as the line feed.

In order to allow \l in the DOT file, changes to the quoting system seem
necessary.

* src/print_graph.c (print_core): Escape tokens here, instead of...
* src/graphviz.c (output_node): Here...
(escape): Using this, new.

Signed-off-by: Akim Demaille <akim@lrde.epita.fr>
This commit is contained in:
Theophile Ranquet
2012-10-08 15:53:44 +00:00
committed by Akim Demaille
parent 2be37f19fe
commit a13121f759
3 changed files with 42 additions and 27 deletions

View File

@@ -30,7 +30,7 @@
/* Return an unambiguous printable representation for NAME, suitable /* Return an unambiguous printable representation for NAME, suitable
for C strings. Use slot 2 since the user may use slots 0 and 1. */ for C strings. Use slot 2 since the user may use slots 0 and 1. */
static char const * static char *
quote (char const *name) quote (char const *name)
{ {
return quotearg_n_style (2, c_quoting_style, name); return quotearg_n_style (2, c_quoting_style, name);
@@ -57,12 +57,12 @@ start_graph (FILE *fout)
void void
output_node (int id, char const *label, FILE *fout) output_node (int id, char const *label, FILE *fout)
{ {
fprintf (fout, " %d [label=%s]\n", id, quote (label)); fprintf (fout, " %d [label=\"%s\"]\n", id, label);
} }
void void
output_edge (int source, int destination, char const *label, output_edge (int source, int destination, char const *label,
char const *style, FILE *fout) char const *style, FILE *fout)
{ {
fprintf (fout, " %d -> %d [style=%s", source, destination, style); fprintf (fout, " %d -> %d [style=%s", source, destination, style);
if (label) if (label)
@@ -70,6 +70,14 @@ output_edge (int source, int destination, char const *label,
fputs ("]\n", fout); fputs ("]\n", fout);
} }
char const *
escape (char const *name)
{
char *q = quote (name);
q[strlen (q) - 1] = '\0';
return q + 1;
}
void void
finish_graph (FILE *fout) finish_graph (FILE *fout)
{ {

View File

@@ -46,4 +46,8 @@ void output_edge (int source, int destination, char const *label,
/// \param fout output stream. /// \param fout output stream.
void finish_graph (FILE *fout); void finish_graph (FILE *fout);
/// Escape a lookahead token.
/// \param name the token.
char const *escape (char const *name);
#endif /* ! GRAPHVIZ_H_ */ #endif /* ! GRAPHVIZ_H_ */

View File

@@ -18,6 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h> #include <config.h>
#include <quotearg.h>
#include "system.h" #include "system.h"
#include "LR0.h" #include "LR0.h"
@@ -54,7 +55,7 @@ print_core (struct obstack *oout, state *s)
snritems = nitemset; snritems = nitemset;
} }
obstack_printf (oout, "%d", s->number); obstack_printf (oout, "%d\\n", s->number);
for (i = 0; i < snritems; i++) for (i = 0; i < snritems; i++)
{ {
item_number *sp; item_number *sp;
@@ -64,43 +65,45 @@ print_core (struct obstack *oout, state *s)
sp1 = sp = ritem + sitems[i]; sp1 = sp = ritem + sitems[i];
while (*sp >= 0) while (*sp >= 0)
sp++; sp++;
r = item_number_as_rule_number (*sp); r = item_number_as_rule_number (*sp);
obstack_printf (oout, "\n%d: %s -> ", r, rules[r].lhs->tag); obstack_printf (oout, "%d: %s -> ", r, escape (rules[r].lhs->tag));
for (sp = rules[r].rhs; sp < sp1; sp++) for (sp = rules[r].rhs; sp < sp1; sp++)
obstack_printf (oout, "%s ", symbols[*sp]->tag); obstack_printf (oout, "%s ", escape (symbols[*sp]->tag));
obstack_1grow (oout, '.'); obstack_1grow (oout, '.');
for (/* Nothing */; *sp >= 0; ++sp) for (/* Nothing */; *sp >= 0; ++sp)
obstack_printf (oout, " %s", symbols[*sp]->tag); obstack_printf (oout, " %s", escape (symbols[*sp]->tag));
/* Experimental feature: display the lookahead tokens. */ /* Experimental feature: display the lookahead tokens. */
if (report_flag & report_lookahead_tokens if (report_flag & report_lookahead_tokens
&& item_number_is_rule_number (*sp1)) && item_number_is_rule_number (*sp1))
{ {
/* Find the reduction we are handling. */ /* Find the reduction we are handling. */
reductions *reds = s->reductions; reductions *reds = s->reductions;
int redno = state_reduction_find (s, &rules[r]); int redno = state_reduction_find (s, &rules[r]);
/* Print them if there are. */ /* Print them if there are. */
if (reds->lookahead_tokens && redno != -1) if (reds->lookahead_tokens && redno != -1)
{ {
bitset_iterator biter; bitset_iterator biter;
int k; int k;
char const *sep = ""; char const *sep = "";
obstack_sgrow (oout, "["); obstack_1grow (oout, '[');
BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0) BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0)
{ {
obstack_printf (oout, "%s%s", sep, symbols[k]->tag); obstack_sgrow (oout, sep);
sep = ", "; obstack_sgrow (oout, escape (symbols[k]->tag));
} sep = ", ";
obstack_sgrow (oout, "]"); }
} obstack_1grow (oout, ']');
} }
}
obstack_sgrow (oout, "\\l");
} }
} }