Generating syntax diagrams using the LaTeX rail package
Sun 21 May 2017If you ever had the need to add syntax specifications to your document, you basically have two options: Either write down the syntax in the Backus-Naur form (BNF) (or one of its derivatives) or opt for a more graphical approach by adding "railroad diagrams". In my opinon, the latter are easier to grasp for less experienced readers and also look quite nice.
In LaTeX, you can use the rail
package to
generate those diagrams from
EBNF
rules:
\begin{rail}
decl : 'def' identifier '=' ( expression + ';' )
| 'type' identifier '=' type
;
\end{rail}
This will result in something like this:
To archieve this, the package first generates a *.rai
file. We then have
to convert the rai file to a *.rao
by invoking the accompanying C
program named rail
.
However, the rail
package is fairly old. It has been written by
Luc Rooijakkers in 1991 (!) and was updated by Klaus Barthelmann until 1998.
Thus, the code is -- at least -- 19 years old and that really shows: Trying
to compile it on modern systems yields a bunch of compilation errors.
Most of the issues stem from missing return types in function declarations and also missing forward declarations. I stepped up and fixed these issues, so that it works with a up-to-date compiler (I tested with gcc (GCC) 6.3.1 on Arch Linux. You can find the result on Github.
I also threw in some Makefile
improvements into the mix: You can now use
DESTDIR
and
PREFIX
(defaults to /usr/local
) when running make install
.
Installation
Installation should be fairly straighforward. Here's an example which will
install rail
into /usr
:
$ curl -L https://github.com/Holzhaus/latex-rail/archive/v1.2.1.tar.gz | tar xzvf -
$ cd latex-rail-1.2.1
$ make
bison -y -dv gram.y
gram.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
cmp -s gram.c y.tab.c || cp y.tab.c gram.c
cmp -s gram.h y.tab.h || cp y.tab.h gram.h
gcc -DYYDEBUG -O -c -o rail.o rail.c
gcc -DYYDEBUG -O -c -o gram.o gram.c
flex -t lex.l > lex.c
gcc -DYYDEBUG -O -c -o lex.o lex.c
gcc -DYYDEBUG -O rail.o gram.o lex.o -o rail
$ sudo make PREFIX=/usr install
$ sudo mktexlsr
Please note that installing stuff using sudo make install
will circumvent
your package manager and is usually not a good idea. If you're using
Arch Linux you should use the
AUR package instead:
$ pacaur -S latex-rail
Manual compilation and Latexmk support
To generate a document manually, you need to run multiple commands:
- Run
latex mydoc
, which will createmydoc.rai
- Run
rail mydoc
to generatemydoc.rao
frommydoc.rai
- Run
latex mydoc
for the final document
If you don't want to bother with running LaTeX multiple times, you can use latexmk, a perl script to automate the document generation.
To make it work with the rail
package, you should create a .latexmkrc
in your document folder with this content:
push @file_not_found, '^Package .* Info: No file (.+) on input line \d+\.';
add_cus_dep('rai', 'rao', 0, 'rail');
sub rail {
my ($base_name, $path, $ext) = fileparse( $_[0], qr/\.[^.\/]*/ );
pushd $path;
my $return = system "rail $base_name";
popd;
return $return;
}
The first line will add the appropriate RegEx to Latexmk's missing file
detection, the second line will instruct latexmk to run the rail
subroutine
with a *.rai
file as input and *.rao
file as output.
Alternatives
I you don't quite like the rail
package, you might want to look into
one of these alternative packages:
syngen
by Jens Klöckersyntax-mdw
by Mark Woodingsyntax
by Bernd Worsch
These also an online tool to generate railroad diagrams if you don't want to do it in LaTeX.