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