4

I'd like to draw a diagram like this.

enter image description here

I thought and searched for a long time and I can only generate the picture below.

enter image description here

digraph G {
    node [shape=plaintext]
//    newrank=true;

    subgraph part1 {
        {rank=same state0, state9, state6}
        subgraph nest1 {
            state0 [label=<
                    <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
                    <TR><TD PORT="title" bgcolor="yellow">0</TD></TR>
                    <TR><TD PORT="text1" bgcolor="red">S&rarr; ・E$</TD></TR>
                    <TR><TD PORT="text2" bgcolor="green">E&rarr; ・E+T <br/> E&rarr;・T </TD></TR>
                    <TR><TD PORT="text3" bgcolor="green">T&rarr; ・id <br/> T&rarr;・(E)</TD></TR>
                    </TABLE>>];
        }

        subgraph nest2 {
            state6 [label=<
                    <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
                    <TR><TD PORT="title" bgcolor="yellow">6</TD></TR>
                    <TR><TD PORT="text1" bgcolor="red">T&rarr;(・E) </TD></TR>
                    <TR><TD PORT="text2" bgcolor="green">E&rarr; ・E+T <br/> E&rarr;・T </TD></TR>
                    <TR><TD PORT="text3" bgcolor="green">T&rarr; ・id <br/> T&rarr;・(E)</TD></TR>
                    </TABLE>>];
        }

        subgraph nest3 {
            state9 [label=<
                    <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
                    <TR><TD PORT="title" bgcolor="yellow">9</TD></TR>
                    <TR><TD PORT="text" bgcolor="red">E&rarr;T・ </TD></TR>
                    </TABLE>>];

            state5 [label=<
                    <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
                    <TR><TD PORT="title" bgcolor="yellow">5</TD></TR>
                    <TR><TD PORT="text" bgcolor="red">T&rarr;id・ </TD></TR>
                    </TABLE>>];
        }

//        {rank=same; nest1; nest2; nest3;}
//        nest1 -> nest2 -> nest3 [style=invis]
    }

    subgraph part2 {
        {rank=same state1, state3, state7}
        state1 [label=<
                <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
                <TR><TD PORT="title" bgcolor="yellow">1</TD></TR>
                <TR><TD PORT="text" bgcolor="red">S&rarr;E・$<br/>E&rarr;E・+T</TD></TR>
                </TABLE>>];

        state7 [label=<
                <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
                <TR><TD PORT="title" bgcolor="yellow">7</TD></TR>
                <TR><TD PORT="text1" bgcolor="red">T&rarr;(E・) </TD></TR>
                <TR><TD PORT="text2" bgcolor="green">E&rarr; E・+T</TD></TR>
                </TABLE>>];

        state3 [label=<
                <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
                <TR><TD PORT="title" bgcolor="yellow">3</TD></TR>
                <TR><TD PORT="text1" bgcolor="red">E&rarr;E+・T </TD></TR>
                <TR><TD PORT="text2" bgcolor="green">T&rarr;・id <br/> T&rarr;・(E) </TD></TR>
                </TABLE>>];
    }

    subgraph part3 {
        {rank=same state2, state4, state8}

        state2 [label=<
                <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
                <TR><TD PORT="title" bgcolor="yellow">2</TD></TR>
                <TR><TD PORT="text" bgcolor="red">S&rarr;E$・ </TD></TR>
                </TABLE>>];

        state8 [label=<
                <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
                <TR><TD PORT="title" bgcolor="yellow">8</TD></TR>
                <TR><TD PORT="text" bgcolor="red">T&rarr;(E)・ </TD></TR>
                </TABLE>>];

        state4 [label=<
                <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
                <TR><TD PORT="title" bgcolor="yellow">4</TD></TR>
                <TR><TD PORT="text" bgcolor="red">E&rarr;E+T・ </TD></TR>
                </TABLE>>];
    }

//    state0:s -> state1:n [label="E"]
//    state0:title:e -> state9:title:w [label="T"]
//    state0:text3:e -> state5:text:w [label="id"]
//    state0:text2:e -> state6:text2:w [label="("]

    state0:s -> state1:n [label="E"]
    state0 -> state9 [label="T"]
    state0 -> state5 [label="id"]
    state0 -> state6 [label="(", weight=100]

    state1:s -> state2:n [label="$"]
    state1:title:e -> state3:title:w [label="+"]

    state3:s -> state4:n [label="T"]
    state3:n -> state5:s [label="id"]
//    state3:title:e -> state6:s [label="("]
    state3:title:e -> state6 [label="("]

//    state6:text3:w -> state5:text:e [label="id"]
//    state6:s -> state7:n [label="E"]
//    state6:title:w -> state9:title:e [label="T"]
//    state6:title:n -> state6:e [label="("]

    state6:s -> state7:n [label="E"]
    state6 -> state9 [label="T"]
    state6 -> state5 [label="id"]
    state6 -> state6 [label="("]

    state7:text2:w -> state3:text2:e [label="+"]
    state7:s -> state8:n [label=")"]

    // ------------ Invisible edges to order vertically node groups
    state9:s -> state5:n [style=invis]
    state5:s -> state3:n [style=invis]
    state3:s -> state4:n [style=invis]

    state6:s -> state7:n [style=invis]
    state7:s -> state8:n [style=invis]
    // ---------------------------------------------------

    // below two lines make sure the order 1 3 7 | 2 4 8 is right
    state1 -> state3 -> state7 [style=invis]
    state2 -> state4 -> state8 [style=invis]

    state0:text1:e -> state9:text1:w [style=invis]
    state9:text1:e -> state6:text1:w [style=invis]
}

I want to adjust the 0 9 5 6 part. This means I need to rank same 0 9/5 6, I have tried using subgraph, but it doesn't solve the problem.

Is there any way to align two nodes horizontally and keep them top/bottom align like HTML image?

enter image description here


tk421 memtions neato in his answer, see How to force node position (x and y) in graphviz for more detail.

Ynjxsjmh
  • 28,441
  • 6
  • 34
  • 52

1 Answers1

2

A couple fixes you can apply. splines=ortho will change the edges to vertical and horizontal lines. When you do this, the edge labels have to be redone as xlabel= instead of label=.

enter image description here

However, the 9 and 5 are not placed properly. If you use neato instead of dot, you can position the nodes exactly where you want. Then you can remove all the subgraph and invisible nodes and weight and do this:

enter image description here

The graphviz code would be:

digraph G {
    splines=ortho;
    node [shape=plaintext]

    state0 [label=<
            <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD PORT="title" bgcolor="yellow">0</TD></TR>
            <TR><TD PORT="text1" bgcolor="red">S&rarr; ・E$</TD></TR>
            <TR><TD PORT="text2" bgcolor="green">E&rarr; ・E+T <br/> E&rarr;・T </TD></TR>
            <TR><TD PORT="text3" bgcolor="green">T&rarr; ・id <br/> T&rarr;・(E)</TD></TR>
            </TABLE>>, pos="0,4!"];

    state6 [label=<
            <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD PORT="title" bgcolor="yellow">6</TD></TR>
            <TR><TD PORT="text1" bgcolor="red">T&rarr;(・E) </TD></TR>
            <TR><TD PORT="text2" bgcolor="green">E&rarr; ・E+T <br/> E&rarr;・T </TD></TR>
            <TR><TD PORT="text3" bgcolor="green">T&rarr; ・id <br/> T&rarr;・(E)</TD></TR>
            </TABLE>>, pos="4,4!"];

    state9 [label=<
            <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD PORT="title" bgcolor="yellow">9</TD></TR>
            <TR><TD PORT="text" bgcolor="red">E&rarr;T・ </TD></TR>
            </TABLE>>, pos="2,4.7!"];

    state5 [label=<
            <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD PORT="title" bgcolor="yellow">5</TD></TR>
            <TR><TD PORT="text" bgcolor="red">T&rarr;id・ </TD></TR>
            </TABLE>>, pos="2,3.3!"];

    state1 [label=<
            <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD PORT="title" bgcolor="yellow">1</TD></TR>
            <TR><TD PORT="text" bgcolor="red">S&rarr;E・$<br/>E&rarr;E・+T</TD></TR>
            </TABLE>>, pos="0,1.5!"];

    state7 [label=<
            <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD PORT="title" bgcolor="yellow">7</TD></TR>
            <TR><TD PORT="text1" bgcolor="red">T&rarr;(E・) </TD></TR>
            <TR><TD PORT="text2" bgcolor="green">E&rarr; E・+T</TD></TR>
            </TABLE>>, pos="4,1.5!"];

    state3 [label=<
            <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD PORT="title" bgcolor="yellow">3</TD></TR>
            <TR><TD PORT="text1" bgcolor="red">E&rarr;E+・T </TD></TR>
            <TR><TD PORT="text2" bgcolor="green">T&rarr;・id <br/> T&rarr;・(E) </TD></TR>
            </TABLE>>, pos="2,1.5!"];

    state2 [label=<
            <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD PORT="title" bgcolor="yellow">2</TD></TR>
            <TR><TD PORT="text" bgcolor="red">S&rarr;E$・ </TD></TR>
            </TABLE>>, pos="0,0!"];

    state8 [label=<
            <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD PORT="title" bgcolor="yellow">8</TD></TR>
            <TR><TD PORT="text" bgcolor="red">T&rarr;(E)・ </TD></TR>
            </TABLE>>, pos="4,0!"];

    state4 [label=<
            <TABLE ALIGN="LEFT" BORDER="0" CELLBORDER="1" CELLSPACING="0">
            <TR><TD PORT="title" bgcolor="yellow">4</TD></TR>
            <TR><TD PORT="text" bgcolor="red">E&rarr;E+T・ </TD></TR>
            </TABLE>>, pos="2,0!"];

    state0:s -> state1:n [xlabel="E"]
    state0 -> state9 [xlabel="T"]
    state0:e -> state5:w [xlabel="id"]
    state0 -> state6 [xlabel="("]

    state1:s -> state2:n [xlabel="$"]
    state1:title:e -> state3:title:w [xlabel="+"]

    state3:s -> state4:n [xlabel="T"]
    state3:n -> state5:s [xlabel="id"]
    state3:title:e -> state6 [xlabel="("]

    state6:s -> state7:n [xlabel="E"]
    state6 -> state9 [xlabel="T"]
    state6 -> state5 [xlabel="id"]
    state6 -> state6 [xlabel="("]

    state7:text2:w -> state3:text2:e [xlabel="+"]
    state7:s -> state8:n [xlabel=")"]
}

References

tk421
  • 5,775
  • 6
  • 23
  • 34
  • Thanks for your answer, your answer makes the line straight. But what I really want is to rank state0 (state9 state5) state6 same like the first picture I gave. What your solution and my solution's realization only rank state0 state9 and state6 same. – Ynjxsjmh Apr 19 '19 at 08:01
  • Sorry to bother you again, but I have a question that is there any way to control how to draw the self-connection line in state 6? The default style of self-connection is from top to bottom, but I'd like to use port like `from N to NE` or `from E to NE` to reduce the space the self-connection line takes up. But port doesn't work in this case. I think I can use invisible node to do that, but that's a lot typing. I searched a lot in Google, it didn't help me. Is there any simplier way to do that? – Ynjxsjmh Apr 20 '19 at 06:26
  • I played around with it too and couldn't find anything that works. My guess is that the rendering engine has problems with embedded HTML. – tk421 Apr 22 '19 at 17:17