MarpaX::Grammar::GraphViz2 - Convert a Marpa grammar into an image
use MarpaX::Grammar::GraphViz2; my(%option) = ( # Inputs: legend => 1, marpa_bnf_file => 'share/metag.bnf', user_bnf_file => 'share/stringparser.bnf', # Outputs: output_file => 'html/stringparser.svg', ); MarpaX::Grammar::GraphViz2 -> new(%option) -> run;
See share/*.bnf for input files and html/*.svg for output files.
For more help, run:
shell> perl -Ilib scripts/bnf2graph.pl -h
Note: Installation includes copying all files from the share/ directory, into a dir chosen by File::ShareDir. Run scripts/find.grammars.pl to display the name of the latter dir.
See also the demo page.
For a given BNF, process the cooked tree output by MarpaX::Grammar::Parser, and turn it into an image.
The tree holds a representation of the user's BNF (SLIF-DSL), and is managed by Tree::DAG_Node.
This modules uses MarpaX::Grammar::Parser internally. It does not read that module's output file.
Install MarpaX::Grammar::GraphViz2 as you would for any Perl module:
Perl
Run:
cpanm MarpaX::Grammar::GraphViz2
or run:
sudo cpan MarpaX::Grammar::GraphViz2
or unpack the distro, and then either:
perl Build.PL ./Build ./Build test sudo ./Build install
or:
perl Makefile.PL make (or dmake or nmake) make test make install
Call new() as my($parser) = MarpaX::Grammar::GraphViz2 -> new(k1 => v1, k2 => v2, ...).
new()
my($parser) = MarpaX::Grammar::GraphViz2 -> new(k1 => v1, k2 => v2, ...)
It returns a new object of type MarpaX::Grammar::GraphViz2.
MarpaX::Grammar::GraphViz2
Key-value pairs accepted in the parameter list (see also the corresponding methods [e.g. "marpa_bnf_file([$bnf_file_name])"]):
The name of the Graphviz program to provide to GraphViz2.
Default: 'dot'.
This is the format of the output file, to be passed to GraphViz2.
Default: 'svg'.
Provides an object of type GraphViz2, to do the rendering.
Default:
GraphViz2 -> new ( edge => {color => 'grey'}, global => {directed => 1, driver => $self -> driver, format => $self -> format}, graph => {label => basename($self -> user_bnf_file), rankdir => 'TB'}, logger => $self -> logger, node => {shape => 'rectangle', style => 'filled'}, );
Add a legend (1) to the graph, or omit it (0).
Default: 0.
Specify a logger object.
The default value triggers creation of an object of type Log::Handler which outputs to the screen.
To disable logging, just set logger to the empty string.
The value for logger is passed to GraphViz2.
Default: undef.
Specify the name of Marpa's own BNF file. This file ships with Marpa::R2. It's name is metag.bnf.
A copy, as of Marpa::R2 V 2.096000, ships with MarpaX::Grammar::GraphViz2. See share/metag.bnf.
This option is mandatory.
Default: ''.
This option is only used if an object of type Log::Handler is created. See logger above.
See also Log::Handler::Levels.
Default: 'notice'. A typical value is 'debug'.
Default: 'error'.
No lower levels are used.
Write the image to this file.
Use the format option to specify the type of image desired.
format
If '', the file is not written.
Specify the name of the file containing your Marpa::R2-style grammar.
See share/stringparser.bnf for a sample.
Adds a legend to the graph if new() was called as new(legend => 1).
new(legend => 1)
Adds (once only) a node to the graph. The node's name is $attributes{name}.
$attributes{name}
Also, adds that name to the hashref of node names seen, which is returned by "nodes_seen()".
Cleans the given name to escape or replace characters special to dot.
Note: GraphViz2 also escapes some characters.
$skip_symbols is used by the caller in 1 case to stop a regexp being activated.
See the "FAQ" for details.
Returns the cleaned-up name.
Calls "clean_name($name, $skip_symbols)" for each node in the tree.
Returns the number of :default' rules in the user's input.
:default
Returns the number of :discard rules in the user's input.
:discard
Here, the [] indicate an optional parameter.
Get or set the name of the Graphviz program to provide to GraphViz2.
Note: driver is a parameter to new().
driver
Returns the number of event rules in the user's input.
event
Get or set the format of the output file, to be created by the renderer.
Note: format is a parameter to new().
Get of set the GraphViz2 object which will do the graphing.
See also "output_file([$output_file_name])".
Note: graph is a parameter to new().
graph
Get or set the option to include (1) or exclude (0) a legend from the image.
Note: legend is a parameter to new().
legend
Returns the number of :lexeme rules in the user's input.
:lexeme
Returns a hashref keyed by the clean name, of lexemes seen in the user's input.
The value for each key is an arrayref of hashrefs suitable for forcing GraphViz2 to plot the node as a record structure. See http://www.graphviz.org/content/node-shapes#record for the gory details.
Calls $self -> logger -> log($level => $s) if ($self -> logger).
Get or set the logger object.
This logger is passed to GraphViz2.
Note: logger is a parameter to new().
logger
Get or set the name of the file to read Marpa's grammar from.
Note: marpa_bnf_file is a parameter to new().
marpa_bnf_file
Get or set the value used by the logger object.
This option is only used if an object of type Log::Handler is created. See Log::Handler::Levels.
Note: maxlevel is a parameter to new().
maxlevel
Note: minlevel is a parameter to new().
minlevel
The constructor. See "Constructor and Initialization".
Returns a hashref keyed by the node name, of nodes passed to GraphViz2.
This is simply used to stop nodes being plotted twice.
Get or set the name of the file to which the renderer will write the resultant graph.
If no output file is supplied, nothing is written.
See also graph([$graph]).
Note: output_file is a parameter to new().
output_file
Returns the Marpa::Grammar::Parser object which will do the analysis of the user's grammar.
This object is created automatically during the call to "new()".
For the given $node, which is an object of type Tree::DAG_Node, clean it's real name.
Then it adds the node's quantifier ('', '*' or '+') to that name, to act as the label (visible name) of the node, when the node is finally passed to GraphViz2.
Returns a 2-element list of ($name, $label).
Returns a string which is the name of the root node of graph.
The method which does all the work.
See "Synopsis" and scripts/bnf2graph.pl for sample code.
Get or set the name of the file to read the user's grammar from.
Note: user_bnf_file is a parameter to new().
user_bnf_file
This is part of MarpaX::Languages::C::AST, by Jean-Damien Durand. It's 1,565 lines long.
This is the image from c.ast.bnf.
See the next point for how this file is created.
It is part of MarpaX::Demo::JSONParser, written as a gist by Peter Stuifzand.
See https://gist.github.com/pstuifzand/4447349.
This is the image from json.1.bnf.
It also is part of MarpaX::Demo::JSONParser, written by Jeffrey Kegler as a reply to the gist above from Peter.
This is the image from json.2.bnf.
See the previous point for how this file is created.
It also is part of MarpaX::Demo::JSONParser, and is written by Jeffrey Kegler.
This is the image from json.3.bnf.
This is a copy of Marpa::R2's BNF, as of Marpa::R2 V 2.096000.
This is the image from metag.bnf.
This BNF was extracted from MarpaX::Demo::SampleScripts's examples/ambiguous.grammar.01.pl.
This is the image from numeric.expressions.bnf.
This is a copy of MarpaX::Demo::StringParser's BNF.
This is the image from stringparser.bnf.
It also is part of MarpaX::Database::Terminfo, written by Jean-Damien Durand.
This is the image from termcap.info.bnf.
This is a neat way of using the module. For help, run:
Of course you are also encouraged to include this module directly in your own code.
This is a quick way for me to run bnf2graph.pl.
This prints the path to a grammar file. After installation of the module, run it with:
shell> perl scripts/find.grammars.pl (Defaults to json.1.bnf) shell> perl scripts/find.grammars.pl c.ast.bnf shell> perl scripts/find.grammars.pl json.1.bnf shell> perl scripts/find.grammars.pl json.2.bnf shell> perl scripts/find.grammars.pl stringparser.bnf shell> perl scripts/find.grammars.pl termcap.inf.bnf
It will print the name of the path to given grammar file.
Generates html/index.html.
This calls generate.demo.pl for each grammar shipped with the module.
Actually, it skips c.ast by default, since it takes 6 m 47 s to run that. But if you pass any command line parameter to the script, it includes c.ast.
Then it copies html/* to my web server's doc root (which is in Debian's default RAM disk) at /dev/shm/html.
This lets me quickly proof-read edits to the docs.
Firstly, the Perl module GraphViz2 escapes some characters. Currently, these are:
[ ] " (in various circumstances)
We let GraphViz2 handle these.
Secondly, Graphviz itself treats some characters specially. Currently, these are:
< > : "
We use this code to handle these:
$name =~ s/\\/\\\\/g; # Escape \. $name =~ s/</\\</g; # Escape <. $name =~ s/>/\\>/g; # Escape >. $name =~ s/:/\x{a789}/g; # Replace : with a Unicode : $name =~ s/\"/\x{a78c}\x{a78c}/g; # Replace " with 2 copies of a Unicode ' ... # ... because I could not find a Unicode ".
This is due to the author using both 'comma' and '<comma>' as tokens within the grammar.
So far this module does not notice the two are the same.
A similar thing can happen elsewhere, e.g. with named event statements, when the rhs name uses (say) '<xyz>' and the rule referred to uses just 'xyz'.
In all such cases, there will be 2 nodes, with 2 names differing in just the brackets.
There is simply no way to plot a node both with and without the quantifier. The one which appears is chosen arbitrarily, depending on how the code scans the grammar. This means it is currently beyond control.
I'm undecided as to whether or not they are a good idea. I documented it on the demo page to indicate it was easy (for some nodes), and await feedback.
No, but you can turn it off with the legend option to new().
This is the rule # within the input stream. Doing this is simple for some nodes, and difficult for others.
The file Changes was converted into Changelog.ini by Module::Metadata::Changes.
Version numbers < 1.00 represent development versions. From 1.00 up, they are production versions.
https://github.com/ronsavage/MarpaX-Grammar-GraphViz2
Email the author, or log a bug on RT:
https://rt.cpan.org/Public/Dist/Display.html?Name=MarpaX::Grammar::GraphViz2.
MarpaX::Grammar::GraphViz2 was written by Ron Savage <ron@savage.net.au> in 2013.
Home page: http://savage.net.au/.
Australian copyright (c) 2013, Ron Savage.
All Programs of mine are 'OSI Certified Open Source Software'; you can redistribute them and/or modify them under the terms of The Perl License, a copy of which is available at: http://www.opensource.org/licenses/index.html
To install MarpaX::Grammar::GraphViz2, copy and paste the appropriate command in to your terminal.
cpanm
CPAN shell
perl -MCPAN -e shell install MarpaX::Grammar::GraphViz2
For more information on module installation, please visit the detailed CPAN module installation guide.