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