Joelde GuzmanEricNiebler20022004Joel 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 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
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 ElementsFont Styles['italic], [*bold], [_underline], [^teletype]
will generate:italic, bold, underline, teletype
Like all non-terminal phrase level elements, this can of course be nested:[*['bold-italic]]
will generate:bold-italicSimple formatting
Simple markup for formatting text, common in many applications, is now supported:/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 Unordered lists.
More Formatting SamplesMarkupResult*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 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 int main() { return 0; } 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 Info section.
To change the source mode, use the [source-mode] markup, where
source-mode is 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 ModesModeSource Mode MarkupC++[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, here and
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 Section and Headings
for 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 BoostBook or 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 ElementsDocument
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/02/14 06:36:16 $]
[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
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 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:[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 are supported. Example:# One
# Two
# Three
# Three.a
# Three.b
# Three.c
# Four
# Four.a
# Four.a.i
# Four.a.ii
# Four.b
will generate:
One
Two
Three
Three.a
Three.b
Three.c
Fourth
Four.a
Four.a.i
Four.a.ii
Four.b
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 (ordered and unordered) are supported. Example:# One
# Two
# Three
* Three.a
* Three.b
* Three.c
will generate:
One
Two
Three
Three.a
Three.b
Three.c
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 pre blocks.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 1Heading 2Heading 3Heading 4Heading 5Heading 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:[link section_id.normalized_header_text The link text]
to link to them. See Anchor links and
Section for 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 Images
and Links)
Invoking these macros:Hi __spirit__ :-)
will generate this:
Hi SpiritPredefined Macros
Quickbook has some predefined macros that you can already use.Predefined MacrosMacroMeaningExample__DATE__Today's date2005-Feb-14__TIME__The current time02:30:05 PM__FILENAME__Quickbook source filenameC:\dev\boost\tools\quickbook\doc\quickbook.qbkBlurbs[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...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++.
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 TableHeading 1Heading 2Heading 3R0-C0R0-C1R0-C2R2-C0R2-C1R2-C2R3-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 cellsHeading 1Heading 2Row 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 cellRow 1, Col 1: a small cellVariable 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 1The definition of term 1term 2The definition of term 2term 3The 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". Quick ReferenceSyntax CompendiumTo 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\nanchor[#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\cimages[$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
# threeunordered list* one
* two
* threecodeNo 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]]
] Library Document Grammardoc_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 Grammarlibrary =
*(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
; C++ Syntax Highlighting Grammarprogram
=
*( 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 Grammarprogram
=
*( 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 | '_'))
;