The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

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