NAME
Graph::Easy::Marpa - A Marpa-based parser for Graph::Easy::Marpa-style Graphviz files
Synopsis
Sample Code
#!/usr/bin/env perl
use strict;
use warnings;
use Graph::Easy::Marpa;
use Getopt::Long;
use Pod::Usage;
# -----------------------------------------------
my($option_parser) = Getopt::Long::Parser -> new();
my(%option);
if ($option_parser -> getoptions
(
\%option,
'description=s',
'dot_input_file=s',
'format=s',
'help',
'input_file=s',
'logger=s',
'maxlevel=s',
'minlevel=s',
'output_file=s',
'rankdir=s',
'report_tokens=i',
'token_file=s',
) )
{
pod2usage(1) if ($option{'help'});
# Return 0 for success and 1 for failure.
exit Graph::Easy::Marpa -> new(%option) -> run;
}
else
{
pod2usage(2);
}
This is shipped as scripts/parse.pl
, although the shipped version has built-in help.
Run 'perl -Ilib scripts/parse.pl -h' for sample demos.
Sample output
Unpack the distro and copy html/*.html and html/*.svg to your web server's doc root directory.
Then, point your browser at 127.0.0.1/index.html.
Or, hit http://savage.net.au/Perl-modules/html/graph.easy.marpa/index.html.
Modules
- o Graph::Easy::Marpa
-
The current module, which documents the set of modules.
It uses Graph::Easy::Marpa::Parser and Graph::Easy::Marpa::Renderer::GraphViz2, and 'dot', to render a
Graph::Easy::Marpa
-syntax file into a (by default) *.svg file.See scripts/parse.pl and scripts/parse.sh.
- o Graph::Easy::Marpa::Parser
-
See Graph::Easy::Marpa::Parser.
Accepts a graph definition in the Graph::Easy::Marpa language and builds a data structure representing the graph.
See scripts/parse.pl and scripts/parse.sh.
- o Graph::Easy::Marpa::Renderer::GraphViz2
-
This is the default renderer, and can output a dot file, suitable for inputting to the
dot
program.Also, it can use GraphViz2 to call
dot
and write dot's output to yet another file. - o Graph::Easy::Marpa::Actions
-
This is a file of methods called by Marpa::R2 as callbacks, during the parse.
End-users have no need to call any of its methods.
- o Graph::Easy::Marpa::Config
-
This manages the config file, which contains a HTML template used by
scripts/generate.index.pl
.End-users have no need to call any of its methods.
- o Graph::Easy::Marpa::Filer
-
Methods to help with reading sets of files.
End-users have no need to call any of its methods.
- o Graph::Easy::Marpa::Utils
-
Methods to help with testing and generating the demo page.
See http://savage.net.au/Perl-modules/html/graph.easy.marpa/index.html.
End-users have no need to call any of its methods.
Description
Graph::Easy::Marpa provides a Marpa-based parser for Graph::Easy::Marpa
-style graph definitions.
Such graph definitions are wrappers around Graphviz's DOT language. Therefore this module is a pre-processor for DOT files.
The default renderer mentioned above, Graph::Easy::Marpa::Renderer::GraphViz2, can be used to convert the graph into a image.
See "Data Files and Scripts" for details.
Distributions
This module is available as a Unix-style distro (*.tgz).
See http://savage.net.au/Perl-modules/html/installing-a-module.html for help on unpacking and installing distros.
Installation
Install Graph::Easy::Marpa as you would for any Perl
module:
Run:
cpanm Graph::Easy::Marpa
or run:
sudo cpan Graph::Easy::Marpa
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
Constructor and Initialization
new()
is called as my($parser) = Graph::Easy::Marpa -> new(k1 => v1, k2 => v2, ...)
.
It returns a new object of type Graph::Easy::Marpa
.
Key-value pairs accepted in the parameter list (see corresponding methods for details [e.g. maxlevel()]):
- o description => $graph_description_string
-
Specify a string for the graph definition.
You are strongly encouraged to surround this string with '...' to protect it from your shell.
See also the input_file key to read the graph from a file.
The description key takes precedence over the input_file key.
The value for description is passed to Graph::Easy::Marpa::Parser.
Default: ''.
- o dot_input_file => $file_name
-
Specify the name of a file that the rendering engine can write to, which will contain the input to dot (or whatever). This is good for debugging.
If '', the file will not be created.
The value for dot_input_file is passed to Graph::Easy::Marpa::Renderer::GraphViz2.
Default: ''.
- o format => $format_name
-
This is the format of the output file, to be created by the renderer.
The value for format is passed to Graph::Easy::Marpa::Renderer::GraphViz2.
Default: 'svg'.
- o input_file => $graph_file_name
-
Read the graph definition from this file.
See also the description key to read the graph from the command line.
The whole file is slurped in as a single graph.
The first few lines of the file can start with /^\s*#/, and will be discarded as comments.
The description key takes precedence over the input_file key.
The value for input_file is passed to Graph::Easy::Marpa::Parser.
Default: ''.
- o logger => $logger_object
-
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 Graph::Easy::Marpa::Parser and to Graph::Easy::Marpa::Renderer::GraphViz2.
Default: undef.
- o maxlevel => $level
-
This option is only used if an object of type Log::Handler is created. See logger above.
See also Log::Handler::Levels.
The value for maxlevel is passed to Graph::Easy::Marpa::Parser and to Graph::Easy::Marpa::Renderer::GraphViz2.
Default: 'info'. A typical value is 'debug'.
- o minlevel => $level
-
This option is only used if an object of type Log::Handler is created. See logger above.
See also Log::Handler::Levels.
The value for minlevel is passed to Graph::Easy::Marpa::Parser and to Graph::Easy::Marpa::Renderer::GraphViz2.
Default: 'error'.
No lower levels are used.
- o output_file => $output_file_name
-
If an output file name is supplied, and a rendering object is also supplied, then this call is made:
$self -> renderer -> run(format => $self -> format, items => [$self -> items -> print], output_file => $file_name);
This is how the plotted graph is actually created.
The value for output_file is passed to Graph::Easy::Marpa::Renderer::GraphViz2.
Default: ''.
- o rankdir => $direction
-
$direction must be one of: LR or RL or TB or BT.
Specify the rankdir of the graph as a whole.
The value for rankdir is passed to Graph::Easy::Marpa::Renderer::GraphViz2.
Default: 'TB'.
- o renderer => $renderer_object
-
This is the object whose run() method will be called to render the result of parsing the input graph.
The format of the parameters passed to the renderer are documented in "run(%arg)" in Graph::Easy::Marpa::Renderer::GraphViz2, which is the default value for this object.
Default: ''.
- o report_tokens => $Boolean
-
Reports, via the log, the tokens recognized by the parser.
The value for report_tokens is passed to Graph::Easy::Marpa::Parser.
Default: 0.
- o token_file => $token_file_name
-
This is the name of the file to write containing the tokens (items) output from Graph::Easy::Marpa::Parser.
The value for token_file is passed to Graph::Easy::Marpa::Parser.
Default: 0.
Data Files and Scripts
Overview of the Data Flow
The parser works like this:
- o You use the parser Graph::Easy::Marpa::Parser directly ...
-
Call
Graph::Easy::Marpa::Parser -> new(%options)
. - o ... or, you use Graph::Easy::Marpa, which calls the parser and then the renderer
-
Call
Graph::Easy::Marpa -> new(%options)
.Of course, the renderer is only called if the parser exits without error.
Details:
- o Input a graph definition
-
This comes from the description parameter to new(), or is read from a file with the input_file parameter.
See new(input_file => $graph_file_name) or new(description => $graph_string) above for details.
A definition looks like '[node.1]{a:b;c:d}->{e:f;}->{g:h}[node.2]{i:j}->[node.3]{k:l}'.
Here, node names are: node.1, node.2 and node.3.
Edge names are: '->' for directed graphs, or '--' for undirected graphs.
Nodes and edges can have attributes, very much like CSS. The attributes in this sample are meaningless, and are just to demonstrate the syntax.
And yes, unlike the original Graph::Easy syntax, you can use a series of edges between 2 nodes, with different attributes, as above.
See http://www.graphviz.org/content/attrs for a long list of the attributes available for Graphviz.
- o Parse the graph
-
After the parser runs successfully, the parser object holds a Set::Array object of tokens representing the graph.
See "How is the parsed graph stored in RAM?" in Graph::Easy::Marpa::Parser for details.
- o Output the parsed tokens
-
See new(token_file => $csv_file_name) above for details.
- o Call the renderer
Data and Script Interaction
Sample input files for the parser are in data/*.ge. Sample output files are in data/*.tokens.
- o scripts/parse.pl and scripts/parser.sh
-
These use Graph::Easy::Marpa::Parser.
They run the parser on one *.ge input file, and produce an arrayref of items.
Run scripts/parse.pl -h for samples of how to drive it.
Try:
cat data/node.05.ge perl -Ilib scripts/parse.pl -i data/node.05.ge -t data/node.05.tokens -re 1
You can use scripts/parse.sh to simplify this process:
scripts/parse.sh data/node.05.ge data/node.05.tokens -re 1 scripts/parse.sh data/subgraph.12.ge data/subgraph.12.tokens -re 1
Methods
description([$graph_description_string])
Here, the [] indicate an optional parameter.
Get or set the string for the graph definition.
See also the input_file() method to read the graph from a file, below.
The value supplied to the description() method takes precedence over the value read from the input file.
dot_input_file([$file_name])
Here, the [] indicate an optional parameter.
Get or set the name of the file into which the rendering engine will write to input to dot (or whatever).
format([$format])
Here, the [] indicate an optional parameter.
Get or set the format of the output file, to be created by the renderer.
input_file([$graph_file_name])
Here, the [] indicate an optional parameter.
Get or set the name of the file to read the graph definition from.
See also the description() method.
The whole file is slurped in as a single graph.
The first few lines of the file can start with /^\s*#/, and will be discarded as comments.
The value supplied to the description() method takes precedence over the value read from the input file.
log($level, $s)
Calls $self -> logger -> log($level => $s) if ($self -> logger).
Up until V 1.11, this used to call $self -> logger -> $level($s), but the change was made to allow simpler loggers, meaning they did not have to implement all the methods covered by $level(). See CHANGES for details. For more on log levels, see Log::Handler::Levels.
logger([$logger_object])
Here, the [] indicate an optional parameter.
Get or set the logger object.
To disable logging, just set logger to the empty string.
This logger is passed to Graph::Easy::Marpa::Parser and Graph::Easy::Marpa::Renderer::GraphViz2.
maxlevel([$string])
Here, the [] indicate an optional parameter.
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.
minlevel([$string])
Here, the [] indicate an optional parameter.
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.
output_file([$output_file_name])
Here, the [] indicate an optional parameter.
Get or set the name of the file to which the renderer will write to resultant graph.
This is how the plotted graph is actually created.
If no renderer is supplied, or no output file is supplied, nothing is written.
rankdir([$direction])
Here, the [] indicate an optional parameter.
Get or set the rankdir of the graph as a whole.
The default is 'TB' (top to bottom).
renderer([$rendering_object])
Here, the [] indicate an optional parameter.
Get or set the rendering object.
This is the object whose run() method will be called to render the result of parsing the input file.
The format of the parameters passed to the renderer are documented in "run(%arg)" in Graph::Easy::Marpa::Renderer::GraphViz2, which is the default value for this object.
report_tokens([$Boolean])
Here, the [] indicate an optional parameter.
Get or set the flag to report, via the log, the items recognized in the tokens file.
Calls "report()" in Graph::Easy::Marpa::Parser to do the reporting.
tokens_file([$token_file_name])
Here, the [] indicate an optional parameter.
Get or set the name of the file to write containing the tokens (items) output from Graph::Easy::Marpa::Parser.
FAQ
Has anything changed moving from V 1.* to V 2.*?
Yes:
- o Input file naming
-
The test data files are shipped as data/*.ge.
Of course, you can use any input file name you wish.
- o Output file naming
-
The output files of parsed tokens are shipped as data/*.tokens.
Of course, you can use any output file name you wish.
- o Output files
-
The output files, data/*.dot, are now shipped.
What is the homepage of Marpa?
http://jeffreykegler.github.io/Ocean-of-Awareness-blog/.
How do I reconcile Marpa's approach with classic lexing and parsing?
I've included in this article a section which is aimed at helping us think about this issue.
What is the purpose of this set of modules?
It's a complete re-write of Graph::Easy, designed to make on-going support for the Graph::Easy::Marpa
language much, much easier.
What are Graph::Easy::Marpa graphs?
In short, it means a text string containing a definition of a graph, using a cleverly designed language, that can be used to describe the sort of graph you wish to plot. Then, Graph::Easy::Marpa does the plotting by calling Graph::Easy::Marpa::Renderer::GraphViz2.
See "What is the Graph::Easy::Marpa language?" in Graph::Easy::Marpa::Parser.
What do Graph::Easy::Marpa graph definitions look like?
[node_1]{color: red; style: circle} -> {class: fancy;} [node_2]{color: green;}
How are graphs stored in RAM by the parser?
See "FAQ" in Graph::Easy::Marpa::Parser.
How are attributes assigned to nodes and edges?
Since the scan of the input stream is linear, any attribute detected belongs to the nearest preceeding node(s) or edge.
How are attributes assigned to groups?
The only attributes which can be passed to a subgraph (group) are those that 'dot' accepts under the 'graph' part of a subgraph definition.
This means the attribute 'rank' cannot be passed, yet.
Is there sample data I can examine?
See data/*.ge and the corresponding data/*.tokens and html/*.svg.
Note: Some files contain deliberate mistakes. See above for scripts/parse.pl and scripts/parse.sh.
What about the fact the Graph::Easy can read various other definition formats?
I have no plans to support such formats. Nevertheless, having written these modules, it should be fairly easy to derive classes which perform that sort of work.
How to I re-generate the web page of demos?
See scripts/generate.index.pl.
What are the defaults for GraphViz2, the default rendering engine?
GraphViz2 -> new
(
edge => $class{edge} || {color => 'grey'},
global => $class{global} || {directed => 1},
graph => $class{graph} || {rankdir => $self -> rankdir},
logger => $self -> logger,
node => $class{node} || {shape => 'oval'},
verbose => 0,
)
where $class($name) is taken from the class declarations at the start of the input stream.
Machine-Readable Change Log
The file Changes was converted into Changelog.ini by Module::Metadata::Changes.
Version Numbers
Version numbers < 1.00 represent development versions. From 1.00 up, they are production versions.
Thanks
Many thanks are due to the people who worked on Graph::Easy.
Jeffrey Kegler wrote Marpa, and has been helping me via private emails.
Repository
https://github.com/ronsavage/Graph-Easy-Marpa
Support
Email the author, or log a bug on RT:
https://rt.cpan.org/Public/Dist/Display.html?Name=Graph::Easy::Marpa.
Author
Graph::Easy::Marpa was written by Ron Savage <ron@savage.net.au> in 2011.
Home page: http://savage.net.au/index.html.
Copyright
Australian copyright (c) 2011, 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 Artistic License, a copy of which is available at:
http://www.opensource.org/licenses/index.html