blob: 7e2f777c7182d080ea6b7a1dffcdacd74c12335a [file] [log] [blame]
/*=============================================================================
Copyright (c) 2002 2004 2006Joel de Guzman
Copyright (c) 2004 Eric Niebler
http://spirit.sourceforge.net/
Use, modification and distribution is subject to 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 "phrase_grammar.hpp"
#include "utils.hpp"
#include "actions_class.hpp"
#include "scoped_block.hpp"
#include <boost/spirit/include/classic_confix.hpp>
#include <boost/spirit/include/classic_chset.hpp>
#include <boost/spirit/include/classic_assign_actor.hpp>
#include <boost/spirit/include/classic_if.hpp>
#include <boost/spirit/include/classic_symbols.hpp>
#include <boost/spirit/include/classic_clear_actor.hpp>
namespace quickbook
{
namespace cl = boost::spirit::classic;
template <typename Scanner>
struct block_grammar::definition
{
definition(block_grammar const&);
bool no_eols;
cl::rule<Scanner>
start_, blocks, block_markup, code, code_line, blank_line,
paragraph, space, blank, comment, headings, h, h1, h2,
h3, h4, h5, h6, hr, blurb, blockquote, admonition,
phrase, list, phrase_end, ordered_list, def_macro,
macro_identifier, table, table_row, variablelist,
varlistentry, varlistterm, varlistitem, table_cell,
preformatted, list_item, begin_section, end_section,
xinclude, include, hard_space, eol, paragraph_end,
template_, template_id, template_formal_arg,
template_body, identifier, dummy_block, import,
inside_paragraph,
element_id, element_id_1_5, element_id_1_6;
cl::symbols<> paragraph_end_markups;
phrase_grammar common;
cl::rule<Scanner> const&
start() const { return start_; }
};
template <typename Scanner>
block_grammar::definition<Scanner>::definition(block_grammar const& self)
: no_eols(true)
, common(self.actions, no_eols)
{
using detail::var;
quickbook::actions& actions = self.actions;
if (self.skip_initial_spaces)
{
start_ =
*(cl::blank_p | comment) >> blocks >> blank
;
}
else
{
start_ =
blocks >> blank
;
}
blocks =
*( block_markup
| code
| list [actions.list]
| hr [actions.hr]
| +eol
| paragraph [actions.inside_paragraph]
)
;
space =
*(cl::space_p | comment)
;
blank =
*(cl::blank_p | comment)
;
eol = blank >> cl::eol_p
;
phrase_end =
']' |
cl::if_p(var(no_eols))
[
eol >> *cl::blank_p >> cl::eol_p
// Make sure that we don't go
] // past a single block, except
; // when preformatted.
// Follows after an alphanumeric identifier - ensures that it doesn't
// match an empty space in the middle of the identifier.
hard_space =
(cl::eps_p - (cl::alnum_p | '_')) >> space // must not be preceded by
; // alpha-numeric or underscore
comment =
"[/" >> *(dummy_block | (cl::anychar_p - ']')) >> ']'
;
dummy_block =
'[' >> *(dummy_block | (cl::anychar_p - ']')) >> ']'
;
hr =
cl::str_p("----")
>> *(cl::anychar_p - eol)
>> +eol
;
block_markup =
'[' >> space
>> ( begin_section
| end_section
| headings
| blurb
| blockquote
| admonition
| preformatted
| def_macro
| table
| variablelist
| xinclude
| include
| import
| template_
)
>> ( (space >> ']' >> +eol)
| cl::eps_p [actions.error]
)
;
element_id =
':'
>>
(
cl::if_p(qbk_since(105u)) [space]
>> (+(cl::alnum_p | '_')) [cl::assign_a(actions.element_id)]
| cl::eps_p [actions.element_id_warning]
[cl::assign_a(actions.element_id)]
)
| cl::eps_p [cl::assign_a(actions.element_id)]
;
element_id_1_5 =
cl::if_p(qbk_since(105u)) [
element_id
]
.else_p [
cl::eps_p [cl::assign_a(actions.element_id)]
]
;
element_id_1_6 =
cl::if_p(qbk_since(106u)) [
element_id
]
.else_p [
cl::eps_p [cl::assign_a(actions.element_id)]
]
;
begin_section =
"section"
>> hard_space
>> element_id
>> space
>> phrase [actions.begin_section]
;
end_section =
cl::str_p("endsect") [actions.end_section]
;
headings =
h1 | h2 | h3 | h4 | h5 | h6 | h
;
h = "heading" >> hard_space >> element_id_1_6 >> space >> phrase [actions.h];
h1 = "h1" >> hard_space >> element_id_1_6 >> space >> phrase [actions.h1];
h2 = "h2" >> hard_space >> element_id_1_6 >> space >> phrase [actions.h2];
h3 = "h3" >> hard_space >> element_id_1_6 >> space >> phrase [actions.h3];
h4 = "h4" >> hard_space >> element_id_1_6 >> space >> phrase [actions.h4];
h5 = "h5" >> hard_space >> element_id_1_6 >> space >> phrase [actions.h5];
h6 = "h6" >> hard_space >> element_id_1_6 >> space >> phrase [actions.h6];
static const bool true_ = true;
static const bool false_ = false;
inside_paragraph =
phrase [actions.inside_paragraph]
>> *(
+eol >> phrase [actions.inside_paragraph]
)
;
blurb =
"blurb" >> hard_space
>> scoped_block(actions)[inside_paragraph]
[actions.blurb]
;
blockquote =
':' >> blank >>
scoped_block(actions)[inside_paragraph]
[actions.blockquote]
;
admonition =
"warning" >> hard_space >>
scoped_block(actions)[inside_paragraph]
[actions.warning]
|
"caution" >> hard_space >>
scoped_block(actions)[inside_paragraph]
[actions.caution]
|
"important" >> hard_space >>
scoped_block(actions)[inside_paragraph]
[actions.important]
|
"note" >> hard_space >>
scoped_block(actions)[inside_paragraph]
[actions.note]
|
"tip" >> hard_space >>
scoped_block(actions)[inside_paragraph]
[actions.tip]
;
preformatted =
"pre" >> hard_space [cl::assign_a(no_eols, false_)]
>> !eol >> phrase [actions.preformatted]
>> cl::eps_p [cl::assign_a(no_eols, true_)]
;
macro_identifier =
+(cl::anychar_p - (cl::space_p | ']'))
;
def_macro =
"def" >> hard_space
>> macro_identifier [actions.macro_identifier]
>> blank >> phrase [actions.macro_definition]
;
identifier =
(cl::alpha_p | '_') >> *(cl::alnum_p | '_')
;
template_id =
identifier | (cl::punct_p - (cl::ch_p('[') | ']'))
;
template_ =
"template"
>> hard_space
>> template_id [cl::assign_a(actions.template_identifier)]
[cl::clear_a(actions.template_info)]
>>
!(
space >> '['
>> *(
space >> template_id [cl::push_back_a(actions.template_info)]
)
>> space >> ']'
)
>> ( cl::eps_p(*cl::blank_p >> cl::eol_p)
[cl::assign_a(actions.template_block, true_)]
| cl::eps_p [cl::assign_a(actions.template_block, false_)]
)
>> template_body [actions.template_body]
;
template_body =
*(('[' >> template_body >> ']') | (cl::anychar_p - ']'))
>> cl::eps_p(space >> ']')
>> space
;
variablelist =
"variablelist"
>> (cl::eps_p(*cl::blank_p >> cl::eol_p) | hard_space)
>> (*(cl::anychar_p - eol)) [cl::assign_a(actions.table_title)]
>> +eol
>> *varlistentry
>> cl::eps_p [actions.variablelist]
;
varlistentry =
space
>> cl::ch_p('[') [actions.start_varlistentry]
>>
(
(
varlistterm
>> ( scoped_block(actions) [+varlistitem]
[actions.varlistitem]
| cl::eps_p [actions.error]
)
>> cl::ch_p(']') [actions.end_varlistentry]
>> space
)
| cl::eps_p [actions.error]
)
;
varlistterm =
space
>> cl::ch_p('[') [actions.start_varlistterm]
>>
(
(
phrase
>> cl::ch_p(']') [actions.end_varlistterm]
>> space
)
| cl::eps_p [actions.error]
)
;
varlistitem =
space
>> cl::ch_p('[')
>>
(
(
inside_paragraph
>> cl::ch_p(']')
>> space
)
| cl::eps_p [actions.error]
)
;
table =
"table"
>> (cl::eps_p(*cl::blank_p >> cl::eol_p) | hard_space)
>> element_id_1_5
>> (cl::eps_p(*cl::blank_p >> cl::eol_p) | space)
>> (*(cl::anychar_p - eol)) [cl::assign_a(actions.table_title)]
>> +eol
>> *table_row
>> cl::eps_p [actions.table]
;
table_row =
space
>> cl::ch_p('[') [actions.start_row]
>>
(
(
*table_cell
>> cl::ch_p(']') [actions.end_row]
>> space
)
| cl::eps_p [actions.error]
)
;
table_cell =
space
>> cl::ch_p('[')
>> ( scoped_block(actions) [
inside_paragraph
>> cl::ch_p(']')
>> space
] [actions.cell]
| cl::eps_p [actions.error]
)
;
xinclude =
"xinclude"
>> hard_space
>> (*(cl::anychar_p -
phrase_end)) [actions.xinclude]
;
import =
"import"
>> hard_space
>> (*(cl::anychar_p -
phrase_end)) [actions.import]
;
include =
"include"
>> hard_space
>>
!(
':'
>> (*((cl::alnum_p | '_') - cl::space_p))
[cl::assign_a(actions.include_doc_id)]
>> space
)
>> (*(cl::anychar_p -
phrase_end)) [actions.include]
;
code =
(
code_line
>> *(*blank_line >> code_line)
) [actions.code]
>> *eol
;
code_line =
cl::blank_p >> *(cl::anychar_p - cl::eol_p) >> cl::eol_p
;
blank_line =
*cl::blank_p >> cl::eol_p
;
list =
cl::eps_p(cl::ch_p('*') | '#') >>
+(
(*cl::blank_p
>> (cl::ch_p('*') | '#')) [actions.list_format]
>> *cl::blank_p
>> list_item
) [actions.list_item]
;
list_item =
*( common
| (cl::anychar_p -
( cl::eol_p >> *cl::blank_p >> cl::eps_p(cl::ch_p('*') | '#')
| (eol >> eol)
)
) [actions.plain_char]
)
>> +eol
;
paragraph_end_markups =
"section", "endsect", "h1", "h2", "h3", "h4", "h5", "h6",
"blurb", ":", "pre", "def", "table", "include", "xinclude",
"variablelist", "import", "template", "warning", "caution",
"important", "note", "tip", ":"
;
paragraph_end =
'[' >> space >> paragraph_end_markups >> hard_space | eol >> *cl::blank_p >> cl::eol_p
;
paragraph =
+( common
| (cl::anychar_p - // Make sure we don't go past
paragraph_end // a single block.
) [actions.plain_char]
)
>> (cl::eps_p('[') | +eol)
;
phrase =
*( common
| comment
| (cl::anychar_p -
phrase_end) [actions.plain_char]
)
;
}
cl::parse_info<iterator> call_parse(
iterator& first, iterator last, block_grammar& g)
{
return boost::spirit::classic::parse(first, last, g);
}
}