=head1 NAME

Bigtop::Docs::Syntax - An introduction to Bigtop syntax description

=head1 Intro

This document explains the basic structure of a bigtop file.

Note that you might find L<Bigtop::Docs::Cookbook> useful depending on
the complexity of your questions and how you like to use docs.  For a
full list of Bigtop keywords, see L<Bigtop::Docs::FullKeywords>.  A
shorter version is available in L<Bigtop::Docs::QuickKeywords>.
To know what each backend does, and how to configure them, see
L<Bigtop::Docs::AutoBackends>.  All of those, except the cookbook,
are generated from the official source of Bigtop keywords (Bigtop::Keywords)
and so are up to date.

Other docs are available, including docs on tentmaker.  See
L<Bigtop::Docs::TOC> for a complete list of documentation.

=head1 Anatomy of a Bigtop File

Bigtop files are designed to be easy to write and to read (by you and the
computer).  There is a basic structure based on brace delimited blocks,
but it's not complicated like a programming language.  It's a descriptive
language.  There is no flow of control.  That means that you can
put things in whatever order you like, except that config comes first
and some recipients of the generated files may care about order.  For
instance, your command line SQL tool probably expects to see the
definition for a table before it sees any foreign keys pointing to that
table.  These orderings are usually fairly intuitive, especially when that
other program complains about missing definitions, etc.  (Further, if
you use L<Kickstart Syntax>, Bigtop will adjust the order to account
for foreign keys.)

The following skeleton is the smallest legal bigtop file which describes
almost nothing (and will do nothing if you feed it to bigtop):

    config {}
    app App::Name {}

=head2 config Section

At the top level there are two sections in a Bigtop file.  The order is
enforced.  First comes config.  It lists things that make the output
specific.  In it, there are statements and backend blocks.  Each statement
can take exactly one value.  If there are any characters that Perl wouldn't
like in an identifier, enclose the value in back ticks, a.k.a. backquotes,
(the quote usually found under tilde, not the ones on the same key with
double quotes).

The available config statements are described briefly in
L<Bigtop::Docs::QuickKeywords> and in more detail in
L<Bigtop::Docs::FullKeywords>.  There are two keywords which have
been deprecated and so do not appear there.  These are sometimes useful
for testing, so I've described them here:

=over 4

=item base_dir

Deprecated.

Optional, defaults to the current directory.  Ignored with a warning except
in create mode.

A path to where the app will be built.  Enclose paths in backquotes.  Example:

    base_dir `/home/phil/play`;

=item app_dir

Deprecated.

Optional, defaults to the h2xs style directory name for your app.  Ignored
with a warning except in create mode.

A path relative to base_dir where Build.PL, Changes, README, etc. will live.
For example, if your app block looks like this:

    app MyNS::Apps::Name

the default will be MyNS-Apps-Name under the base_dir.  If you wanted
extra nesting you could say:

    app_dir `MyNS/Apps/Name`;

then bigtop would make those intervening directories for you.

=back

In addition to these hard coded keys, there are backend blocks which
depend on what Bigtop:: modules you have installed.  These typically
generate files on the disk, which could be Perl modules, httpd.confs, etc.

The system is simplistic and best described by an example.  Suppose you list

    SomeType  SomeBackend {}

in the config section.  Bigtop will assume the following (yes, I know how
dangerous assumptions can be):

=over 4

=item *

You have a package called Bigtop::Backend::SomeType::SomeBackend, defined in
the usual way, which is installed on your system.  (i.e. There is a file
called SomeBackend.pm which defines the package
Bigtop::Backend::SomeType::SomeBackend, which lives in
the path Bigtop/Backend/SomeType/SomeBackend.pm, relative to an
@INC member.)

=item *

That package has a method called gen_SomeType which does whatever backends
of this type should do (it might make .pm files, .conf files, .sql files
etc.).  This allows bigtop to call gen_SomeType when the user types:

    bigtop file.bigtop SomeType

=back

The distribution comes with a number of these Bigtop::Backends.
[ See L<Bigtop::Docs::AuotBackends> for a list. ]  If you write a useful one,
please send it in so we can include it in a future release.  For advice
on writing one, see L<Bigtop::Docs::Modules>.

As a user, you can mark a file as not to be generated by saying:

    SomeType SomeBackend { no_gen 1; }

This serves as a reminder that you generated SomeType in the past, but
have messed with the result (even though you were probably warned not to).
But, more importantly, it allows SomeBackend to register the keywords it
handles, so their absence doesn't generate parse errors.

Most backends also honor the template statement.  If you say:

    SomeType SomeModule { template my_template.tt; }

Bigtop::Backend::SomeType::SomeModule will use C<my_template.tt> instead of
the one hard coded inside it.  Note that the template must be directly
usable by Template Toolit.  Further, it needs to define the same blocks
as the backend's normal template.  It's usually best to start by copying
the template from the here doc in backend into a file, then modify
it.

That is all there is to the config section.  A typical one looks
like this:

    config {
        # engine          MP13;
        engine          MP20;
        template_engine TT;
        Init            Std             {}
        SQL             Postgres        {}
        Control         Gantry          {}
        Model           GantryDBIxClass {}
    }

Note that one engine statement is commented out.  A comment is any line
whose first non-whitespace character is a pound sign.

=head2 app Section

The app section is far more interesting than the config section.  This is
where you describe the data in your application and how you want the
user to view and manipulate it.  This is the heart of the Bigtop file.
Theoretically, you can completely recast the app (say by exchanging
Postgres for mysql, Catalyst for Gantry, mod_perl 1.3 for mod_perl 2.0,
etc.) without changing the app section.  Whether you can do that in
practice depends on whether there are backends for the system you want
to move to (if you are interested in writing backends, see
L<Bigtop::Docs::Modules> for some pointers).  Reality also impinges on
this ideal.  Some backends understand different keywords, because
they work with different concepts.

In the app section, there are two key components:

=over 4

=item Blocks

Most blocks look like this:

    block_type Name {
        ... statements or blocks
    }

Controller and method blocks are exceptions.  These have a type property
(the type is required for methods, but is optional for controllers):

    method name is stub { ... }

The legal values of this property are specified in the
Bigtop::Backend::Control:: backend you choose.  See it's docs for a
list of the types and what they mean, but the trivial type, C<stub>,
is always supported.

=item Statements

Some examples of statements:

    label          Description;
    label          `First Name`;
    header_options Add => `$site->location . q!/add!`;
    cols           first_name, last_name, age;

A statement is a legal keyword followed by a value and terminated with a
semi-colon.  Legal values are numbers, valid Perl idents (including colons),
anything you enclose in backward quotes (see 'A Note About Quotes in Strings'
if you need to embed quotes in strings), and comma separated lists of
the above.

Note that we sometimes use => instead of comma, they mean substantially
different things.  Only use => when told to.  Always use the => when told to.
Here's the difference.  In the grammar, comma is the separator for items
in a list, while the fat comma (=>) forms a pair which becomes a single
element in the list.  If your backend is expecting two items and it
gets one pair instead, it will be sorely confused.  Likewise, if your backend
is expecting a pair, but you give it two items separated by comma, it will be
just as confused.  This is different from the way Perl treats the fat
comma.  Remember: in Bigtop a fat comma makes a pair a comma never does.

Which keywords are legal depends on which backends you are using.
Whether a particular keyword's value will work is up to the backend and to
whatever program ends up receiving what the backend produced.

A Note About Quotes in Strings:

You can put whatever you like into backquoted strings (as long as you don't
like backquotes).  But if you put quotes in such strings, you may need to
escape them in some way.  For example, if the string is a label for
html presentation, your backend will likely take your:

    label `Customer's Name`;

and make it something like:

    some_display_function('Customer's Name');

This will not work, since the generated Perl now has an extra single quote.
Usually you avoid this by protecting the quote like this:

    label `Customer\'s Name';

This results in the correct final output:

    some_display_function('Customer\'s Name');

You must read the backend documentation to find out what will happen
to the value you provide, but the above is typical.

In particular, if the statement's value is Perl code, you probably want
to use q or qq operators for quoting instead of single or double quotes.
Otherwise, tentmaker may become confused about your values, since it must
embed them in Javascript enabled HTML.

[ Note for those who read tests as examples:  In the tests you will
see quotes protected by two backslashes.  This is because the tests
use here documents to build Bigtop input.  The first backslash is
eaten by the heredoc processor.  Since you will supply input from 
file (at least most of the time), you should not need two backslashes. ]

=back

The general structure of the app section is:

    app App::Name { }

In fact, that is a valid specification, but it doesn't do much (you could
generate Init for such an app, but that would do slightly less than h2xs).

Inside the braces there are statements and blocks.  Again, the
statements are described in L<Bigtop::Docs::QuickKeywords> and
L<Bigtop::Docs::FullKeywords>.

Currently there are five legal block types at the app level: sequence,
config, table, join_table, and controller.  These are described
below.  

There are also several literal statements which dump their string values
directly to generated output files.  See L<Bigtop::Docs::QuickKeywords>
or L<Bigtop::Docs::FullKeywords> for a list of legal literal types and
explanations of where their output goes.

=over 4

=item sequence

(understood by Bigtop::Backend::SQL::*, Bigtop::Backend::Model::*,
and some Bigtop::Backend::Control::* modules)

If you are going to generate default id's from sequences in PostgreSQL,
use this to declare the sequence.  Give the sequence a name and a block:

    sequence address_seq {}

Currently the block must be empty (but it might eventually allow you to
specify things like starting value, increment, etc.).

=item config

(understood by Bigtop::Backend::Conf::*, Bigtop::Backend::HttpdConf::*,
and Bigtop::Backend::CGI::*)

[ For historical reasons set_vars can be used as a synonym for config.
That use is deprecated. ]

This allows you to dump config parameters into your Gantry::Conf instance
config file, PerlSetVar statements into the root location for your app in
your httpd.conf, or the equivalent in your CGI dispatching script or stand
alone server.  Simply list the name of a variable and its value in each
statement (remember to use backquotes):

    config {
        dbconn `dbi:Pg:dbname=yourdb` => no_accessor;
        dbuser `some_user`            => no_accessor;

        smtp_host `smtp.example.com`;
    }

If you tag the statement with => no_accessor, the controller backend
will skip making an accessor for the variable (thus assuming that your
framework is handling it).  It will also omit fishing the parameter from
the config info into the site object in the controller's generated init
method.

Note that all the backends which understand config blocks allow a gen_root
statement in their backend block in the bigtop config section.  It will
manufacture a root parameter with a relative path to the generated html
templates.

You can have multiple config blocks.  One of them must have either no name
(as shown above), or be called 'base'.  The others can named with any valid
Perl ident.  A second config block might look like this:

    config prod {
        dbconn `dbi:Pg:dbname=proddb;host=ourdb.example.com`;
    }

This results in a second conf instance for Gantry::Conf and alternate
files for other approaches (like two cgi scritps or two files ready for
inclusion in httpd.conf).

All of the config values are inherited from the unnamed config block.
Parameters defined in a named config block override or augment those
inherited values.

=item table

(understood by Bigtop::Backend::SQL::*, Bigtop::Backend::Model::*,
and Bigtop::Backend::Control::*)

The general structure of a table is:

    table name { }

Inside you can list either statements or field blocks.

    field name { }

The field block can contain only statements.

=item join_table

Join tables are used to connect two other tables in a many-to-many
relationship.  For example, a book can have multiple authors while an
author can have multiple books.  A joining table for this set-up has
two foreign keys one to author and the other to book.

Join table blocks have statements and allow field blocks just as other
tables do.

=item controller

    controller Control::Module [ is type ] { ... }

The type is optional and defaults to stub.  Nothing special happens for stubs.

Controllers allow statements and literal statements.  They also contain
method and config blocks (see below).

There are four controller types:

=over 4

=item AutoCRUD

(understood by Bigtop::Backend::Control::Gantry)

The Gantry Control backend puts Gantry::Plugins::AutoCRUD into your
use list (so don't put it there yourself, or it will appear twice in
the output).

=item CRUD

(understood by Bigtop::Backend::Control::Gantry)

Puts Gantry::Plugins::CRUD in your use list (so don't put it there
yourself).  Also generates a mass of code stubs to get you started
with semi-automated CRUD.  See "How do I use Gantry's CRUD?" in
Gantry::Docs::FAQ for details.

=item stub

(understood by Bigtop::Backend::Control::*)

This has no effect and is provided solely for symmetry.

This is the default, so:

    controller MySpecialOne is stub {
    }

is exactly equivalent to

    controller MySpecialOne {
    }

=item base_controller

You may have one base_controller in your bigtop file.  Use it if you
want to include non-default things in the apps's base module.  To replace
the default behavior, you need at least this:

    controller is base_controller {
        method do_main is base_links {
            title `Your Choice`;
        }
        method site_links is links {}
    }

Once you do that, you should put any app level location or uses statement
inside the block.  You may not use rel_location inside a base controller,
but most other statements will work as they would for any other controller.
Further, there is no restriction on methods types in either base
controllers or regular controllers.

It is unwise to include multiple base controllers, no error will be
reported, but strange things will surely happen.

=back

There are two blocks for controllers:

=over 4

=item config

(part of the grammar understood by Bigtop::Backend::Conf::General,
Bigtop::Backend::Control::Gantry and Bigtop::Backend::HttpdConf::Gantry)

[ For historical reasons set_vars can be used as a synonym for config.
That use is deprecated. ]

This block works like the app level config block, but dumps its
variables into the location for the controller.  The same rules for
named blocks apply.  There must be an unnamed block (well, you could call
it 'base').  Other blocks need names, and their names should match
the app level named blocks (if there are any).  Then parameters in the
named blocks augment or override the ones in the base block.

=item method

    method name is type { ... }

What goes in the block is controlled by the type (and how the backend
treats it).  Everything in the block must be a statement.

=back

=back

=head1 AUTHOR

Phil Crow E<lt>crow.phil@gmail.comE<gt>

=cut
