Blame view

src/expressionParser/CustomFoldDirective.hh 3 KB
a7f2648e   Benjamin Renard   Parser: First imp...
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
#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 {

f5ef5545   Benjamin Renard   Fix operators sym...
32
33
template <typename Exposed, typename InitialParser, typename RepeatingParser>
struct fold_directive
a7f2648e   Benjamin Renard   Parser: First imp...
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
{
	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