• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  Copyright (c) 2009 Chris Hoeppler
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #if !defined(BOOST_SPIRIT_REPOSITORY_QI_CONFIX_JUN_22_2009_1041AM)
7 #define BOOST_SPIRIT_REPOSITORY_QI_CONFIX_JUN_22_2009_1041AM
8 
9 #if defined(_MSC_VER)
10 #pragma once
11 #endif
12 
13 #include <boost/spirit/home/qi/domain.hpp>
14 #include <boost/spirit/home/qi/meta_compiler.hpp>
15 #include <boost/spirit/home/qi/auxiliary/lazy.hpp>
16 #include <boost/spirit/home/support/common_terminals.hpp>
17 #include <boost/spirit/home/support/info.hpp>
18 #include <boost/spirit/home/support/unused.hpp>
19 #include <boost/spirit/home/qi/detail/attributes.hpp>
20 
21 #include <boost/spirit/repository/home/support/confix.hpp>
22 
23 #include <boost/fusion/include/vector.hpp>
24 #include <boost/mpl/or.hpp>
25 
26 ///////////////////////////////////////////////////////////////////////////////
27 namespace boost { namespace spirit
28 {
29     ///////////////////////////////////////////////////////////////////////////
30     // Enablers
31     ///////////////////////////////////////////////////////////////////////////
32 
33     // enables confix(..., ...)[]
34     template <typename Prefix, typename Suffix>
35     struct use_directive<qi::domain
36           , terminal_ex<repository::tag::confix, fusion::vector2<Prefix, Suffix> > >
37       : mpl::true_ {};
38 
39     // enables *lazy* confix(..., ...)[]
40     template <>
41     struct use_lazy_directive<qi::domain, repository::tag::confix, 2>
42       : mpl::true_ {};
43 
44 }}
45 
46 ///////////////////////////////////////////////////////////////////////////////
47 namespace boost { namespace spirit { namespace repository { namespace qi
48 {
49 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
50     using repository::confix;
51 #endif
52     using repository::confix_type;
53 
54     ///////////////////////////////////////////////////////////////////////////
55     // the confix() generated parser
56     template <typename Subject, typename Prefix, typename Suffix>
57     struct confix_parser
58       : spirit::qi::unary_parser<confix_parser<Subject, Prefix, Suffix> >
59     {
60         typedef Subject subject_type;
61 
62         template <typename Context, typename Iterator>
63         struct attribute
64           : traits::attribute_of<subject_type, Context, Iterator>
65         {};
66 
confix_parserboost::spirit::repository::qi::confix_parser67         confix_parser(Subject const& subject, Prefix const& prefix
68               , Suffix const& suffix)
69           : subject(subject), prefix(prefix), suffix(suffix) {}
70 
71         template <typename Iterator, typename Context
72           , typename Skipper, typename Attribute>
parseboost::spirit::repository::qi::confix_parser73         bool parse(Iterator& first, Iterator const& last
74           , Context& context, Skipper const& skipper
75           , Attribute& attr) const
76         {
77             Iterator iter = first;
78 
79             if (!(prefix.parse(iter, last, context, skipper, unused) &&
80                 subject.parse(iter, last, context, skipper, attr) &&
81                 suffix.parse(iter, last, context, skipper, unused)))
82             {
83                 return false;
84             }
85 
86             first = iter;
87             return true;
88         }
89 
90         template <typename Context>
whatboost::spirit::repository::qi::confix_parser91         info what(Context const& ctx) const
92         {
93             return info("confix", subject.what(ctx));
94         }
95 
96         Subject subject;
97         Prefix prefix;
98         Suffix suffix;
99     };
100 
101 }}}}
102 
103 ///////////////////////////////////////////////////////////////////////////////
104 namespace boost { namespace spirit { namespace qi
105 {
106     ///////////////////////////////////////////////////////////////////////////
107     // Parser generators: make_xxx function (objects)
108     ///////////////////////////////////////////////////////////////////////////
109 
110     // creates confix(..., ...)[] directive
111     template <typename Prefix, typename Suffix, typename Subject
112       , typename Modifiers>
113     struct make_directive<
114         terminal_ex<repository::tag::confix, fusion::vector2<Prefix, Suffix> >
115       , Subject, Modifiers>
116     {
117         typedef typename
118             result_of::compile<qi::domain, Prefix, Modifiers>::type
119         prefix_type;
120         typedef typename
121             result_of::compile<qi::domain, Suffix, Modifiers>::type
122         suffix_type;
123 
124         typedef repository::qi::confix_parser<
125             Subject, prefix_type, suffix_type> result_type;
126 
127         template <typename Terminal>
operator ()boost::spirit::qi::make_directive128         result_type operator()(Terminal const& term, Subject const& subject
129           , Modifiers const& modifiers) const
130         {
131             return result_type(subject
132               , compile<qi::domain>(fusion::at_c<0>(term.args), modifiers)
133               , compile<qi::domain>(fusion::at_c<1>(term.args), modifiers));
134         }
135     };
136 
137 }}}
138 
139 namespace boost { namespace spirit { namespace traits
140 {
141     template <typename Subject, typename Prefix, typename Suffix>
142     struct has_semantic_action<
143             repository::qi::confix_parser<Subject, Prefix, Suffix> >
144       : mpl::or_<
145             has_semantic_action<Subject>
146           , has_semantic_action<Prefix>
147           , has_semantic_action<Suffix>
148         > {};
149 }}}
150 
151 #endif
152 
153