1 /*=============================================================================
2     Copyright (c) 2002 2004 2006 Joel de Guzman
3     Copyright (c) 2004 Eric Niebler
4     Copyright (c) 2010 Daniel James
5     http://spirit.sourceforge.net/
6 
7     Use, modification and distribution is subject to the Boost Software
8     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9     http://www.boost.org/LICENSE_1_0.txt)
10 =============================================================================*/
11 #if !defined(BOOST_SPIRIT_QUICKBOOK_GRAMMARS_IMPL_HPP)
12 #define BOOST_SPIRIT_QUICKBOOK_GRAMMARS_IMPL_HPP
13 
14 #include <boost/spirit/include/classic_symbols.hpp>
15 #include "cleanup.hpp"
16 #include "grammar.hpp"
17 #include "values.hpp"
18 
19 namespace quickbook
20 {
21     namespace cl = boost::spirit::classic;
22 
23     // Information about a square bracket element (e.g. [* word]), and
24     // some other syntactic elements (such as lists and horizontal rules)..
25     struct element_info
26     {
27         // Types of elements.
28         //
29         // Used to determine:
30         //
31         //  - where they can be used.
32         //  - whether they end a paragraph
33         //  - how following newlines are interpreted by the grammar.
34         //  - and possibly other things.....
35         enum type_enum
36         {
37             // Used when there's no element.
38             nothing = 0,
39 
40             // A section tag. These can't be nested.
41             section_block = 1,
42 
43             // Block elements that can be used in conditional phrases and lists,
44             // but not nested.
45             conditional_or_block = 2,
46 
47             // Block elements that can be nested in other elements.
48             nested_block = 4,
49 
50             // Phrase elements.
51             phrase = 8,
52 
53             // Depending on the context this can be a block or phrase.
54             //
55             // Currently this is only used for elements that don't actually
56             // generate output (e.g. anchors, source mode tags). The main
57             // reason is so that lists can be preceeded by the element, e.g.
58             //
59             // [#anchor]
60             // * list item.
61             //
62             // If the anchor was considered to be a phrase element, then the
63             // list wouldn't be recognised.
64             maybe_block = 16
65         };
66 
67         // Masks to determine which context elements can be used in (in_*), and
68         // whether they are consided to be a block element (is_*).
69         enum context
70         {
71             // At the top level we allow everything.
72             in_top_level = phrase | maybe_block | nested_block |
73                            conditional_or_block | section_block,
74 
75             // In conditional phrases and list blocks we everything but section
76             // elements.
77             in_conditional =
78                 phrase | maybe_block | nested_block | conditional_or_block,
79             in_list_block =
80                 phrase | maybe_block | nested_block | conditional_or_block,
81 
82             // In nested blocks we allow a more limited range of elements.
83             in_nested_block = phrase | maybe_block | nested_block,
84 
85             // In a phrase we only allow phrase elements, ('maybe_block'
86             // elements are treated as phrase elements in this context)
87             in_phrase = phrase | maybe_block,
88 
89             // At the start of a block these are all block elements.
90             is_contextual_block = maybe_block | nested_block |
91                                   conditional_or_block | section_block,
92 
93             // These are all block elements in all other contexts.
94             is_block = nested_block | conditional_or_block | section_block
95         };
96 
element_infoquickbook::element_info97         element_info() : type(nothing), rule(), tag(0) {}
98 
element_infoquickbook::element_info99         element_info(
100             type_enum t,
101             cl::rule<scanner>* r,
102             value::tag_type tag_ = value::default_tag,
103             unsigned int v = 0)
104             : type(t), rule(r), tag(tag_), qbk_version(v)
105         {
106         }
107 
108         type_enum type;
109         cl::rule<scanner>* rule;
110         value::tag_type tag;
111         unsigned int qbk_version;
112     };
113 
114     struct quickbook_grammar::impl
115     {
116         quickbook::state& state;
117         cleanup cleanup_;
118 
119         // Main Grammar
120         cl::rule<scanner> block_start;
121         cl::rule<scanner> phrase_start;
122         cl::rule<scanner> nested_phrase;
123         cl::rule<scanner> inline_phrase;
124         cl::rule<scanner> paragraph_phrase;
125         cl::rule<scanner> extended_phrase;
126         cl::rule<scanner> table_title_phrase;
127         cl::rule<scanner> inside_preformatted;
128         cl::rule<scanner> inside_paragraph;
129         cl::rule<scanner> command_line;
130         cl::rule<scanner> attribute_template_body;
131         cl::rule<scanner> attribute_value_1_7;
132         cl::rule<scanner> escape;
133         cl::rule<scanner> raw_escape;
134         cl::rule<scanner> skip_entity;
135 
136         // Miscellaneous stuff
137         cl::rule<scanner> hard_space; // Either non-empty space, or
138                                       // empty and not followed by
139                                       // alphanumeric/_. Use to match the
140                                       // the end of an itendifier.
141         cl::rule<scanner> space; // Space/tab/newline/comment (possibly empty)
142         cl::rule<scanner> blank; // Space/tab/comment (possibly empty)
143         cl::rule<scanner> eol;   // blank >> eol
144         cl::rule<scanner> phrase_end; // End of phrase text, context sensitive
145         cl::rule<scanner> comment;
146         cl::rule<scanner> line_comment;
147         cl::rule<scanner> macro_identifier;
148 
149         // Element Symbols
150         cl::symbols<element_info> elements;
151 
152         // Source mode
153         cl::symbols<source_mode_type> source_modes;
154 
155         // Doc Info
156         cl::rule<scanner> doc_info_details;
157 
158         impl(quickbook::state&);
159 
160       private:
161         void init_main();
162         void init_block_elements();
163         void init_phrase_elements();
164         void init_doc_info();
165     };
166 }
167 
168 #endif // BOOST_SPIRIT_QUICKBOOK_GRAMMARS_HPP
169