Tuesday, January 24, 2006

LaTeX on Rail

Ever wondered how to graphically represent EBNF?

There are some packages out there that can produce so called Railroad diagrams.

Phillips has a package called Elegant (you can see some examples in this document)

Then there is LaTeX-style rail.sty online, where the results are quite ok as well (the png image is scaled to 600pt in width, so the real quality is better) :

So, how does one read the diagram? For the start form left to right :-) Words in rounded boxes are terminals (i.e. words that you put literally in your code) Words in normal boxes are non-terminals that refer to other diagrams. A construct like in the start with "AVG", "MAX", ... is a switch statement, where you can choose one ot the options. You will see that above "DISTINCT" is a line without a box. This means that "DISTINCT" is optional.
And this is basically all about reading those diagrams.

Unfortunately, this package does not directly know about the 'ususal' EBNF syntax ( AggreagateExpression ::= ....), but uses its own, which looks like the following for the above example

AggregateExpression : ("AVG" |"MAX" |"MIN" |"SUM")
'DISTINCT' ? StateFieldPathExpression
) | 'COUNT'
'DISTINCT' ? IdentificationVariable
| StateFieldPathExpression
| SingleValuedAssociationPathExpression

Perhaps I am going to write some translator between the formats in Perl ...


Luc Rooijakkers said...

I developed this package in 1991; does it actually still work with current LaTeX versions? Wow!

Dave Hughes said...

For Luc and anyone else interested:

Yup - it does work with current LaTeX versions (I'm using it with texlive 2007). Unfortunately it doesn't quite compile cleanly with modern versions of bison. The quick (but probably dirty) fix is to stick:


on line 60 of rail.h below the YYSTYPE declaration. There seem to be a few other nasties, e.g. attempting to stick a hyphen in a non-terminal's name segfaults the app, but generally it works nicely provided one's reasonably careful with the input.

I also tried to get the (similar but more recent) "syngen" package from CTAN working. Unfortunately it's written in the obscure "Caml Special Light" language (which became the only slightly less obscure OCaml 1). Despite hours of trying I couldn't get it to work (got the CSL to OCaml 1 converter to work, but then the OCaml 1 to OCaml 2 converter wouldn't compile with OCaml 3, and neither OCaml 1 or OCaml 2 would compile, so I didn't even get to the OCaml 2 to OCaml 3 conversion ...)