Reed-Kellogg progress

I got half-way through a recursive algorithm for generating Reed-Kellogg diagrams from (appropriately matched) tree definitions, and realized that I still don't really understand the R-K diagrams, and thus don't have much confidence that I won't learn something down the road that forces a major revision of the algorithm. So I decided to take a smaller step first, implementing a "little language" that makes it fairly easy to draw arbitrary diagrams of a vaguely R-K sort.

So far the little language has five primitives (excluding comments, which are lines starting with #):

Obviously this could be made more elegant by combining the first four cases into a single primitive that generates text on an arbitrary line of arbitrary style in an arbitrary direction, but it was more convenient for various reasons to keep the different cases separate. In fact, it would be even more convenient to multiply the cases further, so that (e.g.) the (textless) lines for subj/predicate, verb/object, and verb/complement divisions are each treated specially, the subdiagrams for indirect objects and prepositional phrases can be generated by a single command line, and so on. My current plan is to make both kinds of changes -- i.e. to purify the graphical language down to two primitives (text on a line and line without text), and to create a second, more grammatical language that knows about things like "indirect object", "prepositional phrase", "conjunction", "clause", etc.

Anyhow, as it stands, this input

# Professor Higgins gave her students two projects.
1 htext 0 20 $hmargin $hmargin Professor Higgins
# next is post-subject line
2 line $x2{1} $y2{1}+$subjbelow $x2{1} $y2{1}-$subjabove
3 htext $x2{1} $y2{1} $hmargin $hmargin+3*$charwidth gave
# next is pre-object line
4 line $x2{3} $y2{3} $x2{3} $y2{3}-$objabove
5 htext $x2{3} $y2{3} $hmargin $hmargin projects
6 otext $x1{5}+$hmargin+2*$charwidth $y1{5} two
# indirect object
7 line $x1{3}+$charwidth $y1{3} $x1{3}+$charwidth+$iobjinc $y1{3}+$iobjinc
8 htext $x2{7} $y2{7} $charwidth $charwidth students
9 otext $x1{8}+$hmargin $y2{8} her

generates this .svg output:

<svg width="20cm" height="10cm" version="1.1">
<!-- # Professor Higgins gave her students two projects. -->
<!-- 1 htext 0 20 $hmargin $hmargin Professor Higgins -->
<!-- Horizontal text |1| from 0 20 to 76.19 20 (Professor Higgins) -->
<path d="M 0 20 76.19 20" style="stroke: gray; fill: none;" />
<text x="0" y="20"
font-family="monospace" style="font-size:8;" letter-spacing="-0.6pt"
baseline-shift="10%" dx="5.71">
Professor Higgins
</text>
<!-- # next is post-subject line -->
<!-- 2 line $x2{1} $y2{1}+$subjbelow $x2{1} $y2{1}-$subjabove -->
<!-- line |2| from 76.19 24 to 76.19 13.5 -->
<path d="M 76.19 24 76.19 13.5" style="stroke: gray; fill: none;" />
<!-- 3 htext $x2{1} $y2{1} $hmargin $hmargin+3*$charwidth gave -->
<!-- Horizontal text |3| from 76.19 20 to 114.28 20 (gave) -->
<path d="M 76.19 20 114.28 20" style="stroke: gray; fill: none;" />
<text x="76.19" y="20"
font-family="monospace" style="font-size:8;" letter-spacing="-0.6pt"
baseline-shift="10%" dx="5.71">
gave
</text>
<!-- # next is pre-object line -->
<!-- 4 line $x2{3} $y2{3} $x2{3} $y2{3}-$objabove -->
<!-- line |4| from 114.28 20 to 114.28 13.5 -->
<path d="M 114.28 20 114.28 13.5" style="stroke: gray; fill: none;" />
<!-- 5 htext $x2{3} $y2{3} $hmargin $hmargin projects -->
<!-- Horizontal text |5| from 114.28 20 to 156.18 20 (projects) -->
<path d="M 114.28 20 156.18 20" style="stroke: gray; fill: none;" />
<text x="114.28" y="20"
font-family="monospace" style="font-size:8;" letter-spacing="-0.6pt"
baseline-shift="10%" dx="5.71">
projects
</text>
<!-- 6 otext $x1{5}+$hmargin+2*$charwidth $y1{5} two -->
<!-- Oblique Text |6| from 127.61 20 to 143.24 35.63 (two) -->
<path id="P6" d="M 127.61 20 l 15.63 15.63" style="stroke: gray; fill: none;" />
<text x="127.61" y="20"
font-family="monospace" style="font-size:8;" letter-spacing="-0.6pt"
baseline-shift="10%" dx="6.86">
<textPath xlink:href="#P6">two</textPath>
</text>
<!-- # indirect object -->
<!-- 7 line $x1{3}+$charwidth $y1{3} $x1{3}+$charwidth+$iobjinc $y1{3}+$iobjinc -->
<!-- line |7| from 80 20 to 89.525 29.525 -->
<path d="M 80 20 89.525 29.525" style="stroke: gray; fill: none;" />
<!-- 8 htext $x2{7} $y2{7} $charwidth $charwidth students -->
<!-- Horizontal text |8| from 89.525 29.525 to 127.62 29.525 (students) -->
<path d="M 89.525 29.525 127.62 29.525" style="stroke: gray; fill: none;" />
<text x="89.525" y="29.525"
font-family="monospace" style="font-size:8;" letter-spacing="-0.6pt"
baseline-shift="10%" dx="3.81">
students
</text>
<!-- 9 otext $x1{8}+$hmargin $y2{8} her -->
<!-- Oblique Text |9| from 95.235 29.525 to 110.86 45.16 (her) -->
<path id="P9" d="M 95.235 29.525 l 15.63 15.63" style="stroke: gray; fill: none;" />
<text x="95.235" y="29.525"
font-family="monospace" style="font-size:8;" letter-spacing="-0.6pt"
baseline-shift="10%" dx="6.86">
<textPath xlink:href="#P9">her</textPath>
</text>
</svg>

which in turn looks like this at suitable magnification in an svg viewer (this is a screen capture turned into a .png file):

This is the example from slide 8 of this PowerPoint presentation.

It looks to me like Professor should really be a modifier of Higgins, so here's a revised version:

# Professor Higgins gave her students two projects.
1 htext 0 20 $hmargin $hmargin Higgins
1a otext $x1{1}+$hmargin $y1{1} Professor
# next is post-subject line
2 line $x2{1} $y2{1}+$subjbelow $x2{1} $y2{1}-$subjabove
3 htext $x2{1} $y2{1} $hmargin $hmargin+3*$charwidth gave
# next is pre-object line
4 line $x2{3} $y2{3} $x2{3} $y2{3}-$objabove
5 htext $x2{3} $y2{3} $hmargin $hmargin projects
6 otext $x1{5}+$hmargin+2*$charwidth $y1{5} two
# indirect object
7 line $x1{3}+$charwidth $y1{3} $x1{3}+$charwidth+$iobjinc $y1{3}+$iobjinc
8 htext $x2{7} $y2{7} $charwidth $charwidth students
9 otext $x1{8}+$hmargin $y2{8} her

which generates (via this .svg file) this picture:

There are just a couple of basic ideas here.

Each line of the input is either a comment (starting with #), or a drawing instruction. The drawing instructions are of the form

ID TYPE COORDINATES [string]

where

Each drawing instruction produces a single, basically linear diagram component. The program calculates nominal endpoints x1 y1 x2 y2 and stores them in hash locations $x1{ID}, $x2{ID} etc. for future use.

The program is written in perl, and all coordinates are interpreted via "eval", so that prior hashed endpoints are available, as are various global parameters like $charwidth (the width of a character) and $objabove (the standard height above the baseline of the object separator) and $iobjinc (the x and y increment of the oblique line used to connect an indirect object).

A current draft of the program is here.