diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
new file mode 100644
index 0000000..12b1fb3
--- /dev/null
+++ b/test/Jamfile.v2
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2005 João Abecasis
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+project test ;
+
+import quickbook-testing : quickbook-test ;
+
+test-suite quickbook.test :
+ [ quickbook-test test1 ]
+ ;
diff --git a/test/quickbook-testing.jam b/test/quickbook-testing.jam
new file mode 100644
index 0000000..ab9fde4
--- /dev/null
+++ b/test/quickbook-testing.jam
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2005 João Abecasis
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+
+import testing ;
+import project ;
+
+#
+# quickbook-test - generates a test for quickbook itself. A quickbook-test is
+# actually made up of two tests:
+# $(target-name) : generate boostbook from $(source) or $(target-name).qbk
+# $(target-name).diff : compare generated boostbook to $(target-name).gold
+#
+# Known Issues:
+# * FIXME: quickbook gets generated for each test
+# * FIXME: text_diff gets generated for each test
+# * FIXME: text_diff will fail on dates, and other variable output
+#
+rule quickbook-test ( target-name : source ? : requirements * )
+{
+ local project = [ project.current ] ;
+ source ?= $(target-name).qbk ;
+
+ return
+ [ testing.make-test boostbook : $(source) : $(requirements)
+ : $(target-name) ]
+
+ [ run text_diff.cpp : : $(target-name) $(target-name).gold
+ : $(requirements) : $(target-name).diff : $(default-build) ]
+ ;
+}
diff --git a/test/test1.gold b/test/test1.gold
new file mode 100644
index 0000000..0cd0076
--- /dev/null
+++ b/test/test1.gold
@@ -0,0 +1,2260 @@
+
+
+
+
+
+ Joelde Guzman
+
+
+ EricNiebler
+
+
+ 20022004Joel de Guzman, Eric Niebler
+
+
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt )
+
+
+
+ WikiWiki style documentation tool
+
+ quickbook 1.1
+
+ Introduction
+
+
+ "Why program by hand in five days what
+ you can spend five years of your life automating?"
+ -- 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
+
+
+
+ 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
+ BoostBookdocumentation 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
+
+
+
+
+ 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.
+ Comments
+
+ Can be placed anywhere.
+
+[/ comment (no output generated) ]
+
+ Phrase
+ Level Elements
+ Font Styles
+['italic], [*bold], [_underline], [^teletype], [-strikethrough]
+
+
+ will generate:
+
+
+ italic, bold, underline, teletype, strikethrough
+
+
+ Like all non-terminal phrase level elements, this can of course be nested:
+
+[*['bold-italic]]
+
+
+ will generate:
+
+
+ bold-italic
+
+ Simple formatting
+
+ Simple markup for formatting text, common in many applications, is now supported:
+
+/italic/, *bold*, _underline_, =teletype=, -strikethrough-
+
+
+ will generate:
+
+
+ italic, bold, underline, teletype, strikethrough
+
+
+ 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
+ Unordered lists.
+
+
+
+ More Formatting Samples
+
+
+
+
+ MarkupResult
+
+
+
+
+ *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 45 = 60 (4 is bold)
+
+
+ *This is bold* this is not *but this is*
+ This is boldthis is not but this is
+
+
+ *This is bold*.
+ This is bold.
+
+
+ *B*. (bold B)
+ B. (bold B)
+
+
+ ['*Bold-Italic*]Bold-Italic
+
+
+
+
+
+
+
+
+
+
+ Thanks to David Barrett,
+ author of
+ 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.
+
+
+
+
+ Inline code
+
+ Inlining code in paragraphs is quite common when writing C++ documentation.
+ We provide a very simple markup for this. For example, this:
+
+This text has inlined code `int main() { return 0; }` in it.
+
+
+ will generate:
+
+
+ This text has inlined code
+
+ intmain
+ (){return0
+ ;}
+ in it. The code will be syntax highlighted.
+
+
+
+
+
+
+
+ Note that we simply enclose
+ the code with the tick: "`", not the single quote:
+
+ "'"
+ . Note too that `some code`is prefered over
+ [^some code].
+
+
+
+
+ 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 Document Infosection.
+
+
+ To change the source mode, use the [source-mode]markup,
+ where source-modeis one of the supported modes. For example,
+ this:
+
+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
+
+ import
+ is rather like C++'s
+
+ #include
+ . A C++ comment
+
+ // looks like this
+ whereas a Python comment
+
+ #looks like this
+ .
+
+
+ Supported Source Modes
+
+
+
+
+ ModeSource Mode Markup
+
+
+
+
+ C++[c++]
+
+
+ Python[python]
+
+
+
+
+
+
+
+
+
+
+ The source mode strings
+ are lowercase.
+
+
+
+
+ line-break
+[br]
+
+
+
+
+
+
+
+ Note that
+
+ \n
+ is now preferred over
+
+ [br
+ ]
+ .
+
+
+
+ Anchors
+
+[#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
+ here, hereand
+ here.
+ Links
+[@http://www.boost.org this is [*boost's] website....]
+
+
+ will generate:
+
+
+ this is boost's
+ website....
+
+
+ URL links where the link text is the link itself is common. Example:
+
+see http://spirit.sourceforge.net/
+
+
+ so, when the text is absent in a link markup, the URL is assumed. Example:
+
+see [@http://spirit.sourceforge.net/]
+
+
+ will generate:
+
+
+ see http://spirit.sourceforge.net/
+
+ Anchor
+ links
+
+ You can link within a document using:
+
+[link section_id.normalized_header_text The link text]
+
+
+ See sections Sectionand
+ Headingsfor more info.
+ refentry
+ links
+
+ In addition, you can link internally to an XML refentry like:
+
+[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:
+
+[link xml.refentry]
+
+
+ This gets converted into <link linkend="xml.refentry"
+ >xml.refentry</link>.
+ 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:
+
+[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:
+
+[classref boost::bar::baz]
+
+
+ would have "boost::bar::baz" as the link text.
+ Escape
+
+ The escape mark-up is used when we don't want to do any processing.
+
+'''
+escape (no processing/formatting)
+'''
+
+
+ Escaping allows us to pass XML markup to
+ BoostBookor DocBook. For
+ example:
+
+'''
+<emphasis role="bold">This is direct XML markup</emphasis>
+'''
+
+
+ This is direct XML markup
+
+
+
+
+
+
+
+ Be careful when using the
+ escape. The text must conform to
+ BoostBook/DocBook
+ syntax.
+
+
+
+
+ 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]
+ .
+
+ Images (terminal)
+[$image.jpg]
+
+ Block
+ Level Elements
+ Document
+
+ Every document must begin with a Document Info section, which should look like
+ this:
+
+[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/09/05 01:50:41 $]
+ [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-revisionand source-modeare optional information.
+
+
+ Here source-typeis a lowercase string setting the initial
+ source mode. If the source-mode
+ field is omitted, a default value of c++will be
+ used.
+ Section
+
+ Starting a new section is accomplished with:
+
+[section:id The Section Title]
+
+
+ where idis 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-9and _. 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:
+
+[endsect]
+
+
+ Sections can nest, and that results in a hierarchy in the table of contents.
+ xinclude
+
+ You can include another XML file with:
+
+[xinclude file.xml]
+
+
+ This is useful when file.xml has been generated by Doxygen and contains your
+ reference section.
+ 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.
+ Ordered
+ lists
+# One
+# Two
+# Three
+
+
+ will generate:
+
+
+
+ One
+
+
+ Two
+
+
+ Three
+
+
+ List Hierarchies
+
+ List hierarchies are supported. Example:
+
+# 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
+
+
+ Long List Lines
+
+ Long lines will be wrapped appropriately. Example:
+
+# 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.
+
+
+ Unordered lists
+* First
+* Second
+* Third
+
+
+ will generate:
+
+
+
+ First
+
+
+ Second
+
+
+ Third
+
+
+ Mixed lists
+
+ Mixed lists (ordered and unordered) are supported. Example:
+
+# One
+# Two
+# Three
+ * Three.a
+ * Three.b
+ * Three.c
+# Four
+
+
+ will generate:
+
+
+
+ One
+
+
+ Two
+
+
+ Three
+
+
+ Three.a
+
+
+ Three.b
+
+
+ Three.c
+
+
+
+
+ Four
+
+
+
+ And...
+
+# 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
+
+
+
+
+
+
+
+ Code
+
+ Preformatted code starts with a space or a tab. The code will be syntax highlighted
+ according to the current source mode
+ :
+
+
+
+
+
+
+#include <iostream>
+
+int main()
+{
+ // Sample code
+ std::cout << "Hello, World\n";
+ return 0;
+}
+
+
+
+
+
+
+
+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:
+
+[def __syntax_highlight__ [@quickbook/highlight.html syntax_highlight]]
+[def __quickbook__ [@index.html quickbook]]
+
+ using __quickbook__::__syntax_highlight__;
+
+
+ Generates:
+
+
+
+usingquickbook::syntax_highlight;
+
+ Preformatted
+
+
+ Sometimes, you don't want some preformatted text to be parsed as C++. In such
+ cases, use the [pre ... ]markup block.
+
+[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:
+
+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 preblocks.
+ Blockquote
+
+[:sometext...]
+
+
+
+ Indents the paragraph. This applies to one paragraph only.
+
+
Headings
+
+[h1 Heading 1]
+[h2 Heading 2]
+[h3 Heading 3]
+[h4 Heading 4]
+[h5 Heading 5]
+[h6 Heading 6]
+
+ Heading 1
+ Heading 2
+ Heading 3
+ Heading 4
+ Heading 5
+ 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-9and _. 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:
+
+[link section_id.normalized_header_text The link text]
+
+
+ to link to them. See Anchor links
+ and Sectionfor more info.
+ Macros
+[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 sf_logo [$http://sourceforge.net/sflogo.php?group_id=28447&type=1]]
+sf_logo
+
+
+ Now everywhere the sf_logo is placed, the picture will be inlined.
+
+
+
+
+
+
+
+
+
+
+
+ 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:
+
+[def :-) [$theme/smiley.png]]
+[def __spirit__ [@http://spirit.sourceforge.net Spirit]]
+
+
+ (See Imagesand
+ Links)
+
+
+ Invoking these macros:
+
+Hi __spirit__ :-)
+
+
+ will generate this:
+
+
+ Hi Spirit
+
+
+
+ Predefined Macros
+
+ Quickbook has some predefined macros that you can already use.
+
+
+ Predefined Macros
+
+
+
+
+ MacroMeaningExample
+
+
+
+
+ __DATE__Today's date2005-Sep-05
+
+
+
+ __TIME__The current time02:25:18
+ AM
+
+
+ __FILENAME__Quickbook source filename
+ /home/joao/sandbox/boost/tools/quickbook/test/test1.qbk
+
+
+
+ Blurbs
+
+[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:
+
+
+
+
+
+
+
+
+ An eye catching advertisement or note...Spiritis 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++.
+
+
+
+
+ Tables
+
+[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:
+
+
+ A Simple Table
+
+
+
+
+ Heading 1Heading 2Heading 3
+
+
+
+
+ R0-C0R0-C1R0-C2
+
+
+ R2-C0R2-C1R2-C2
+
+
+ R3-C0R3-C1R3-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:
+
+[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 with fat cells
+
+
+
+
+ Heading 1Heading 2
+
+
+
+
+ Row 0, Col 0: a small cellRow 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 cellRow 1, Col 1: a small
+ cell
+
+
+
+
+ Variable Lists
+[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:
+
+
+ A Variable Listterm 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".
+ Include
+
+ You can include one QuickBook file from another. The syntax is simply:
+
+[include someother.qbk]
+
+
+ The included file will be processed as if it had be cut and pasted into the
+ current document, with the following exceptions:
+
+
+
+ The __FILENAME__ predefined macro will reflect the name of the file currently
+ being processed.
+
+
+ Any macros defined in the included file are scoped to that file.
+
+
+
+ As the number of included QuickBook files grows, so too does the likelihood
+ of two sections having the same name. Since QuickBook generates an anchor for
+ each section based on the section name, it is possible to end up with two identically
+ named anchors, leading to link ambiguities. To resolve these ambiguities, the
+ [include]directive lets you specify a document id to use
+ for the included file. You can use it like this:
+
+[include:someid someother.qbk]
+
+
+ When using this form, all auto-generated anchors will use "someid"
+ as a unique prefix. So for instance, if there is a section in someother.qbk
+ named "Intro", the named anchor for that section will be "someid.intro
+ ", and you can link to it with [link someid.intro The Intro]
+ .
+
+
+
+ Quick Reference
+
+ 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=
+
+
+ strikethrough
+ [-strikethrough] or -strikethrough-
+
+
+ source mode[c++]or
+ [python]
+
+
+ inline code`int main();`
+
+
+ line break[br] or \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]
+
+
+ paragraphNo markup. Paragraphs start left-flushed
+ and are terminated by two or more newlines.
+
+
+ ordered list# one# two# three
+
+
+
+ unordered list* one* two*
+ three
+
+
+ codeNo 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[[a][b][c]]
+ [[a][b][c]]]
+
+
+ variablelist[variablelist Title
+ [[a][b]][[a][b]]]
+
+
+ include[include someother.qbk]
+
+
+
+
+
+
+
+ Library Document Grammar
+
+
+
+
+
+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
+
+
+
+
+
+ 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
+ | include
+ )
+ >> ( (']' >> +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))
+ ;
+
+include =
+ "include"
+ >> hard_space
+ >>
+ !(
+ ':'
+ >> (*((alnum_p | '_') - space_p))
+ >> 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_strikethrough
+ ;
+
+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))
+ )
+ )
+ >> '='
+ ;
+
+simple_strikethrough =
+ '-' >>
+ (
+ ( 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
+ | strikethrough
+ | 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
+ ;
+
+strikethrough =
+ ch_p('-')
+ >> blank >> phrase
+ ;
+
+
+
+
+
+ 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 | '_'))
+ ;
+
+
+
+
+
+ Python Syntax Highlighting Grammar
+
+
+
+
+
+program
+ =
+ *( macro
+ | comment
+ | keyword
+ | identifier
+ | special
+ | string_
+ | number
+ | space_p
+ | anychar_p
+ )
+ ;
+
+acro
+ = *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 | '_'))
+ ;
+
+
+
+
+
\ No newline at end of file
diff --git a/test/test1.qbk b/test/test1.qbk
new file mode 100644
index 0000000..9f5722c
--- /dev/null
+++ b/test/test1.qbk
@@ -0,0 +1,1771 @@
+[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
+
+ http://www.boost.org/LICENSE_1_0.txt
+ )
+ ]
+ [last-revision $Date$]
+]
+
+[/ 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], [-strikethrough]
+''']
+
+will generate:
+
+['italic], [*bold], [_underline], [^teletype], [-strikethrough]
+
+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=, -strikethrough-
+''']
+
+will generate:
+
+/italic/, *bold*, _underline_, =teletype=, -strikethrough-
+
+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 [^The link text].
+
+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 [^xml.refentry].
+
+[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
+\'\'\'
+This is direct XML markup
+\'\'\'
+]
+
+'''
+This is direct XML markup
+'''
+
+[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$]
+ [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
+
+ 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&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 [^...] 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".
+
+[h3 Include]
+
+You can include one QuickBook file from another. The syntax is simply:
+
+[pre'''
+[include someother.qbk]
+''']
+
+The included file will be processed as if it had be cut and pasted
+into the current document, with the following exceptions:
+
+* The '''__FILENAME__''' predefined macro will reflect the name of the
+ file currently being processed.
+* Any macros defined in the included file are scoped to that file.
+
+As the number of included QuickBook files grows, so too does the
+likelihood of two sections having the same name. Since QuickBook generates
+an anchor for each section based on the section name, it is possible to
+end up with two identically named anchors, leading to link ambiguities.
+To resolve these ambiguities, the [^\[include\]] directive lets you
+specify a document id to use for the included file. You can use it like
+this:
+
+[pre'''
+[include:someid someother.qbk]
+''']
+
+When using this form, all auto-generated anchors will use "someid" as
+a unique prefix. So for instance, if there is a section in someother.qbk
+named "Intro", the named anchor for that section will be "someid.intro",
+and you can link to it with [^\[link someid.intro The Intro\]].
+
+[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=''']]]
+ [[[-strikethrough]] [[^'''[-strikethrough] or -strikethrough-''']]]
+ [[source mode] [[^\[c++\]] or [^\[python\]]]]
+ [[inline code] [[^'''`int main();`''']]]
+ [[line break] [[^'''[br] or \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\]]]]
+ [[include] [[^'''[include someother.qbk]''']]]
+]
+
+[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
+ | include
+ )
+ >> ( (']' >> +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))
+ ;
+
+ include =
+ "include"
+ >> hard_space
+ >>
+ !(
+ ':'
+ >> (*((alnum_p | '_') - space_p))
+ >> 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_strikethrough
+ ;
+
+ 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))
+ )
+ )
+ >> '='
+ ;
+
+ simple_strikethrough =
+ '-' >>
+ (
+ ( 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
+ | strikethrough
+ | 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
+ ;
+
+ strikethrough =
+ 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]
diff --git a/test/text_diff.cpp b/test/text_diff.cpp
new file mode 100644
index 0000000..9409dc5
--- /dev/null
+++ b/test/text_diff.cpp
@@ -0,0 +1,84 @@
+//
+// Copyright (c) 2005 João Abecasis
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include
+#include
+#include
+
+#include
+#include
+
+namespace spirit = boost::spirit;
+
+typedef std::istream_iterator iterator;
+typedef spirit::scanner scanner;
+
+int main(int argc, char * argv[])
+{
+ if (argc != 3)
+ {
+ std::cerr << "ERROR: Wrong number of arguments." << std::endl;
+ std::cout << "Usage:\n\t" << argv[0] << " file1 file2" << std::endl;
+
+ return 1;
+ }
+
+ std::ifstream
+ file1(argv[1], std::ios_base::binary | std::ios_base::in),
+ file2(argv[2], std::ios_base::binary | std::ios_base::in);
+
+ if (!file1 || !file2)
+ {
+ std::cerr << "ERROR: Unable to open one or both files." << std::endl;
+ return 2;
+ }
+
+ file1.unsetf(std::ios_base::skipws);
+ file2.unsetf(std::ios_base::skipws);
+
+ iterator
+ iter_file1(file1),
+ iter_file2(file2);
+
+ scanner
+ scan1(iter_file1, iterator()),
+ scan2(iter_file2, iterator());
+
+ std::size_t line = 1, column = 1;
+
+ while (!scan1.at_end() && !scan2.at_end())
+ {
+ if (spirit::eol_p.parse(scan1))
+ {
+ if (!spirit::eol_p.parse(scan2))
+ {
+ std::cout << "Files differ at line " << line << ", column " <<
+ column << '.' << std::endl;
+ return 3;
+ }
+
+ ++line, column = 1;
+ continue;
+ }
+
+ if (*scan1 != *scan2)
+ {
+ std::cout << "Files differ at line " << line << ", column " <<
+ column << '.' << std::endl;
+ return 4;
+ }
+
+ ++scan1, ++scan2, ++column;
+ }
+
+ if (scan1.at_end() != scan2.at_end())
+ {
+ std::cout << "Files differ in length." << std::endl;
+ return 5;
+ }
+}