User Guide
+What is JSyntrax?
+JSyntrax is a railroad diagram generator. +It creates a visual illustration of the grammar used for programming languages. +A specification file describes the syntax as a hierarchy of basic elements. +This is processed into an image representing the same syntax with interconnected nodes.
+The specification is a set of nested Groovy function calls:
+indentstack(10,
+ line(opt('-'), choice('0', line('1-9', loop(None, '0-9'))),
+ opt('.', loop('0-9', None))),
+ line(opt(choice('e', 'E'), choice(None, '+', '-'), loop('0-9', None)))
+)
+This is processed by JSyntrax to generate an SVG image:
+JSyntrax can render to PNG bitmap images or SVG vector images. +The SVG output can have hyperlinked text allowing users to quickly navigate to documentation of different syntax +elements.
+The original Syntrax was a heavily modified version of the railroad diagram generator used for the SQLite documentation implemented in Python. +Then in JSyntrax it has been reimplemented in Java in order to simplify installation, get rid of required libraries and make it easily portable to any operating system.
+JSyntrax vs. Syntrax
+-
+
- Why did you reimplement Syntrax in Java? +
-
+
The problem with Syntrax is that it requires Pycairo and Pango which may be difficult to install, especially on Windows. +JSyntrax requires only JDK 11, which is easily available for many platforms.
+
+ - What output formats are supported? +
-
+
JSyntrax produces SVG and PNG images. The original Syntrax can also produce PDF, PS, and EPS, these formats are not yet supported by JSyntrax.
+
+ - Can I build my Syntrax specs with JSyntrax? +
-
+
Yes, after only a couple of minor tweaks. +If you use url maps, refer to Hyperlinked SVG section for Groovy-specific DSL which is a bit different from what was in original Syntrax (in short: you will have to replace
+{}
with[]
and addjsyntrax
wrapper function). +Also,text_mod
attribute in Styling diagrams is not supported (the author of the original Syntrax warned about potential security issues with this attribute). +Instead, if a style regexp pattern contains a capturing group, the node text will contain the contents of the first capturing group only.
+ - Why your executable file is called
syntrax
, notjsyntrax
?
+ -
+
This is made intentionally in order to use AsciiDoctor Diagram integration facility. +JSyntrax executable has exactly the same command line arguments as Syntrax and can be used as a replacement for the original
+syntrax
tool.
+
Licensing
+JSyntrax is licensed for free commercial and non-commercial use under the terms of the MIT license.
+Requirements, download and installation
+JSyntrax requires JDK 11+. No other software is required to run JSyntrax.
+Unzip jsyntrax-XXX.zip
file to any convenient folder. /bin
directory will contain executable syntrax
file.
Using JSyntrax
+JSyntrax is a command line tool. You pass it an input specification file and it will generate a diagram in any of the supported output formats.
+usage: syntrax [--get-style] [-h] [-i <arg>] [-o <arg>] [-s <arg>] [--scale + <arg>] [-t] [--title <arg>] [-v] +Railroad diagram generator. +Options + --get-style Create default style .ini + -h,--help Show this help message and exit + -i,--input <arg> Diagram spec file + -o,--output <arg> Output file + -s,--style <arg> Style config .ini file + --scale <arg> Scale image + -t,--transparent Transparent background + --title <arg> Diagram title + -v,--version JSyntrax version+
Any argument not associated with a flag is assumed to be the input file name. The default output format is PNG.
+> syntrax spec +Output file spec.png was created +Done!+
You can specify the specific out file you want with the -o
option.
+The extension determines the format.
+You can also pass just the extension to -o
and Syntrax will use the input file base name for the output image:
>syntrax -i spec -o result.svg +Output file result.svg was created +Done! + +>syntrax -i spec -o svg +Output file spec.svg was created +Done!+
Transparency
+By default the images have a white background. If you want a transparent background pass the -t
option.
Scaling
+You can control the scale of the resulting image with the --scale
option.
+It takes a floating point scale factor.
+This is most useful for the PNG output to increase the resolution of the image or create thumbnails with less blurring than conventional bitmap resizing.
> syntrax -i scaling.spec -o small.svg --scale 0.5+
> syntrax -i scaling.spec -o big.svg --scale 2.0+
Titles
+You can include a title in the generated diagram either by using title(…)
command or by passing a string to the --title
option (the latter takes precedence).
+The position of the title is controlled by the title_pos
entry in the styling configuration.
+It defaults to the top left.
+The title_font
entry is used to style the font.
Example 1. Setting the title in diagram specification.
+title('title set in spec') +line('diagram', 'with', 'title')+
Example 2. Setting title from a command line argument.
+> syntrax -i titling.spec -o svg --title="Diagram with title"+
Specification language
+JSyntrax diagrams are created using a Groovy-based specification +language. +A series of nestable function calls generate specific diagram elements. +Nodes in the diagram are represented by quoted strings. +Nodes default to rounded bubbles but will change to a box when prefixed with "/". +Note that this is the reverse of how the original SQLite generator works. +The rounded bubbles are typically used for literal tokens. +Boxes are typically place holders for syntactic elements too complex to include in the current diagram. +Nodes starting with a non-alphanumeric character are rendered with their own font style so that punctuation tokens can be made more distinct.
+The following functions are available for creating diagrams:
+
|
+
|
+
|
+
|
+
|
+
|
+
|
+
|
+
|
+
line
+A line()
creates a series of nodes arranged horizontally from left
+to right.
line('[', 'foo', ',', '/bar', ']')
+loop
+A loop()
represents a repeatable section of the syntax diagram. It
+takes two arguments. The first is the line of nodes for the forward path
+and the second is the nodes for the backward path. The backward path is
+rendered with nodes ordered from right to left.
loop(line('/forward', 'path'), line('backward', 'path'))
+Either the forward or backward path can be None
to represent no
+nodes on that portion of the loop.
loop('forward', None)
+toploop
+A toploop()
is a variant of loop()
that places the backward path
+above the forward path.
toploop(line('(', 'forward', ')'), line('(', 'backward', ')'))
+choice
+The choice()
element represents a branch between multiple syntax
+options.
choice('A', 'B', 'C')
+opt
+An opt()
element specifies an optional portion of the syntax. The
+main path bypasses the optional portion positioned below.
opt('A', 'B', 'C')
+opt()
is a special case of the choice()
function where the first
+choice is None
and the remaining nodes are put into a single line
+for the second choice. The example above is equivalent the following:
choice(None, line('A', 'B', 'C'))
+optx
+The optx()
element is a variant of opt()
with the main path
+passing through the nodes.
optx('A', 'B', 'C')
+stack
+The elements described above will concatenate indefinitely from left to
+right. To break up long sections of a diagram you use the stack()
+element. Each of its arguments forms a separate line that is stacked
+from top to bottom.
stack(
+ line('top', 'line'),
+ line('bottom', 'line')
+)
+When an inner element of a stack argument list is an opt()
or an
+optx()
it will be rendered with a special vertical bypass.
stack(
+ line('A', 'B'),
+ opt('bypass'),
+ line('finish')
+)
+indentstack
+For more control of the stacking you can use the indentstack()
+element. It shifts lower lines to the right relative to the top line of
+the stack. Its first argument is an integer specifing the amount of
+indentation.
indentstack(3,
+ line('top', 'line'),
+ line('bottom', 'line')
+)
+rightstack
+The rightstack()
element will right align successive lines without
+needing to determine the indentation.
rightstack(
+ line('top', 'line', 'with', 'more', 'code'),
+ line('bottom', 'line')
+)
+Styling diagrams
+You can control the styling of the generated diagrams by passing in a
+style INI file with the -s
option.
You can use the --get-style
option to generate a copy of the default
+styles in the current directory so you can quickly make modifications.
Here is the default styling:
+[style]
+line_width = 2
+outline_width = 2
+padding = 5
+line_color = (0, 0, 0)
+max_radius = 9
+h_sep = 17
+v_sep = 9
+arrows = True
+title_pos = 'tl'
+bullet_fill = (255, 255, 255)
+text_color = (0, 0, 0)
+shadow = True
+shadow_fill = (0, 0, 0, 127)
+title_font = ('Sans', 22, 'bold')
+
+[bubble]
+pattern = '(^\w+)'
+shape = 'bubble'
+font = ('Sans', 14, 'bold')
+text_color = (0, 0, 0)
+fill = (179, 229, 252)
+
+[box]
+pattern = '^/(.+)'
+shape = 'box'
+font = ('Times', 14, 'italic')
+text_color = (0, 0, 0)
+fill = (144, 164, 174)
+
+[token]
+pattern = '(.*)'
+shape = 'bubble'
+font = ('Sans', 16, 'bold')
+text_color = (0, 0, 0)
+fill = (179, 229, 252)
+Here is the same diagram with modified styling:
+[style]
+; Thicker lines
+line_width = 3
+outline_width = 3
+padding = 5
+line_color = (0, 0, 0)
+; Larger radii
+max_radius = 29
+h_sep = 17
+v_sep = 9
+; Remove arrows
+arrows = False
+title_pos = 'tl'
+; yellow
+bullet_fill = (255,255,0)
+text_color = (0, 0, 0)
+shadow = True
+shadow_fill = (0, 0, 0, 127)
+title_font = ('Sans', 22, 'bold')
+
+; User-defined style name
+[hex_bubble]
+pattern = '(^\w+)'
+; Hexagon shape for node
+shape = 'hex'
+font = ('Sans', 14, 'bold')
+; Alpha component for transparent fills
+fill = (255,0,0,127)
+
+[box]
+pattern = '^/(.*)'
+shape = 'box'
+font = ('Sans', 14, 'bold')
+text_color = (100, 100, 100)
+fill = (144, 164, 174)
+
+[token]
+pattern = '(.*)'
+shape = 'bubble'
+font = ('Times', 16, 'italic')
+fill = (0,255,0,127)
+The style configuration file has a main section named "[style]" followed by user-defined sections for various node types. +The node style is chosen based on a regex pattern applied to the text. +The first matched pattern sets the style for a node. +Patterns are tested in the same order they appear in the configuration file. +The first node style is used by default if no pattern matched the text. +If the pattern contains a capturing group, then the resulting text in the node will be equal to the contents of this group (otherwise, the full text will be used).
+The [style]
section contains the following keys:
-
+
- line_width +
-
+
Connecting line width in pixels. +Default is 2.
+
+ - outline_width +
-
+
Node outline width in pixels. +Default is 2.
+
+ - padding +
-
+
Additional padding around each edge of the image in pixels. +Default is5.
+
+ - line_color +
-
+
Color of the connecting lines and node outlines. +Default is (0,0,0) Black.
+
+ - max_radius +
-
+
Maximum radius for turnbacks on loops and stacked connections.
+
+ - h_sep +
-
+
Horizontal separation between nodes.
+
+ - v_sep +
-
+
Vertical separation between line elements.
+
+ - arrows +
-
+
Boolean used to control rendering of line arrows. +Default is True.
+
+ - title_pos +
-
+
Position of the title text. +String containing one of 'left', 'center', or 'right' for horizontal position and 'top' or 'bottom' for vertical. +These can be abbreviated as 'l', 'c', 'r', 't', and 'b'. +Other characters are ignored. +Examples are 'top-left', 'bottom center', 'cr', and 'rt'.
+
+ - bullet_fill +
-
+
Fill color for small bullets at start and end of the diagram.
+
+ - text_color +
-
+
Default color of all text. Can be overridden with
+text_color
in a +node style section
+ - shadow +
-
+
Boolean controlling the rendering of node shadows. Default is True.
+
+ - shadow_fill +
-
+
Fill color for shadows.
+
+ - title_font +
-
+
Font for image title.
+
+
Node styles
+Nodes are styled with a user-defined section name.
+The built-in sections are [bubble]
for tokens that start with an alphanumeric character, [box]
for symbols drawn with a boxed outline, and [token]
for tokens that consist of a single punctuation character.
+You are not limited to these three node styles.
+Any number of node types can be defined provided they have distinct patterns to match against the node text in your specification file.
The node sections contain the following keys:
+-
+
- pattern +
-
+
A regex pattern to match the node text to a style. Notes about pattern format:
+++-
+
-
+
Must satisfy regex java semantics
+
+ -
+
Matches the whole input sequence exclusively (input
+"</>Hello"
corresponds to this:"</>.*"
, not this:"</>"
)
+ -
+
You may not want to see control characters of your regex in diagram output. To omit them, use capture groups to wrap the content you want to display. Examples:
+++-
+
-
+
+<b>(.*)</b>
- matches<b>my_text</b>
and will displaymy_text
+ -
+
+^/(.+)
-→/my_text
-→my_text
+ -
+
+"^</(.*)>"
-→"</my_text>"
-→"my_text"
+
+ -
+
-
+
If given input sequence does not match specified expression, default style will be used.
+
+
+ -
+
- shape +
-
+
Node outline shape. Must be "bubble", "box", or "hex".
+
+ - font +
-
+
Font style for the node.
+
+ - text_color +
-
+
Optional font color for the node. +If omitted, the
+text_color
from the[style]
section is used.
+ - fill +
-
+
Shape fill color for the node.
+
+
Colors
+The various keys controlling coloration can use a variety of color +formats. +The primary color representation is a 3 or 4-tuple representing RGB or RGBA channels. +All channels are an integer ranging from 0 to 255.
+; Supported color formats: + +(255,100,0) ; RGB +(255,100,0,100) ; RGBA+
Fonts
+Fonts are specified as a tuple of three items in the following order:
+-
+
-
+
Font family (Helvetica, Times, Courier, etc.)
+
+ -
+
Point size (12, 14, 16, etc.)
+
+ -
+
Style ('normal', 'bold', 'italic')
+
+
title_font = ('Helvetica', 14, 'bold')+
Hyperlinked SVG
+SVG images can have hyperlinked node text. This is implemented by adding a url_map
parameter to jsyntrax
wrapper function.
+The keys of the dictionary are the text identifying the node and their values are the URL for the link.
+The text key should not include any leading "/" character for the box nodes.
jsyntrax(stack(
+ line('attribute', '/(attribute) identifier', 'of'),
+ line(choice(toploop('/entity_designator', ','), 'others', 'all'), ':'),
+ line('/entity_class', 'is', '/expression', ';')
+),
+[
+ 'entity_class': 'https://www.google.com/#q=vhdl+entity+class',
+ '(attribute) identifier': 'http://en.wikipedia.com/wiki/VHDL'
+])
++ + | +
+ Note for Syntrax (Python) users
+
+
+Note that in Groovy, unlike Python, maps are enclosed in brackets |
+
Current browser policies lump SVG hyperlinks together with embedded
+Javascript.
+Because of this they do not support hyperlinks when an SVG
+is referenced through an HTML <img>
tag.
+To get functional links on a web page you must use an <object>
tag instead:
<object type="image/svg+xml" data="path/to/your.svg"></object>
+In Asciidoctor diagrams, we should put set opts=interactive
or opts=inline
on the diagram block:
[syntrax,hyperlinked,svg,opts=interactive] +.... +jsyntrax( ... , +[ + ... +]) +....+