Spirit QuickDoc C++ documentation tool

    "Why program by hand in five days what you can spend five years of your life
    automating?"

    -- Terrence Parr, author ANTLR/PCCTS

Well, QuickDoc was done over the weekend, thanks to Spirit, which is just over a
year old... What is it? Here's a sample set of HTML documents autogenerated by
QuickDoc:

    http://spirit.sf.net/dl_more/phoenix_v1_0_docs/index.html

These files were generated from one master:

    http://spirit.sf.net/dl_more/phoenix_v1_0_docs/doc/phoenix_users_manual.txt

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

QuickDoc v0.5 Syntax Summary

*** See phoenix_users_manual.txt for an example of a document
*** using the quickdoc format. Compile the quickdoc.exe application
*** and feed phoenix_users_manual.txt. The output is a fully linked
*** set of html pages. Have fun with documentation :-)!

Document

    [doc Document Title]

Should be at the very top

Page

    [page:level Page Title]

"Page Title" will be the html's title, a corresponding filename will be created
with the same name appended with ".html", 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: "page_title.html"

A quickdoc document is basically a flat list of pages. However, the generated
table of contents may be formatted to reflect a certain hierarchy. Example:

    intro
    basics
        pizza flavors
        pizza toppings
    crust
        size
        ingredients

Here, intro, basics and crust are at level 0 while pizza flavors, pizza
toppings, size and ingredients are level 1. level is optional (defaults to zero)
and will be page's hierarchical level from the top. Up to 5 levels (0..5) are
currently supported.

Paragraphs

Paragraphs start left-flushed and are terminated by one or more newlines.

Bulleted lists

    * First
    * Second
    * Third

Ordered lists

    # First
    # Second
    # Third

Code

    int main()
    {
    }

Preformatted code starts with a space or a tab. The code will be syntax
highlighted.

Formatting

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

horizontal rule

    ----------------- 4 or more dashes (text after the 4 dashes are ignored)

line-break

    [br]

blockquote

    [: sometext...]

Applies to one paragraph only.

Anchors

    [#named_anchor]

Headings

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

All headings will have anchors with the same name, 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. Example: heading_1

Blurbs

    [blurb an eye catching advertisement or note]

comment

    [/ comment (no html generated) ]

Escape

    '''

    escape (no processing/formatting)

    '''

image

    [$image.jpg]

Macros (Powerful!)

    [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:

    [def my_picture [$http://www.pixels.com/my_picture.jpg]]

Now everytime my_picture is seen, the picture will be inlined.

Links

    [@url some possibly [*marked up] text....]

Tables

    [table Title

        [R0-C0]     [R0-C1]     [R0-C2]
        [R2-C0]     [R2-C1]     [R2-C2]
        [R3-C0]     [R3-C1]     [R3-C2]
    ]

Cheers,
--Joel [Sept 24, 2002]


Grammar:

    document =
        doc_info >> blocks >> space
        ;

    blocks =
       +(   block_markup
        |   code
        |   unordered_list
        |   ordered_list
        |   hr
        |   comment >> *eol_p
        |   paragraph
        )
        ;

    space =
        *(blank_p | comment)
        ;

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

    doc_info =
            *(space_p | comment)
        >> "[doc" >> space
        >> (*(anychar_p - ']'))
        >> ']' >> +eol_p
        ;

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

    block_markup =
            '['
        >>  (   page
            |   headings
            |   blurb
            |   blockquote
            |   def_macro
            |   table
            )
        >>  ']'
        >> +eol_p
        ;

    page =
            "page"
        >>  !(':' >> uint_p)
        >>  space
        >>  (*(anychar_p - ']'))
        ;

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

    h1 = "h1" >> space >> phrase;
    h2 = "h2" >> space >> phrase;
    h3 = "h3" >> space >> phrase;
    h4 = "h4" >> space >> phrase;
    h5 = "h5" >> space >> phrase;
    h6 = "h6" >> space >> phrase;

    blurb =
        "blurb" >> space
        >> phrase
        ;

    blockquote =
        ':' >> space >>
        phrase
        ;

    def_macro =
        "def" >> space >> identifier
         >> space >> phrase
        ;

    table =
        "table" >> space
        >>  (*(anychar_p - eol_p))
        >>  +eol_p
        >> *(   table_row
                >> +eol_p
            )
        >>  eps_p
        ;

    table_row =
       *(       space
            >>  ch_p('[')
            >>  phrase
            >>  ch_p(']')
            >>  space
        )
        ;

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

    code =
        code_line >> *(*eol_p >> code_line)
        ;

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

    unordered_list =
        +('*' >> space >> paragraph)
        ;

    ordered_list =
        +('#' >> space >> paragraph)
        ;

    paragraph =
       *(   self.actions.macro
        |   phrase_markup
        |   escape
        |   comment
        |   (anychar_p - eol_p)
        )
        >> +eol_p
        ;

    phrase =
       *(   self.actions.macro
        |   phrase_markup
        |   escape
        |   comment
        |   (anychar_p - ']')
        )
        ;

    phrase_markup =
            '['
        >>  (   image
            |   link
            |   bold
            |   italic
            |   underline
            |   teletype
            |   str_p("br")
            |   unexpected
            )
        >>  ']'
        ;

    escape =
            "'''"
        >>  *(anychar_p - "'''")
        >>  "'''"
        ;

    image =
            '$' >> space
        >> (*(anychar_p - ']'))
        ;

    link =
            '@'
        >>  (*(anychar_p - space))
        >>  space >> phrase
        ;

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

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

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

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

    unexpected =
        (*(anychar_p - ']'))
        ;
