• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2   Copyright (c) 2001-2015 Joel de Guzman
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 #include <boost/detail/lightweight_test.hpp>
8 #include <boost/spirit/home/x3.hpp>
9 #include <boost/fusion/include/at_key.hpp>
10 #include <boost/fusion/include/make_map.hpp>
11 #include <boost/fusion/adapted/struct.hpp>
12 
13 #include <string>
14 #include <iostream>
15 #include "test.hpp"
16 
17 struct AdaptedStruct {
18     std::string key1;
19     std::string key2;
20 };
21 
22 class key1_attr {};
23 class key2_attr {};
24 
25 BOOST_FUSION_ADAPT_ASSOC_STRUCT(
26     AdaptedStruct,
27     (std::string, key1, class key1_attr)
28     (std::string, key2, class key2_attr)
29     )
30 
31 template <class Parser, class Attribute>
test_attr(const std::string in,Parser const & p,Attribute & attr)32 bool test_attr(const std::string in,Parser const& p, Attribute& attr) {
33     auto it = in.begin();
34     return boost::spirit::x3::parse(it,in.end(), p, attr);
35 }
36 
37 int
main()38 main()
39 {
40     using spirit_test::test;
41     using boost::spirit::x3::lit;
42     using boost::spirit::x3::attr;
43     using boost::spirit::x3::char_;
44     using boost::spirit::x3::eps;
45     namespace fusion = boost::fusion;
46 
47     { // parsing sequence directly into fusion map
48 
49         auto const key1 = lit("key1") >> attr(key1_attr());
50         auto const kv1 = key1 >> lit("=") >> +char_;
51 
52         {
53            auto attr_ =  fusion::make_map<key1_attr>(std::string());
54            BOOST_TEST(test_attr("key1=ABC", kv1, attr_));
55            BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC");
56         }
57         {
58            AdaptedStruct attr_;
59            BOOST_TEST(test_attr("key1=ABC", kv1, attr_));
60            BOOST_TEST(attr_.key1 == "ABC");
61            BOOST_TEST(attr_.key2 == "");
62         }
63         }
64         {   // case when parser handling fusion assoc sequence
65             // is on one side of another sequence
66             auto const key1 = lit("key1") >> attr(key1_attr());
67             auto const kv1 = key1 >> lit("=") >> +~char_(';');
68 
69             AdaptedStruct attr_;
70             BOOST_TEST(test_attr("key1=ABC", eps >>  (kv1 % ';') , attr_));
71             BOOST_TEST(attr_.key1 == "ABC");
72             BOOST_TEST(attr_.key2 == "");
73         }
74         { // parsing repeated sequence directly into fusion map (overwrite)
75           auto const key1 = lit("key1") >> attr(key1_attr());
76           auto const kv1 = key1 >> lit("=") >> +~char_(';');
77 
78         {
79            auto attr_ =  fusion::make_map<key1_attr>(std::string());
80            BOOST_TEST(test_attr("key1=ABC;key1=XYZ", kv1 % ';', attr_));
81            BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "XYZ");
82         }
83         {
84            AdaptedStruct attr_;
85            BOOST_TEST(test_attr("key1=ABC;key1=XYZ", kv1 % ';', attr_));
86            BOOST_TEST(attr_.key1 == "XYZ");
87         }
88     }
89 
90     {   // parsing repeated sequence directly into fusion map (append)
91 
92         /* NOT IMPLEMENTED
93         auto const key1 = lit("key1") >> attr(key1_attr());
94         auto const kv1 = key1 >> lit("=") >> +char_;
95         auto attr_ =  fusion::make_map<key1_attr>(std::vector<std::string>());
96 
97         BOOST_TEST(test_attr("key1=ABC;key1=XYZ", kv1 % ";", attr_));
98         BOOST_TEST(fusion::at_key<key1_attr>(attr_) == {"ABC","XYZ"});
99         */
100     }
101 
102     { // alternative over key-value pairs
103 
104         auto const key1 = lit("key1") >> attr(key1_attr());
105         auto const key2 = lit("key2") >> attr(key2_attr());
106         auto const kv1 = key1 >> lit("=") >> +~char_(';');
107         auto const kv2 = key2 >> lit("=") >> +~char_(';');
108 
109         auto attr_ =  fusion::make_map<key1_attr, key2_attr>(std::string(),std::string());
110         BOOST_TEST(test_attr("key2=XYZ;key1=ABC", (kv1|kv2) % ';', attr_));
111         BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC");
112         BOOST_TEST(fusion::at_key<key2_attr>(attr_) == "XYZ");
113     }
114 
115     { // parsing sequence where key is a variant
116 
117         namespace x3 = boost::spirit::x3;
118         auto  key1 = lit("key1") >> attr(key1_attr());
119         auto  key2 = lit("key2") >> attr(key2_attr());
120         auto  keys = key1 | key2;
121         auto pair = keys >> lit("=") >> +~char_(';');
122 
123         {
124             auto attr_ =  fusion::make_map<key1_attr,key2_attr>(std::string(),std::string());
125             BOOST_TEST(test_attr("key1=ABC;key2=XYZ", pair % ';', attr_));
126             BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC");
127             BOOST_TEST(fusion::at_key<key2_attr>(attr_) == "XYZ");
128         }
129         {
130             AdaptedStruct attr_;
131             BOOST_TEST(test_attr("key1=ABC;key2=XYZ", pair % ';', attr_));
132             BOOST_TEST(fusion::at_key<key1_attr>(attr_) == "ABC");
133             BOOST_TEST(fusion::at_key<key2_attr>(attr_) == "XYZ");
134         }
135     }
136 
137     return boost::report_errors();
138 }
139