CustomFoldDirective.hh
3 KB
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
#ifndef CUSTOMFOLDDIRECTIVE_HH_
#define CUSTOMFOLDDIRECTIVE_HH_
namespace AMDA {
namespace parser {
namespace tag {
struct fold { BOOST_SPIRIT_IS_TAG() };
}
template <typename Exposed, typename Expr>
boost::spirit::stateful_tag_type<Expr, tag::fold, Exposed> fold(Expr const& expr)
{
return boost::spirit::stateful_tag_type<Expr, tag::fold, Exposed>(expr);
}
} /*namespace parser */
} /*namespace AMDA */
namespace boost {
namespace spirit {
template <typename Expr, typename Exposed>
struct use_directive<qi::domain, tag::stateful_tag<Expr, AMDA::parser::tag::fold, Exposed> > : mpl::true_ {};
} /*namespace spirit */
} /*namespace boost */
namespace AMDA {
namespace parser {
template <typename Exposed, typename InitialParser, typename RepeatingParser>
struct fold_directive
{
fold_directive(InitialParser const& initial, RepeatingParser const& repeating):initial(initial),repeating(repeating){}
template <typename Context, typename Iterator>
struct attribute
{
typedef typename boost::spirit::traits::attribute_of<InitialParser,Context,Iterator>::type type;//This works in this case but is not generic
};
template <typename Iterator, typename Context, typename Skipper, typename Attribute>
bool parse(Iterator& first, Iterator const& last, Context& context, Skipper const& skipper, Attribute& attr_) const
{
Iterator start = first;
typename boost::spirit::traits::attribute_of<InitialParser,Context,Iterator>::type initial_attr;
if (!initial.parse(first, last, context, skipper, initial_attr))
{
first=start;
return false;
}
typename boost::spirit::traits::attribute_of<RepeatingParser,Context,Iterator>::type repeating_attr;
if(!repeating.parse(first, last, context, skipper, repeating_attr))
{
boost::spirit::traits::assign_to(initial_attr, attr_);
return true;
}
Exposed current_attr(initial_attr,repeating_attr);
while(repeating.parse(first, last, context, skipper, repeating_attr))
{
boost::spirit::traits::assign_to(Exposed(current_attr,repeating_attr),current_attr);
}
boost::spirit::traits::assign_to(current_attr,attr_);
return true;
}
template <typename Context>
boost::spirit::info what(Context& context) const
{
return boost::spirit::info("fold");
}
InitialParser initial;
RepeatingParser repeating;
};
} /*namespace parser */
} /*namespace AMDA */
namespace boost {
namespace spirit {
namespace qi {
template <typename Expr, typename Exposed, typename Subject, typename Modifiers>
struct make_directive<tag::stateful_tag<Expr, AMDA::parser::tag::fold, Exposed>, Subject, Modifiers>
{
typedef AMDA::parser::fold_directive<Exposed, Expr, Subject> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject, Modifiers const&) const
{
typedef tag::stateful_tag<Expr, AMDA::parser::tag::fold, Exposed> tag_type;
using spirit::detail::get_stateful_data;
return result_type(get_stateful_data<tag_type>::call(term),subject);
}
};
} /* namespace qi */
} /* namespace parser */
} /* namespace AMDA */
#endif