summaryrefslogtreecommitdiffstats
blob: 982e49b91e16476bf290709a7a4bc543fe0f8efd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*=============================================================================
    Copyright (c) 2001-2011 Joel de Guzman

    Distributed under 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)
==============================================================================*/
#if !defined(BOOST_SPIRIT_GRAMMAR_FEBRUARY_19_2007_0236PM)
#define BOOST_SPIRIT_GRAMMAR_FEBRUARY_19_2007_0236PM

#if defined(_MSC_VER)
#pragma once
#endif

#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/assert_msg.hpp>
#include <boost/spirit/home/qi/domain.hpp>
#include <boost/spirit/home/qi/nonterminal/rule.hpp>
#include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp>
#include <boost/spirit/home/qi/reference.hpp>
#include <boost/noncopyable.hpp>
#include <boost/type_traits/is_same.hpp>

namespace boost { namespace spirit { namespace qi
{
    template <
        typename Iterator, typename T1, typename T2, typename T3
      , typename T4>
    struct grammar
      : proto::extends<
            typename proto::terminal<
                reference<rule<Iterator, T1, T2, T3, T4> const>
            >::type
          , grammar<Iterator, T1, T2, T3, T4>
        >
      , parser<grammar<Iterator, T1, T2, T3, T4> >
      , noncopyable
    {
        typedef Iterator iterator_type;
        typedef rule<Iterator, T1, T2, T3, T4> start_type;
        typedef typename start_type::sig_type sig_type;
        typedef typename start_type::locals_type locals_type;
        typedef typename start_type::skipper_type skipper_type;
        typedef typename start_type::encoding_type encoding_type;
        typedef grammar<Iterator, T1, T2, T3, T4> base_type;
        typedef reference<start_type const> reference_;
        typedef typename proto::terminal<reference_>::type terminal;

        static size_t const params_size = start_type::params_size;

        template <typename Context, typename Iterator_>
        struct attribute
        {
            typedef typename start_type::attr_type type;
        };

        grammar(
            start_type const& start
          , std::string const& name_ = "unnamed-grammar")
        : proto::extends<terminal, base_type>(terminal::make(reference_(start)))
        , name_(name_)
        {}

        // This constructor is used to catch if the start rule is not
        // compatible with the grammar.
        template <typename Iterator_,
            typename T1_, typename T2_, typename T3_, typename T4_>
        grammar(
            rule<Iterator_, T1_, T2_, T3_, T4_> const&
          , std::string const& = "unnamed-grammar")
        {
            // If you see the assertion below failing then the start rule
            // passed to the constructor of the grammar is not compatible with
            // the grammar (i.e. it uses different template parameters).
            BOOST_SPIRIT_ASSERT_MSG(
                (is_same<start_type, rule<Iterator_, T1_, T2_, T3_, T4_> >::value)
              , incompatible_start_rule, (rule<Iterator_, T1_, T2_, T3_, T4_>));
        }

        std::string name() const
        {
            return name_;
        }

        void name(std::string const& str)
        {
            name_ = str;
        }

        template <typename Context, typename Skipper, typename Attribute>
        bool parse(Iterator& first, Iterator const& last
          , Context& context, Skipper const& skipper
          , Attribute& attr) const
        {
            return this->proto_base().child0.parse(
                first, last, context, skipper, attr);
        }

        template <typename Context>
        info what(Context&) const
        {
            return info(name_);
        }

        // bring in the operator() overloads
        start_type const& get_parameterized_subject() const
        { return this->proto_base().child0.ref.get(); }
        typedef start_type parameterized_subject_type;
        #include <boost/spirit/home/qi/nonterminal/detail/fcall.hpp>

        std::string name_;

    };
}}}

namespace boost { namespace spirit { namespace traits
{
    ///////////////////////////////////////////////////////////////////////////
    template <
        typename IteratorA, typename IteratorB, typename Attribute
      , typename Context, typename T1, typename T2, typename T3, typename T4>
    struct handles_container<
        qi::grammar<IteratorA, T1, T2, T3, T4>, Attribute, Context, IteratorB>
      : traits::is_container<
          typename attribute_of<
              qi::grammar<IteratorA, T1, T2, T3, T4>, Context, IteratorB
          >::type
        >
    {};
}}}

#endif