• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2015 Joel de Guzman
3     Copyright (c) 2013-2014 Agustin Berge
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 
9 #include <boost/detail/lightweight_test.hpp>
10 #include <boost/spirit/home/x3.hpp>
11 
12 #include <string>
13 #include <cstring>
14 #include <iostream>
15 #include "test.hpp"
16 
17 int
main()18 main()
19 {
20     using spirit_test::test_attr;
21     using spirit_test::test;
22 
23     using namespace boost::spirit::x3::ascii;
24     using boost::spirit::x3::any_parser;
25     using boost::spirit::x3::make_context;
26     using boost::spirit::x3::lit;
27     using boost::spirit::x3::unused_type;
28     using boost::spirit::x3::phrase_parse;
29     using boost::spirit::x3::skip_flag;
30     using boost::spirit::x3::skipper_tag;
31     using boost::spirit::x3::_attr;
32 
33     typedef char const* iterator_type;
34     typedef decltype(make_context<skipper_tag>(space)) context_type;
35     { // basic tests
36 
37         auto a = lit('a');
38         auto b = lit('b');
39         auto c = lit('c');
40 
41         {
42             any_parser<iterator_type> start =
43                 *(a | b | c);
44 
45             BOOST_TEST(test("abcabcacb", start));
46         }
47     }
48 
49     { // basic tests w/ skipper
50 
51         auto a = lit('a');
52         auto b = lit('b');
53         auto c = lit('c');
54 
55         {
56             any_parser<iterator_type, unused_type, context_type> start =
57                 *(a | b | c);
58 
59             BOOST_TEST(test(" a b c a b c a c b ", start, space));
60         }
61     }
62 
63     { // basic tests w/ skipper but no final post-skip
64 
65         any_parser<iterator_type, unused_type, context_type> a = lit('a');
66         any_parser<iterator_type, unused_type, context_type> b = lit('b');
67         any_parser<iterator_type, unused_type, context_type> c = lit('c');
68 
69         {
70             any_parser<iterator_type, unused_type, context_type> start = *(a | b) >> c;
71 
72             char const *s1 = " a b a a b b a c ... "
73               , *const e1 = s1 + std::strlen(s1);
74             BOOST_TEST(phrase_parse(s1, e1, start, space, skip_flag::dont_post_skip)
75               && s1 == e1 - 5);
76         }
77     }
78 
79     { // context tests
80 
81         char ch;
82         any_parser<iterator_type, char> a = alpha;
83 
84         // this semantic action requires both the context and attribute
85         //!!auto f = [&](auto&, char attr){ ch = attr; };
86         //!!BOOST_TEST(test("x", a[f]));
87         //!!BOOST_TEST(ch == 'x');
88 
89         // the semantic action may have the context passed
90         auto f2 = [&](auto&){ ch = 'y'; };
91         BOOST_TEST(test("x", a[f2]));
92         BOOST_TEST(ch == 'y');
93 
94         // the semantic action may optionally not have any arguments at all
95         auto f3 = [&]{ ch = 'z'; };
96         BOOST_TEST(test("x", a[f3]));
97         BOOST_TEST(ch == 'z');
98 
99         BOOST_TEST(test_attr("z", a, ch)); // attribute is given.
100         BOOST_TEST(ch == 'z');
101     }
102 
103     { // auto rules tests
104 
105         char ch = '\0';
106         any_parser<iterator_type, char> a = alpha;
107         auto f = [&](auto& ctx){ ch = _attr(ctx); };
108 
109         BOOST_TEST(test("x", a[f]));
110         BOOST_TEST(ch == 'x');
111         ch = '\0';
112         BOOST_TEST(test_attr("z", a, ch)); // attribute is given.
113         BOOST_TEST(ch == 'z');
114 
115         ch = '\0';
116         BOOST_TEST(test("x", a[f]));
117         BOOST_TEST(ch == 'x');
118         ch = '\0';
119         BOOST_TEST(test_attr("z", a, ch)); // attribute is given.
120         BOOST_TEST(ch == 'z');
121     }
122 
123     { // auto rules tests: allow stl containers as attributes to
124       // sequences (in cases where attributes of the elements
125       // are convertible to the value_type of the container or if
126       // the element itself is an stl container with value_type
127       // that is convertible to the value_type of the attribute).
128 
129         std::string s;
130         auto f = [&](auto& ctx){ s = _attr(ctx); };
131 
132         {
133             any_parser<iterator_type, std::string> r
134                 = char_ >> *(',' >> char_)
135                 ;
136 
137             BOOST_TEST(test("a,b,c,d,e,f", r[f]));
138             BOOST_TEST(s == "abcdef");
139         }
140 
141         {
142             any_parser<iterator_type, std::string> r
143                 = char_ >> *(',' >> char_);
144             s.clear();
145             BOOST_TEST(test("a,b,c,d,e,f", r[f]));
146             BOOST_TEST(s == "abcdef");
147         }
148 
149         {
150             any_parser<iterator_type, std::string> r
151                 = char_ >> char_ >> char_ >> char_ >> char_ >> char_;
152             s.clear();
153             BOOST_TEST(test("abcdef", r[f]));
154             BOOST_TEST(s == "abcdef");
155         }
156     }
157 
158     return boost::report_errors();
159 }
160