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 "grammar.hpp" 15 #include "cleanup.hpp" 16 #include "values.hpp" 17 #include <boost/spirit/include/classic_symbols.hpp> 18 19 namespace quickbook 20 { 21 namespace cl = boost::spirit::classic; 22 23 // Information about a square bracket element (e.g. [* word]). 24 // 25 // TODO: The naming is a bit confused as element is also sometimes used for 26 // syntactic/implicit elements (such as lists and horizontal rules). Maybe 27 // should use entity as a more general name instead of element. Or it might 28 // be better to use 'tag' for square bracket elements, although that is 29 // currently used for the type of entities. 30 struct element_info 31 { 32 // Types of elements. 33 // 34 // Used to determine: 35 // 36 // - where they can be used. 37 // - whether they end a paragraph 38 // - how following newlines are interpreted by the grammar. 39 // - and possibly other things..... 40 enum type_enum { 41 // Used when there's no element. 42 nothing = 0, 43 44 // A section tag. These can't be nested. 45 section_block = 1, 46 47 // Block elements that can be used in conditional phrases and lists, 48 // but not nested. (TODO: not a good name). 49 conditional_or_block = 2, 50 51 // Block elements that can be nested in other elements. 52 nested_block = 4, 53 54 // Phrase elements. 55 phrase = 8, 56 57 // Depending on the context this can be a block or phrase. 58 // 59 // Currently this is only used for elements that don't actually 60 // generate output (e.g. anchors, source mode tags). The main 61 // reason is so that lists can be preceeded by the element, e.g. 62 // 63 // [#anchor] 64 // * list item. 65 // 66 // If the anchor was considered to be a phrase element, then the 67 // list wouldn't be recognised. 68 maybe_block = 16 69 }; 70 71 // Masks to determine which context elements can be used in (in_*), and 72 // whether they are consided to be a block element (is_*). 73 enum context { 74 // At the top level we allow everything. 75 in_top_level = phrase | maybe_block | nested_block | 76 conditional_or_block | section_block, 77 78 // In conditional phrases and list blocks we everything but section 79 // elements. 80 in_conditional = phrase | maybe_block | nested_block | 81 conditional_or_block, 82 in_list_block = phrase | maybe_block | nested_block | 83 conditional_or_block, 84 85 // In nested blocks we allow a more limited range of elements. 86 in_nested_block = phrase | maybe_block | nested_block, 87 88 // In a phrase we only allow phrase elements, ('maybe_block' 89 // elements are treated as phrase elements in this context) 90 in_phrase = phrase | maybe_block, 91 92 // At the start of a block these are all block elements. 93 is_contextual_block = maybe_block | nested_block | 94 conditional_or_block | section_block, 95 96 // These are all block elements in all other contexts. 97 is_block = nested_block | conditional_or_block | section_block, 98 }; 99 element_infoquickbook::element_info100 element_info() 101 : type(nothing), rule(), tag(0) {} 102 element_infoquickbook::element_info103 element_info( 104 type_enum t, 105 cl::rule<scanner>* r, 106 value::tag_type tag = value::default_tag, 107 unsigned int v = 0) 108 : type(t), rule(r), tag(tag), qbk_version(v) {} 109 110 type_enum type; 111 cl::rule<scanner>* rule; 112 value::tag_type tag; 113 unsigned int qbk_version; 114 }; 115 116 struct quickbook_grammar::impl 117 { 118 quickbook::state& state; 119 cleanup cleanup_; 120 121 // Main Grammar 122 cl::rule<scanner> block_start; 123 cl::rule<scanner> phrase_start; 124 cl::rule<scanner> nested_phrase; 125 cl::rule<scanner> inline_phrase; 126 cl::rule<scanner> paragraph_phrase; 127 cl::rule<scanner> extended_phrase; 128 cl::rule<scanner> table_title_phrase; 129 cl::rule<scanner> inside_preformatted; 130 cl::rule<scanner> inside_paragraph; 131 cl::rule<scanner> command_line; 132 cl::rule<scanner> attribute_template_body; 133 cl::rule<scanner> attribute_value_1_7; 134 cl::rule<scanner> escape; 135 cl::rule<scanner> raw_escape; 136 cl::rule<scanner> skip_entity; 137 138 // Miscellaneous stuff 139 cl::rule<scanner> hard_space; 140 cl::rule<scanner> space; 141 cl::rule<scanner> blank; 142 cl::rule<scanner> eol; 143 cl::rule<scanner> phrase_end; 144 cl::rule<scanner> comment; 145 cl::rule<scanner> line_comment; 146 cl::rule<scanner> macro_identifier; 147 148 // Element Symbols 149 cl::symbols<element_info> elements; 150 151 // Source mode 152 cl::symbols<source_mode_type> source_modes; 153 154 // Doc Info 155 cl::rule<scanner> doc_info_details; 156 157 impl(quickbook::state&); 158 159 private: 160 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