Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.

tools/quickbook/doc/quickbook.qbk

[part quickbook
    [version 1.1]
    [authors [de Guzman, Joel], [Niebler, Eric]]
    [copyright 2002 2004 Joel de Guzman, Eric Niebler]
    [purpose WikiWiki style documentation tool]
    [license
        Distributed under the Boost Software License, Version 1.0.
        (See accompanying file LICENSE_1_0.txt or copy at
        <ulink url="http://www.boost.org/LICENSE_1_0.txt">
            http://www.boost.org/LICENSE_1_0.txt
        </ulink>)
    ]
    [last-revision $Date: 2005/04/30 01:48:44 $]
]

[/ QuickBook Document version 1.1 ]
[/ Sept 24, 2002 ]
[/ Sept 2, 2004 ]
[/ Feb 14, 2005 ]

[/ Some links]

[def __note__       [$images/note.png]]
[def __alert__      [$images/alert.png]]
[def __tip__        [$images/tip.png]]
[def :-)            [$images/smiley.png]]
[def __spirit__     [@http://spirit.sourceforge.net Spirit]]
[def __boostbook__  [@http://www.boost.org/doc/html/boostbook.html BoostBook]]
[def __docbook__    [@http://www.docbook.org/ DocBook]]

[section:intro Introduction]

[:[*['"Why program by hand in five days what you can spend five years of your
life automating?"]]\n\n-- Terrence Parr, author ANTLR/PCCTS]

Well, QuickBook started as a weekend hack. It was originally intended to be a
sample application using __spirit__. What is it? What you are viewing now, this
documentation, is autogenerated by QuickBook. These files were generated from
one master:

[:[@../quickbook.qbk quickbook.qbk]]

Originally named QuickDoc, this funky tool that never dies evolved into a
funkier tool thanks to Eric Niebler who resurrected the project making it
generate __boostbook__ instead of HTML. The __boostbook__ documentation format
is an extension of __docbook__, an SGML- or XML- based format for describing
documentation.

QuickBook is a WikiWiki style documentation tool geared towards C++
documentation using simple rules and markup for simple formatting tasks.
QuickBook extends the WikiWiki concept. Like the WikiWiki, QuickBook documents are
simple text files. A single QuickBook document can generate a fully linked set
of nice HTML and PostScript/PDF documents complete with images and syntax-
colorized source code.

Features include:

* generate __boostbook__ xml, to generate HTML, PostScript and PDF
* simple markup to link to Doxygen-generated entities
* macro system for simple text substitution
* simple markup for italics, bold, preformatted, blurbs, code samples,
  tables, URLs, anchors, images, etc.
* automatic syntax coloring of code samples
* CSS support

[endsect]
[section:syntax Syntax Summary]

A QuickBook document is composed of one or more blocks. An example of
a block is the paragraph or a C++ code snippet. Some blocks have
special mark-ups. Blocks, except code snippets which have their own
grammar (C++ or Python), are composed of one or more phrases. A phrase
can be a simple contiguous run of characters. Phrases can have special
mark-ups. Marked up phrases can recursively contain other phrases, but
cannot contain blocks. A terminal is a self contained block-level or
phrase- level element that does not nest anything.

Blocks, in general, are delimited by two end-of-lines (the block terminator).
Phrases in each block cannot contain a block terminator. This way, syntax errors
such as un-matched closing brackets do not go haywire and corrupt anything past
a single block.

[h2 Comments]

Can be placed anywhere.

[pre
'''[/ comment (no output generated) ]'''
]

[h2 Phrase Level Elements]

[h3 Font Styles]

[pre'''
['italic], [*bold], [_underline], [^teletype]
''']

will generate:

['italic], [*bold], [_underline], [^teletype]

Like all non-terminal phrase level elements, this can of course be nested:

[pre'''
[*['bold-italic]]
''']

will generate:

[*['bold-italic]]

[h3 Simple formatting]

Simple markup for formatting text, common in many applications, is now supported:

[pre'''
/italic/, *bold*, _underline_, =teletype=
''']

will generate:

/italic/, *bold*, _underline_, =teletype=

Unlike QuickBook's standard formatting scheme, the rules for simpler alternatives
are much stricter.

* Simple markups cannot nest. You can combine a simple markup with a nestable markup.
* A non-space character must follow the leading markup
* A non-space character must precede the trailing markup
* A space or a punctuation must follow the trailing markup
* If the matching markup cannot be found within a line, the formatting
  will not be applied. This is to ensure that un-matched formatting markups,
  which can be a common mistake, does not corrupt anything past a single line.
  We do not want the rest of the document to be rendered bold just because we
  forgot a trailing '*'.
* A line starting with the star will be interpreted as an unordered list.
  See [link syntax.unordered_lists Unordered lists].

[table More Formatting Samples
    [[Markup]                                           [Result]]
    [[[^'''*Bold*''']]                                  [*Bold*]]
    [[[^'''*Is bold*''']]                               [*Is bold*]]
    [[[^'''* Not bold* *Not bold * * Not bold *''']]    [* Not bold* *Not bold * * Not bold *]]
    [[[^'''This*Isn't*Bold (no bold)''']]               [This*Isn't*Bold (no bold)]]
    [[[^'''(*Bold Inside*) (parenthesis not bold)''']]  [(*Bold Inside*) (parenthesis not bold)]]
    [[[^'''*(Bold Outside)* (parenthesis bold)''']]     [*(Bold Outside)* (parenthesis bold)]]
    [[[^'''3*4*5 = 60 (no bold)''']]                    [3*4*5 = 60 (no bold)]]
    [[[^'''3 * 4 * 5 = 60 (no bold)''']]                [3 * 4 * 5 = 60 (no bold)]]
    [[[^'''3 *4* 5 = 60 (4 is bold)''']]                [3 *4* 5 = 60 (4 is bold)]]
    [[[^'''*This is bold* this is not *but this is*''']][*This is bold* this is not *but this is*]]
    [[[^'''*This is bold*.''']]                         [*This is bold*.]]
    [[[^'''*B*. (bold B)''']]                           [*B*. (bold B)]]
    [[[^'''['*Bold-Italic*]''']]                        [['*Bold-Italic*]]]
]

[blurb __note__ Thanks to David Barrett, author of
[@http://quinthar.com/qwikiwiki/index.php?page=Home Qwiki], for sharing these samples
and teaching me these obscure formatting rules. I wasn't sure at all if __spirit__,
being more or less a formal EBNF parser, can handle the context sensitivity and ambiguity.]

[h3 Inline code]

Inlining code in paragraphs is quite common when writing C++ documentation. We
provide a very simple markup for this. For example, this:

[pre'''
This text has inlined code `int main() { return 0; }` in it.
''']

will generate:

This text has inlined code `int main() { return 0; }` in it. The code will be
syntax highlighted.

[blurb __note__
Note that we simply enclose the code with the tick: [^'''"`"'''], not the
single quote: `"'"`. Note too that [^'''`some code`'''] is prefered over
[^'''[^some code]'''].
]

[h3 Source Mode]

If a document contains more than one type of source code then the source mode
may be changed dynamically as the document is processed. All QuickBook
documents are initially in C++ mode by default, though an alternative initial value 
may be set in the [link syntax.document Document Info] section.

To change the source mode, use the [^\[source-mode\]] markup, where
=source-mode= is one of the supported modes. For example, this:

[pre'''
Python's [python] `import` is rather like C++'s [c++] `#include`. A
C++ comment `// looks like this` whereas a Python comment [python]
`# looks like this`.
''']

will generate:

Python's [python] `import` is rather like C++'s [c++] `#include`. A
C++ comment `// looks like this` whereas a Python comment [python]
`#looks like this`.

[table Supported Source Modes
    [[Mode]                 [Source Mode Markup]]
    [[C++]                  [[^\[c++\]]]]
    [[Python]               [[^\[python\]]]]
]

[blurb __note__ The source mode strings are lowercase.]

[h3 line-break]

[pre'''
[br]
''']

[blurb __note__ Note that `\n` is now preferred over `[br]`.]

[h3 Anchors]

[pre'''
[#named_anchor]
''']

A named anchor is a hook that can be referenced by a link elsewhere in the
document. You can then reference an anchor with [^'''[link named_anchor Some link text]'''].
More on anchors [link syntax.anchor_links here], [link syntax.section here] and
[link syntax.headings here].

[h3 Links]

[pre'''
[@http://www.boost.org this is [*boost's] website....]
''']

will generate:

[@http://www.boost.org this is [*boost's] website....]

URL links where the link text is the link itself is common. Example:

[pre'''
see http://spirit.sourceforge.net/
''']

so, when the text is absent in a link markup, the URL is assumed. Example:

[pre
see '''[@http://spirit.sourceforge.net/]'''
]

will generate:

see [@http://spirit.sourceforge.net/]

[h3 Anchor links]

You can link within a document using:

[pre'''
[link section_id.normalized_header_text The link text]
''']

See sections [link syntax.section Section] and [link syntax.headings Headings]
for more info.

[h3 refentry links]

In addition, you can link internally to an XML refentry like:

[pre'''
[link xml.refentry The link text]
''']

This gets converted into [^<link linkend="xml.refentry">The link text</link>].

Like URLs, the link text is optional. If this is not present, the link text will
automatically be the refentry. Example:

[pre'''
[link xml.refentry]
''']

This gets converted into [^<link linkend="xml.refentry">xml.refentry</link>].

[h3 function, class, member, enum or header links]

If you want to link to a function, class, member, enum or header in the reference
section, you can use:

[pre'''
[funcref fully::qualified::function_name The link text]
[classref fully::qualified::class_name The link text]
[memberref fully::qualified::member_name The link text]
[enumref fully::qualified::enum_name The link text]
[headerref path/to/header.hpp The link text]
''']

Again, the link text is optional. If this is not present, the link text will
automatically be the function, class, member or enum. Example:

[pre'''
[classref boost::bar::baz]
''']

would have "boost::bar::baz" as the link text.

[h3 Escape]

The escape mark-up is used when we don't want to do any processing.

[pre
\'\'\'
escape (no processing/formatting)
\'\'\'
]

Escaping allows us to pass XML markup to __boostbook__ or __docbook__. For example:

[pre
\'\'\'
<emphasis role="bold">This is direct XML markup</emphasis>
\'\'\'
]

'''
<emphasis role="bold">This is direct XML markup</emphasis>
'''

[blurb __alert__ Be careful when using the escape. The text must conform to
__boostbook__/__docbook__ syntax.]

[h3 Single char escape]

The backslash may be used to escape a single punctuation character. The
punctuation immediately after the backslash is passed without any processing.
This is useful when we need to escape QuickBook punctuations such as `[` and `]`.
For example, how do you escape the triple quote? Simple: [^\\'\\'\\']

`\n` has a special meaning. It is used to generate line breaks. Note that `\n`
is now preferred over `[br]`.

[h3 Images (terminal)]

[pre'''
[$image.jpg]
''']

[h2 Block Level Elements]

[h3 Document]

Every document must begin with a Document Info section, which should look
like this:

[pre'''
[document-type The Document Title
    [version 1.0]
    [id the_document_name]
    [dirname the_document_dir]
    [copyright 2000 2002 2003 Joe Blow, Jane Doe]
    [purpose The document's reason for being]
    [category The document's category]
    [authors [Blow, Joe], [Doe, Jane]]
    [license The document's license]
    [last-revision $Date: 2005/04/30 01:48:44 $]
    [source-mode source-type]
]
''']

Where document-type is one of:

* book
* library
* part
* article
* chapter

and =version=, =id=, =dirname=, =copyright=, =purpose=, =category=, =authors=,
=license=, =last-revision= and =source-mode= are optional information.

Here =source-type= is a lowercase string setting the initial 
[link syntax.source_mode source mode]. If the =source-mode= field is omitted, a
default value of =c++= will be used.

[h3 Section]

Starting a new section is accomplished with:

[pre'''
[section:id The Section Title]
''']

where /id/ is optional. id will be the filename of the generated section.
If it is not present, "The Section Title" will be normalized and become the id.
Valid characters are =a-Z=, =A-Z=, =0-9= and =_=. All non-valid characters are
converted to underscore and all upper-case are converted to lower case.
Thus: "The Section Title" will be normalized to "the_section_title".

End a section with:

[pre'''
[endsect]
''']

Sections can nest, and that results in a hierarchy in the table of contents.

[h3 xinclude]

You can include another XML file with:

[pre'''
[xinclude file.xml]
''']

This is useful when file.xml has been generated by Doxygen and contains your
reference section.

[h3 Paragraphs]

Paragraphs start left-flushed and are terminated by two or more newlines. No
markup is needed for paragraphs. QuickBook automatically detects paragraphs from
the context.

[h3 Ordered lists]

[pre
# One
# Two
# Three
]

will generate:

# One
# Two
# Three

[h3 List Hierarchies]

List hierarchies are supported. Example:

[pre
# One
# Two
# Three
    # Three.a
    # Three.b
    # Three.c
# Four
    # Four.a
        # Four.a.i
        # Four.a.ii
# Five
]

will generate:

# One
# Two
# Three
    # Three.a
    # Three.b
    # Three.c
# Fourth
    # Four.a
        # Four.a.i
        # Four.a.ii
# Five

[h3 Long List Lines]

Long lines will be wrapped appropriately. Example:

[pre
# A short item.
# A very long item. A very long item. A very long item.
  A very long item. A very long item. A very long item.
  A very long item. A very long item. A very long item.
  A very long item. A very long item. A very long item.
  A very long item. A very long item. A very long item.
# A short item.
]

# A short item.
# A very long item. A very long item. A very long item.
  A very long item. A very long item. A very long item.
  A very long item. A very long item. A very long item.
  A very long item. A very long item. A very long item.
  A very long item. A very long item. A very long item.
# A short item.

[h3 Unordered lists]

[pre'''
* First
* Second
* Third
''']

will generate:

* First
* Second
* Third

[h3 Mixed lists]

Mixed lists (ordered and unordered) are supported. Example:

[pre'''
# One
# Two
# Three
    * Three.a
    * Three.b
    * Three.c
# Four
''']

will generate:

# One
# Two
# Three
    * Three.a
    * Three.b
    * Three.c
# Four

And...

[pre'''
# 1
    * 1.a
        # 1.a.1
        # 1.a.2
    * 1.b
# 2
    * 2.a
    * 2.b
        # 2.b.1
        # 2.b.2
            * 2.b.2.a
            * 2.b.2.b
''']

will generate:

# 1
    * 1.a
        # 1.a.1
        # 1.a.2
    * 1.b
# 2
    * 2.a
    * 2.b
        # 2.b.1
        # 2.b.2
            * 2.b.2.a
            * 2.b.2.b

[h3 Code]

Preformatted code starts with a space or a tab. The code will be
syntax highlighted according to the current [link syntax.source_mode source mode]:

[c++]

    #include <iostream>

    int main()
    {
        // Sample code
        std::cout << "Hello, World\n";
        return 0;
    }

[python]

    import cgi

    def cookForHtml(text):
        '''"Cooks" the input text for HTML.'''
        
        return cgi.escape(text)

Macros that are already defined are expanded in source code. Example:

[pre'''
[def __syntax_highlight__ [@quickbook/highlight.html syntax_highlight]]
[def __quickbook__ [@index.html quickbook]]

    using __quickbook__::__syntax_highlight__;
''']

Generates:

[def __syntax_highlight__ [@quickbook/highlight.html syntax_highlight]]
[def __quickbook__ [@index.html quickbook]]

    using __quickbook__::__syntax_highlight__;

[h3 Preformatted]

Sometimes, you don't want some preformatted text to be parsed as C++. In such
cases, use the [^[pre ... \]] markup block.

[pre'''
[pre

    Some *preformatted* text                    Some *preformatted* text

        Some *preformatted* text            Some *preformatted* text

            Some *preformatted* text    Some *preformatted* text

]
''']

Spaces, tabs and newlines are rendered as-is. Unlike all quickbook block level
markup, pre (and Code) are the only ones that allow multiple newlines. The
markup above will generate:

[pre

Some *preformatted* text                    Some *preformatted* text

    Some *preformatted* text            Some *preformatted* text

        Some *preformatted* text    Some *preformatted* text

]

Notice that unlike Code, phrase markup such as font style is still permitted
inside =pre= blocks.

[h3 Blockquote]

[pre
'''[:sometext...]'''
]

[:Indents the paragraph. This applies to one paragraph only.]

[h3 Headings]

[pre'''
[h1 Heading 1]
[h2 Heading 2]
[h3 Heading 3]
[h4 Heading 4]
[h5 Heading 5]
[h6 Heading 6]
''']

[h1 Heading 1]
[h2 Heading 2]
[h3 Heading 3]
[h4 Heading 4]
[h5 Heading 5]
[h6 Heading 6]

Headings 1-3 [h1 h2 and h3] will automatically have anchors with normalized
names with [^name="section_id.normalized_header_text"] (i.e. valid characters are
=a-z=, =A-Z=, =0-9= and =_=. All non-valid characters are converted to underscore
and all upper-case are converted to lower-case. For example: Heading
1 in section Section 2 will be normalized to [^section_2.heading_1]). You can use:

[pre'''
[link section_id.normalized_header_text The link text]
''']

to link to them. See [link syntax.anchor_links Anchor links] and
[link syntax.section Section] for more info.

[h3 Macros]

[pre'''
[def macro_identifier some text]
''']

When a macro is defined, the identifier replaces the text anywhere in the file,
in paragraphs, in markups, etc. macro_identifier is a string of non- white space
characters except '\]' while the replacement text can be any phrase (even
marked up). Example:

[pre'''
[def sf_logo [$http://sourceforge.net/sflogo.php?group_id=28447&amp;type=1]]
sf_logo
''']

Now everywhere the sf_logo is placed, the picture will be inlined.

[def sf_logo [$http://sourceforge.net/sflogo.php?group_id=28447&type=1]]
sf_logo

[blurb __tip__ It's a good idea to use macro identifiers that are distinguishable.
For instance, in this document, macro identifiers have two leading and trailing
underscores (e.g. [^'''__spirit__''']). The reason is to avoid unwanted macro replacement.]

Links (URLS) and images are good candidates for macros. *1*) They tend to
change a lot. It is a good idea to place all links and images in one place near the top
to make it easy to make changes. *2*) The syntax is not pretty. It's easier to read and
write, e.g. [^'''__spirit__'''] than [^'''[@http://spirit.sourceforge.net Spirit]'''].

Some more examples:

[pre'''
[def :-)            [$theme/smiley.png]]
[def __spirit__     [@http://spirit.sourceforge.net Spirit]]
''']

(See [link syntax.images__terminal_ Images]
and [link syntax.links Links])

Invoking these macros:

[pre'''
Hi __spirit__  :-)
''']

will generate this:

Hi __spirit__ :-)

[h3 Predefined Macros]

Quickbook has some predefined macros that you can already use.

[table Predefined Macros
    [[Macro]                [Meaning]                       [Example]]
    [['''__DATE__''']       [Today's date]                  [__DATE__]]
    [['''__TIME__''']       [The current time]              [__TIME__]]
    [['''__FILENAME__''']   [Quickbook source filename]     [__FILENAME__]]
]

[h3 Blurbs]

[pre'''
[blurb :-) [*An eye catching advertisement or note...]\n\n
    __spirit__ is an object-oriented recursive-descent parser generator framework
    implemented using template meta-programming techniques. Expression templates
    allow us to approximate the syntax of Extended Backus-Normal Form (EBNF)
    completely in C++.
]
''']

will generate this:

[blurb :-) [*An eye catching advertisement or note...]\n\n
    __spirit__ is an object- oriented recursive-descent parser generator
    framework implemented using template meta-programming techniques. Expression
    templates allow us to approximate the syntax of Extended Backus- Normal Form
    (EBNF) completely in C++.
]

[h3 Tables]

[pre'''
[table A Simple Table
    [[Heading 1] [Heading 2] [Heading 3]]
    [[R0-C0]     [R0-C1]     [R0-C2]]
    [[R1-C0]     [R1-C1]     [R1-C2]]
    [[R2-C0]     [R2-C1]     [R2-C2]]
]
''']

will generate:

[table A Simple Table
    [[Heading 1] [Heading 2] [Heading 3]]
    [[R0-C0]     [R0-C1]     [R0-C2]]
    [[R2-C0]     [R2-C1]     [R2-C2]]
    [[R3-C0]     [R3-C1]     [R3-C2]]
]

The first row of the table is automatically treated as the table header; that is,
it is wrapped in [^<thead>...</thead>] XML tags. Note that unlike the original QuickDoc,
the columns are nested in [ cells... ]. The syntax is free-format and allows big
cells to be formatted nicely. Example:

[pre'''
[table Table with fat cells
    [[Heading 1] [Heading 2]]
    [
        [Row 0, Col 0: a small cell]
        [
            Row 0, Col 1:
            A very big cell...A very big cell...A very big cell...
            A very big cell...A very big cell...A very big cell...
            A very big cell...A very big cell...A very big cell...
        ]
    ]
    [
        [Row 1, Col 0: a small cell]
        [Row 1, Col 1: a small cell]
    ]
]
''']

and thus:

[table Table with fat cells
    [[Heading 1] [Heading 2]]
    [
        [Row 0, Col 0: a small cell]
        [
            Row 0, Col 1:
            A very big cell...A very big cell...A very big cell...
            A very big cell...A very big cell...A very big cell...
            A very big cell...A very big cell...A very big cell...
        ]
    ]
    [
        [Row 1, Col 0: a small cell]
        [Row 1, Col 1: a small cell]
    ]
]

[h3 Variable Lists]

[pre'''
[variablelist A Variable List
    [[term 1] [The definition of term 1]]
    [[term 2] [The definition of term 2]]
    [[term 3] [The definition of term 3]]
]
''']

will generate:

[variablelist A Variable List
    [[term 1] [The definition of term 1]]
    [[term 2] [The definition of term 2]]
    [[term 3] [The definition of term 3]]
]

The rules for variable lists are the same as for tables, except that
only 2 "columns" are allowed. The first column contains the terms, and
the second column contains the definitions. Those familiar with HTML
will recognize this as a "definition list".

[endsect]
[section:ref Quick Reference]

[table Syntax Compendium
    [[To do this...]        [Use this...]]
    [[comment]              [[^'''[/ some comment]''']]]
    [[['italics]]           [[^'''['italics] or /italics/''']]]
    [[[*bold]]              [[^'''[*bold] or *bold*''']]]
    [[[_underline]]         [[^'''[_underline] or _underline_''']]]
    [[[^teletype]]          [[^'''[^teletype] or =teletype=''']]]
    [[source mode]          [[^\[c++\]] or [^\[python\]]]]
    [[inline code]          [[^'''`int main();`''']]]
    [[line break]           [[^'''[br]''']]]
    [[line break]           [[^'''\n''']]]
    [[anchor]               [[^'''[#anchor]''']]]
    [[link]                 [[^'''[@http://www.boost.org Boost]''']]]
    [[anchor link]          [[^'''[link section.anchor Link text]''']]]
    [[refentry link]        [[^'''[link xml.refentry Link text]''']]]
    [[function link]        [[^'''[funcref fully::qualified::function_name Link text]''']]]
    [[class link]           [[^'''[classref fully::qualified::class_name Link text]''']]]
    [[member link]          [[^'''[memberref fully::qualified::member_name Link text]''']]]
    [[enum link]            [[^'''[enumref fully::qualified::enum_name Link text]''']]]
    [[header link]          [[^'''[headerref path/to/header.hpp Link text]''']]]
    [[escape]               [[^\'\'\'escaped text (no processing/formatting)\'\'\']]]
    [[single char escape]   [[^\\c]]]
    [[images]               [[^'''[$image.jpg]''']]]
    [[begin section]        [[^'''[section The Section Title]''']]]
    [[end section]          [[^'''[endsect]''']]]
    [[paragraph]            [No markup. Paragraphs start left-flushed and are terminated by two or more newlines.]]
    [[ordered list]         [[^# one\n# two\n# three\n]]]
    [[unordered list]       [[^\* one\n\* two\n\* three\n]]]
    [[code]                 [No markup. Preformatted code starts with a space or a tab.]]
    [[preformatted]         [[^'''[pre preformatted]''']]]
    [[block quote]          [[^'''[:sometext...]''']]]
    [[heading 1]            [[^'''[h1 Heading 1]''']]]
    [[heading 2]            [[^'''[h2 Heading 2]''']]]
    [[heading 3]            [[^'''[h3 Heading 3]''']]]
    [[heading 4]            [[^'''[h4 Heading 4]''']]]
    [[heading 5]            [[^'''[h5 Heading 5]''']]]
    [[heading 6]            [[^'''[h6 Heading 6]''']]]
    [[macro]                [[^'''[def macro_identifier some text]''']]]
    [[blurb]                [[^'''[blurb advertisement or note...]''']]]
    [[table]                [[^[table Title\n \[\[a\]\[b\]\[c\]\]\n    \[\[a\]\[b\]\[c\]\]\n\]]]]
    [[variablelist]         [[^[variablelist Title\n \[\[a\]\[b\]\]\n    \[\[a\]\[b\]\]\n\]]]]
]

[endsect]
[section:docinfo Library Document Grammar]

[c++]

    doc_info =
            space
        >>  '['
        >>  (   str_p("book")
            |   "article"
            |   "library"
            |   "chapter"
            |   "part"
            )
        >> hard_space
        >>  (  *(anychar_p -
                (ch_p('[') | ']' | eol_p)
                )
            )
        >> *( doc_version
            | doc_id
            | doc_dirname
            | doc_copyright
            | doc_purpose
            | doc_category
            | doc_authors
            | doc_license
            | doc_last_revision
            )
        >> ']' >> +eol_p
        ;

    doc_version =
            space
        >> "[version" >> hard_space
        >> (*(anychar_p - ']'))
        >> ']' >> +eol_p
        ;

    doc_id =
            space
        >> "[id" >> hard_space
        >> (*(anychar_p - ']'))
        >> ']' >> +eol_p
        ;

    doc_dirname =
            space
        >> "[dirname" >> hard_space
        >> (*(anychar_p - ']'))
        >> ']' >> +eol_p
        ;

    doc_copyright =
            space
        >> "[copyright" >> hard_space
        >> +( repeat_p(4)[digit_p]
              >> space
            )
        >> space
        >> (*(anychar_p - ']'))
        >> ']' >> +eol_p
        ;

    doc_purpose =
            space
        >> "[purpose" >> hard_space
        >> (*(anychar_p - ']'))
        >> ']' >> +eol_p
        ;

    doc_category =
            space
        >> "[category" >> hard_space
        >> (*(anychar_p - ']'))
        >> ']' >> +eol_p
        ;

    doc_author =
            space
        >>  '[' >> space
        >>  (*(anychar_p - ','))
        >>  ',' >> space
        >>  (*(anychar_p - ']'))
        >>  ']'
        ;

    doc_authors =
            space
        >> "[authors" >> hard_space
        >> doc_author
        >> *(   ','
                >>  doc_author
            )
        >> ']' >> +eol_p
        ;

    doc_license =
            space
        >> "[license" >> hard_space
        >> (*(anychar_p - ']'))
        >> ']' >> +eol_p
        ;

    doc_last_revision =
            space
        >> "[last-revision" >> hard_space
        >> (*(anychar_p - ']'))
        >> ']' >> +eol_p
        ;

    doc_source_mode =
        space
        >> "[source-mode" >> hard_space
        >> (
              str_p("c++") 
           |  "python"
           )
        >> space >> ']' >> +eol_p
        ;

    comment =
        "[/" >> *(anychar_p - ']') >> ']'
        ;

    space =
        *(space_p | comment)
        ;

    hard_space =
        (eps_p - (alnum_p | '_')) >> space  // must not be followed by
        ;                                   // alpha-numeric or underscore

[endsect]
[section:quickbook QuickBook Grammar]

    library =
        *(space_p | comment) >> blocks >> blank
        ;

    blocks =
       +(   block_markup
        |   code
        |   list
        |   hr
        |   comment >> *eol
        |   paragraph
        |   eol
        )
        ;

    space =
        *(space_p | comment)
        ;

    blank =
        *(blank_p | comment)
        ;

    eol = blank >> eol_p
        ;

    close_bracket =
        ']' |
        if_p(var(is_not_preformatted))
        [
            eol_p >> eol_p                  // Make sure that we don't go
        ]                                   // past a single block, except
        ;                                   // when preformatted.

    hard_space =
        (eps_p - (alnum_p | '_')) >> space  // must not be followed by
        ;                                   // alpha-numeric or underscore

    comment =
        "[/" >> *(anychar_p - ']') >> ']'
        ;

    hr =
        str_p("----")
        >> *(anychar_p - eol)
        >> +eol
        ;

    block_markup =
            '['
        >>  (   begin_section
            |   end_section
            |   headings
            |   blurb
            |   blockquote
            |   preformatted
            |   def_macro
            |   table
            |   variablelist
            |   xinclude
            )
        >>  (   (']' >> +eol)
            |   eps_p
            )
        ;

    begin_section =
           "section"
        >> hard_space
        >>  (':' >> (*(alnum_p | '_'))
            | eps_p
            )
        >> (*(anychar_p -
                close_bracket))
        ;

    end_section =
        str_p("endsect")
        ;

    headings =
        h1 | h2 | h3 | h4 | h5 | h6
        ;

    h1 = "h1" >> hard_space >> phrase
    h2 = "h2" >> hard_space >> phrase
    h3 = "h3" >> hard_space >> phrase
    h4 = "h4" >> hard_space >> phrase
    h5 = "h5" >> hard_space >> phrase
    h6 = "h6" >> hard_space >> phrase

    blurb =
        "blurb" >> hard_space
        >> phrase
        ;

    blockquote =
        ':' >> blank >>
        phrase
        ;

    preformatted =
        "pre" >> hard_space
        >> !eol >> phrase
        >> eps_p
        ;

    def_macro =
        "def" >> hard_space
        >> identifier
        >> blank >> phrase
        ;

    table =
        "table" >> hard_space
        >>  (*(anychar_p - eol))
        >>  +eol
        >>  *table_row
        >>  eps_p
        ;

    table_row =
        space
        >>  ch_p('[')
        >>
        (
            (
                *table_cell
                >>  ch_p(']')
                >>  space
            )
            | eps_p
        )
        ;

    table_cell =
        space
        >>  ch_p('[')
        >>
        (
            (
                phrase
                >>  ch_p(']')
                >>  space
            )
            | eps_p
        )
        ;

    variablelist =
        "variablelist" >> hard_space
        >>  (*(anychar_p - eol))
        >>  +eol
        >>  *varlistentry
        >>  eps_p
        ;

    varlistentry =
        space
        >>  ch_p('[')
        >>
        (
            (
                varlistterm
                >> +varlistitem
                >>  ch_p(']')
                >>  space
            )
            | eps_p
        )
        ;

    varlistterm =
        space
        >>  ch_p('[')
        >>
        (
            (
                phrase
                >>  ch_p(']')
                >>  space
            )
            | eps_p
        )
        ;

    varlistitem =
        space
        >>  ch_p('[')
        >>
        (
            (
                phrase
                >>  ch_p(']')
                >>  space
            )
            | eps_p
        )
        ;

    xinclude =
           "xinclude"
        >> hard_space
        >> (*(anychar_p -
                close_bracket))
        ;

    identifier =
        *(anychar_p - (space_p | ']'))
        ;

    source_mode =
       (
           str_p("c++")
           |   "python"
       )
       ;
                
    code =
        (
            code_line
            >> *(*eol >> code_line)
        )
        >> +eol
        ;

    code_line =
        ((ch_p(' ') | '\t'))
        >> *(anychar_p - eol) >> eol
        ;

    list =
        eps_p(ch_p('*') | '#') >>
       +(
            (*blank_p
            >> (ch_p('*') | '#'))
            >> *blank_p
            >> list_item
        )
        ;

    list_item =
       *(   common
        |   (anychar_p -
                (   eol_p >> *blank_p >> eps_p(ch_p('*') | '#')
                |   (eol >> eol)
                )
            )
        )
        >> +eol
        ;

    common =
            self.actions.macro
        |   phrase_markup
        |   inline_code
        |   simple_format
        |   escape
        |   comment
        ;

    inline_code =
        '`' >>
        (
           *(anychar_p -
                (   '`'
                |   (eol >> eol)            // Make sure that we don't go
                )                           // past a single block
            ) >> eps_p('`')
        )
        >>  '`'
        ;

    simple_format =
            simple_bold
        |   simple_italic
        |   simple_underline
        |   simple_teletype
        ;

    simple_bold =
        '*' >>
        (
            (   graph_p >>                  // graph_p must follow '*'
                *(anychar_p -
                    (   eol                 // Make sure that we don't go
                    |   (graph_p >> '*')    // past a single line
                    )
                ) >> graph_p                // graph_p must precede '*'
                >> eps_p('*'
                    >> (space_p | punct_p)) // space_p or punct_p must
            )                               // follow '*'
        |   (
                graph_p                     // A single char. e.g. *c*
                >> eps_p('*'
                    >> (space_p | punct_p))
            )
        )
        >> '*'
        ;

    simple_italic =
        '/' >>
        (
            (   graph_p >>                  // graph_p must follow '/'
                *(anychar_p -
                    (   eol                 // Make sure that we don't go
                    |   (graph_p >> '/')    // past a single line
                    )
                ) >> graph_p                // graph_p must precede '/'
                >> eps_p('/'
                    >> (space_p | punct_p)) // space_p or punct_p must
            )                               // follow '/'
        |   (
                graph_p                     // A single char. e.g. /c/
                >> eps_p('/'
                    >> (space_p | punct_p))
            )
        )
        >> '/'
        ;

    simple_underline =
        '_' >>
        (
            (   graph_p >>                  // graph_p must follow '_'
                *(anychar_p -
                    (   eol                 // Make sure that we don't go
                    |   (graph_p >> '_')    // past a single line
                    )
                ) >> graph_p                // graph_p must precede '_'
                >> eps_p('_'
                    >> (space_p | punct_p)) // space_p or punct_p must
            )                               // follow '_'
        |   (
                graph_p                     // A single char. e.g. _c_
                >> eps_p('_'
                    >> (space_p | punct_p))
            )
        )
        >> '_'
        ;

    simple_teletype =
        '=' >>
        (
            (   graph_p >>                  // graph_p must follow '='
                *(anychar_p -
                    (   eol                 // Make sure that we don't go
                    |   (graph_p >> '=')    // past a single line
                    )
                ) >> graph_p                // graph_p must precede '='
                >> eps_p('='
                    >> (space_p | punct_p)) // space_p or punct_p must
            )                               // follow '='
        |   (
                graph_p                     // A single char. e.g. =c=
                >> eps_p('='
                    >> (space_p | punct_p))
            )
        )
        >> '='
        ;

    paragraph =
       *(   common
        |   (anychar_p -                    // Make sure we don't go past
                (eol >> eol)                // a single block.
            )
        )
        >> +eol
        ;

    phrase =
       *(   common
        |   comment
        |   (anychar_p -
                close_bracket)
        )
        ;

    phrase_markup =
            '['
        >>  (   image
            |   url
            |   link
            |   anchor
            |   source_mode
            |   funcref
            |   classref
            |   memberref
            |   enumref
            |   headerref
            |   bold
            |   italic
            |   underline
            |   teletype
            |   str_p("br")
            )
        >>  ']'
        ;

    escape =
            str_p("\\n")
        |   '\\' >> punct_p
        |   (
                "'''" >> !eol
            >>  *(anychar_p - "'''")
            >>  "'''"
            )
        ;

    image =
            '$' >> blank
        >> (*(anychar_p -
                close_bracket))
        ;

    url =
            '@'
        >>  (*(anychar_p -
                (']' | hard_space)))
        >>  (   eps_p(']')
            |   (hard_space >> phrase)
            )
        ;

    link =
            "link" >> hard_space
        >>  (*(anychar_p -
                (']' | hard_space)))
        >>  (   eps_p(']')
            |   (hard_space >> phrase)
            )
        ;

    anchor =
            '#'
        >>  blank
        >>  (   *(anychar_p -
                    close_bracket)
            )
        ;

    funcref =
        "funcref" >> hard_space
        >>  (*(anychar_p -
                (']' | hard_space)))
        >>  (   eps_p(']')
            |   (hard_space >> phrase)
            )
        ;

    classref =
        "classref" >> hard_space
        >>  (*(anychar_p -
                (']' | hard_space)))
        >>  (   eps_p(']')
            |   (hard_space >> phrase)
            )
        ;

    memberref =
        "memberref" >> hard_space
        >>  (*(anychar_p -
                (']' | hard_space)))
        >>  (   eps_p(']')
            |   (hard_space >> phrase)
            )
        ;

    enumref =
        "enumref" >> hard_space
        >>  (*(anychar_p -
                (']' | hard_space)))
        >>  (   eps_p(']')
            |   (hard_space >> phrase)
            )
        ;

    headerref =
        "headerref" >> hard_space
        >>  (*(anychar_p -
                (']' | hard_space)))
        >>  (   eps_p(']')
            |   (hard_space >> phrase)
            )
        ;

    bold =
            ch_p('*')
        >>  blank >> phrase
        ;

    italic =
            ch_p('\'')
        >>  blank >> phrase
        ;

    underline =
            ch_p('_')
        >>  blank >> phrase
        ;

    teletype =
            ch_p('^')
        >>  blank >> phrase
        ;

[endsect]
[section:highlight C++ Syntax Highlighting Grammar]

    program
        =
        *(  macro
        |   preprocessor
        |   comment
        |   keyword
        |   identifier
        |   special
        |   string_
        |   char_
        |   number
        |   space_p
        |   anychar_p
        )
        ;

    macro
        =   *space_p >> self.macro
        ;

    preprocessor
        =   *space_p >> '#' >> ((alpha_p | '_') >> *(alnum_p | '_'))
        ;

    comment
        =   +(*space_p >> (comment_p("//") | comment_p("/*", "*/")))
        ;

    keyword
        =   *space_p >> keyword_ >> (eps_p - (alnum_p | '_'))
        ;   // make sure we recognize whole words only

    keyword_
        =   "and_eq", "and", "asm", "auto", "bitand", "bitor",
            "bool", "break", "case", "catch", "char", "class",
            "compl", "const_cast", "const", "continue", "default",
            "delete", "do", "double", "dynamic_cast",  "else",
            "enum", "explicit", "export", "extern", "false",
            "float", "for", "friend", "goto", "if", "inline",
            "int", "long", "mutable", "namespace", "new", "not_eq",
            "not", "operator", "or_eq", "or", "private",
            "protected", "public", "register", "reinterpret_cast",
            "return", "short", "signed", "sizeof", "static",
            "static_cast", "struct", "switch", "template", "this",
            "throw", "true", "try", "typedef", "typeid",
            "typename", "union", "unsigned", "using", "virtual",
            "void", "volatile", "wchar_t", "while", "xor_eq", "xor"
        ;

    special
        =   *space_p >> +chset_p("~!%^&*()+={[}]:;,<.>?/|\\-")
        ;

    string_
        =   *space_p >> !as_lower_d['l'] >> confix_p('"', *c_escape_ch_p, '"')
        ;

    char_
        =   *space_p >> !as_lower_d['l'] >> confix_p('\'', *c_escape_ch_p, '\'')
        ;

    number
        =   *space_p >>
            (   as_lower_d["0x"] >> hex_p
            |   '0' >> oct_p
            |   real_p
            )
            >>  *as_lower_d[chset_p("ldfu")]
        ;

    identifier
        =   *space_p >> ((alpha_p | '_') >> *(alnum_p | '_'))
        ;

[endsect]
[section:pyhighlight Python Syntax Highlighting Grammar]

[c++]

     program
         =
         *(  macro
         |   comment
         |   keyword
         |   identifier
         |   special
         |   string_
         |   number
         |   space_p
         |   anychar_p
         )
         ;

    macro
        =   *space_p >> self.macro
        ;

     comment
         =   +(*space_p >> comment_p("#"))
         ;

     keyword
         =   *space_p >> keyword_ >> (eps_p - (alnum_p | '_'))
         ;   // make sure we recognize whole words only

     keyword_
         =
         "and",       "del",       "for",       "is",        "raise",    
         "assert",    "elif",      "from",      "lambda",    "return",   
         "break",     "else",      "global",    "not",       "try",  
         "class",     "except",    "if",        "or",        "while",    
         "continue",  "exec",      "import",    "pass",      "yield",   
         "def",       "finally",   "in",        "print",

         // Technically "as" and "None" are not yet keywords (at Python
         // 2.4). They are destined to become keywords, and we treat them 
         // as such for syntax highlighting purposes.
                    
         "as", "None"
         ;

     special
         =   *space_p >> +chset_p("~!%^&*()+={[}]:;,<.>/|\\-")
         ;

     string_prefix
         =    as_lower_d[str_p("u") >> ! str_p("r")]
         ;
                
     string_
         =   *space_p >> ! string_prefix >> (long_string | short_string)
         ;

     short_string
         =   confix_p('"', * c_escape_ch_p, '"') |
             confix_p('\'', * c_escape_ch_p, '\'')    
         ;
            
     long_string
         =   confix_p("'''", * lex_escape_ch_p, "'''") |
             confix_p("\"\"\"", * lex_escape_ch_p, "\"\"\"")
         ;
                
     number
         =   *space_p >>
             (
                 as_lower_d["0x"] >> hex_p
             |   '0' >> oct_p
             |   real_p
             )
             >>  *as_lower_d[chset_p("lj")]
         ;

     identifier
         =   *space_p >> ((alpha_p | '_') >> *(alnum_p | '_'))
         ;

[endsect]