1 // Copyright (c) 2001-2011 Joel de Guzman 2 // Copyright (c) 2001-2011 Hartmut Kaiser 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 #if !defined(BOOST_SPIRIT_KARMA_GRAMMAR_MAR_05_2007_0542PM) 8 #define BOOST_SPIRIT_KARMA_GRAMMAR_MAR_05_2007_0542PM 9 10 #if defined(_MSC_VER) 11 #pragma once 12 #endif 13 14 #include <boost/spirit/home/support/unused.hpp> 15 #include <boost/spirit/home/support/info.hpp> 16 #include <boost/spirit/home/support/assert_msg.hpp> 17 #include <boost/spirit/home/karma/domain.hpp> 18 #include <boost/spirit/home/karma/nonterminal/rule.hpp> 19 #include <boost/spirit/home/karma/nonterminal/nonterminal_fwd.hpp> 20 #include <boost/spirit/home/karma/reference.hpp> 21 #include <boost/noncopyable.hpp> 22 #include <boost/proto/extends.hpp> 23 #include <boost/proto/traits.hpp> 24 #include <boost/type_traits/is_same.hpp> 25 26 namespace boost { namespace spirit { namespace karma 27 { 28 template < 29 typename OutputIterator, typename T1, typename T2, typename T3 30 , typename T4> 31 struct grammar 32 : proto::extends< 33 typename proto::terminal< 34 reference<rule<OutputIterator, T1, T2, T3, T4> const> 35 >::type 36 , grammar<OutputIterator, T1, T2, T3, T4> 37 > 38 , generator<grammar<OutputIterator, T1, T2, T3, T4> > 39 , noncopyable 40 { 41 typedef OutputIterator iterator_type; 42 typedef rule<OutputIterator, T1, T2, T3, T4> start_type; 43 typedef typename start_type::properties properties; 44 typedef typename start_type::sig_type sig_type; 45 typedef typename start_type::locals_type locals_type; 46 typedef typename start_type::delimiter_type delimiter_type; 47 typedef typename start_type::encoding_type encoding_type; 48 typedef grammar<OutputIterator, T1, T2, T3, T4> base_type; 49 typedef reference<start_type const> reference_; 50 typedef typename proto::terminal<reference_>::type terminal; 51 52 static size_t const params_size = start_type::params_size; 53 54 template <typename Context, typename Unused> 55 struct attribute 56 { 57 typedef typename start_type::attr_type type; 58 }; 59 60 // the output iterator is always wrapped by karma 61 typedef detail::output_iterator<OutputIterator, properties> 62 output_iterator; 63 grammarboost::spirit::karma::grammar64 grammar(start_type const& start 65 , std::string const& name_ = "unnamed-grammar") 66 : proto::extends<terminal, base_type>(terminal::make(reference_(start))) 67 , name_(name_) 68 {} 69 70 // This constructor is used to catch if the start rule is not 71 // compatible with the grammar. 72 template <typename Iterator_, typename T1_, typename T2_, typename T3_, 73 typename T4_> grammarboost::spirit::karma::grammar74 grammar(rule<Iterator_, T1_, T2_, T3_, T4_> const& 75 , std::string const& = "unnamed-grammar") 76 { 77 // If you see the assertion below failing then the start rule 78 // passed to the constructor of the grammar is not compatible with 79 // the grammar (i.e. it uses different template parameters). 80 BOOST_SPIRIT_ASSERT_MSG( 81 (is_same<start_type, rule<Iterator_, T1_, T2_, T3_, T4_> >::value) 82 , incompatible_start_rule, (rule<Iterator_, T1_, T2_, T3_, T4_>)); 83 } 84 nameboost::spirit::karma::grammar85 std::string name() const 86 { 87 return name_; 88 } 89 nameboost::spirit::karma::grammar90 void name(std::string const& str) 91 { 92 name_ = str; 93 } 94 95 template <typename Context, typename Delimiter, typename Attribute> generateboost::spirit::karma::grammar96 bool generate(output_iterator& sink, Context& context 97 , Delimiter const& delim, Attribute const& attr) const 98 { 99 return this->proto_base().child0.generate( 100 sink, context, delim, attr); 101 } 102 103 template <typename Context> whatboost::spirit::karma::grammar104 info what(Context&) const 105 { 106 return info(name_); 107 } 108 109 // bring in the operator() overloads get_parameterized_subjectboost::spirit::karma::grammar110 start_type const& get_parameterized_subject() const 111 { return this->proto_base().child0.ref.get(); } 112 typedef start_type parameterized_subject_type; 113 #include <boost/spirit/home/karma/nonterminal/detail/fcall.hpp> 114 115 std::string name_; 116 }; 117 }}} 118 119 namespace boost { namespace spirit { namespace traits 120 { 121 /////////////////////////////////////////////////////////////////////////// 122 template < 123 typename IteratorA, typename IteratorB, typename Attribute 124 , typename Context, typename T1, typename T2, typename T3, typename T4> 125 struct handles_container< 126 karma::grammar<IteratorA, T1, T2, T3, T4>, Attribute, Context 127 , IteratorB> 128 : detail::nonterminal_handles_container< 129 typename attribute_of< 130 karma::grammar<IteratorA, T1, T2, T3, T4> 131 , Context, IteratorB 132 >::type, Attribute> 133 {}; 134 }}} 135 136 #endif 137