Ticket #6106: map.hpp

File map.hpp, 3.0 KB (added by oakad@…, 11 years ago)

Implementation of the map[] directive in the repository::qi namespace

Line 
1/*=============================================================================
2 Copyright (c) 2011 Alex Dubov
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(SPIRIT_MAP)
8#define SPIRIT_MAP
9
10#if defined(_MSC_VER)
11#pragma once
12#endif
13
14#include <boost/spirit/home/qi/parser.hpp>
15#include <boost/spirit/home/qi/detail/assign_to.hpp>
16#include <boost/spirit/home/support/unused.hpp>
17#include <boost/spirit/home/support/info.hpp>
18#include <boost/spirit/home/support/common_terminals.hpp>
19#include <boost/spirit/home/support/unused.hpp>
20#include <boost/spirit/home/support/has_semantic_action.hpp>
21#include <boost/spirit/home/support/assert_msg.hpp>
22#include <map>
23#include <iostream>
24
25namespace boost { namespace spirit {
26namespace repository
27{
28 BOOST_SPIRIT_DEFINE_TERMINALS_NAME_EX((map, map_type))
29}
30
31template <typename T, typename U>
32struct use_directive<
33 qi::domain,
34 terminal_ex<repository::tag::map, fusion::vector1<std::map<T, U> > >
35> : mpl::true_ {};
36
37template <>
38struct use_lazy_directive<qi::domain, repository::tag::map, 1> : mpl::true_ {};
39
40namespace repository { namespace qi
41{
42 using repository::map_type;
43 using repository::map;
44
45 template <typename Subject, typename T, typename U>
46 struct map_parser : spirit::qi::unary_parser<map_parser<Subject, T, U> >
47 {
48 template <typename Context, typename Iterator>
49 struct attribute : mpl::identity<U> {};
50
51 map_parser(Subject const& subject, std::map<T, U> const& lookup)
52 : subject(subject), lookup(lookup) {}
53
54 template <typename Iterator, typename Context, typename Skipper,
55 typename Attribute>
56 bool parse(Iterator& first, Iterator const& last,
57 Context& context, Skipper const& skipper,
58 Attribute& attr) const
59 {
60 T attr_;
61
62 Iterator iter = first;
63 typename std::map<T, U>::const_iterator attr_iter;
64
65 if (subject.parse(iter, last, context, skipper,
66 attr_)) {
67 attr_iter = lookup.find(attr_);
68 if (attr_iter != lookup.end()) {
69 attr = attr_iter->second;
70 first = iter;
71 return true;
72 }
73 }
74 return false;
75 }
76
77 template <typename Context>
78 info what(Context const& ctx) const
79 {
80 return info("map", subject.what(ctx));
81 }
82
83 Subject subject;
84 std::map<T, U> lookup;
85 };
86}}
87
88namespace qi
89{
90 template <typename T, typename U, typename Subject, typename Modifiers>
91 struct make_directive<
92 terminal_ex<repository::tag::map,
93 fusion::vector1<std::map<T, U> > >,
94 Subject, Modifiers
95 >
96 {
97 typedef repository::qi::map_parser<Subject, T, U> result_type;
98
99 template <typename Terminal>
100 result_type operator()(
101 Terminal const& term,
102 Subject const& subject,
103 Modifiers const& modifiers
104 ) const
105 {
106 return result_type(subject, fusion::at_c<0>(term.args));
107 }
108 };
109}
110
111namespace traits
112{
113 template <typename Subject, typename T, typename U>
114 struct has_semantic_action<
115 repository::qi::map_parser<Subject, T, U>
116 > : unary_has_semantic_action<Subject> {};
117}}}
118
119#endif