How to align ports of HTML cells?

I have the following graph:

digraph grammar
{ compound=true; rankdir="LR";
  r0 [label="S"];
  r0p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">S</td><td>+</td><td>S</td></tr></table>>];
  r0 -> r0p:p [dir=back];
  r1 [label="S"];
  r1p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">S</td><td>-</td><td>S</td></tr></table>>];
  r1 -> r1p:p [dir=back];
  r2 [label="S"];
  r2p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">(</td><td>S</td><td>)</td></tr></table>>];
  r2 -> r2p:p [dir=back];
  r3 [label="S"];
  r3p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">a</td></tr></table>>];
  r3 -> r3p:p [dir=back];
  r0 -> r1 -> r2 -> r3 [style=invis];
  {rank=same; r0; r1; r2; r3;}
  {rank=same; r0p:p; r1p:p; r2p:p; r3p:p;}
}

It gets rendered this way:
grammar

I tried to align every first port of every HTML table, but it does not work. But I do not get an error either.

Is it possible to change the edges so that they are horizontal, straight and have all the same length?

I’m sorry, this looks like a layout bug or feature not working as expected. I don’t believe there is an easy workaround. (The problems involves some subtlety in HTML tables and associated ports; I think the relationship between ports and cellpadding is misinterpreted in LR mode - try cellpadding=“20” to increase the effect.

Indeed fiddley.
Two parts to this solution:

  • add two invisible cells (color=white) to the shorter table. Kludgey, but effective.
  • Then changed the ranking to TB to get the nodes to align horizontally. Not strictly necessary, but otherwise you have to fiddle with node sizes.
digraph grammar
{
  compound=true;
  //  rankdir="LR";    // change to TB ranking

  // the file has been somewhat rearranged, just for my brain
  ranksep=.25
  nodesep=.6
  
  r0 [label="S"]
  r1 [label="S"]
  r3 [label="S"]
  r2 [label="S"]

  r0p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">S</td><td>+</td><td>S</td></tr></table>>];
  r0 -> r0p:p [dir=back];
 
  r1p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">S</td><td>-</td><td>S</td></tr></table>>];
  r1 -> r1p:p [dir=back];
  
  r2p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">(</td><td>S</td><td>)</td></tr></table>>];
  r2 -> r2p:p [dir=back];

  // add two invisible cells (color=white)
  r3p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">a</td><td color="white"> </td><td color="white"> </td></tr></table>>];
  r3 -> r3p:p [dir=back];

  r0 -> r1 -> r2 -> r3 [style=invis];

  // redo ranking
  {rank=same; r0; r0p:p}
  {rank=same; r1; r1p:p}
  {rank=same; r2; r2p:p}
  {rank=same; r3; r3p:p}
}

Giving:
fixAlignment2

1 Like

If I change the direction from LR to TB it seems to work even without the empty cells.

digraph grammar
{ rankdir="TB"; ranksep=.1; nodesep=.6;
  r0 [label="S"];
  r0p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">S</td><td>"+"</td><td>S</td></tr></table>>];
  r0 -> r0p:p [dir=back];
  r1 [label="S"];
  r1p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">S</td><td>"-"</td><td>S</td></tr></table>>];
  r1 -> r1p:p [dir=back];
  r2 [label="S"];
  r2p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">"("</td><td>S</td><td>")"</td></tr></table>>];
  r2 -> r2p:p [dir=back];
  r3 [label="S"];
  r3p [shape=plaintext;label=<<table border="0" cellspacing="5" cellpadding="5" cellborder="1"><tr><td port="p">"a"</td></tr></table>>];
  r3 -> r3p:p [dir=back];
  r0 -> r1 -> r2 -> r3 [style=invis];
  {rank=same; r0; r0p}
  {rank=same; r1; r1p}
  {rank=same; r2; r2p}
  {rank=same; r3; r3p}
}

grammar