1 /*==============================================================================
2     Copyright (c) 2001-2011 Hartmut Kaiser
3     Copyright (c) 2010-2011 Bryce Lelbach
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 
9 #if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_GENERATOR_HPP)
10 #define BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_GENERATOR_HPP
11 
12 #include <boost/spirit/include/support_utree.hpp>
13 #include <boost/spirit/include/karma.hpp>
14 
15 namespace boost {
16 namespace spirit {
17 namespace traits {
18 
19 template<>
20 struct transform_attribute<utree::nil_type, unused_type, karma::domain> {
21   typedef unused_type type;
22 
preboost::spirit::traits::transform_attribute23   static unused_type pre (utree::nil_type&) { return unused_type(); }
24 };
25 
26 } // traits
27 } // spirit
28 } // boost
29 
30 namespace sexpr
31 {
32 
33 namespace karma = boost::spirit::karma;
34 namespace standard = boost::spirit::standard;
35 
36 using boost::spirit::utree;
37 using boost::spirit::utf8_symbol_range_type;
38 using boost::spirit::utf8_string_range_type;
39 using boost::spirit::binary_range_type;
40 
41 struct bool_output_policies : karma::bool_policies<>
42 {
43     template <typename CharEncoding, typename Tag, typename Iterator>
generate_truesexpr::bool_output_policies44     static bool generate_true(Iterator& sink, bool)
45     {
46         return string_inserter<CharEncoding, Tag>::call(sink, "#t");
47     }
48 
49     template <typename CharEncoding, typename Tag, typename Iterator>
generate_falsesexpr::bool_output_policies50     static bool generate_false(Iterator& sink, bool)
51     {
52         return string_inserter<CharEncoding, Tag>::call(sink, "#f");
53     }
54 };
55 
56 template <typename Iterator>
57 struct generator : karma::grammar<Iterator, utree()>
58 {
59     typedef boost::iterator_range<utree::const_iterator> utree_list;
60 
61     karma::rule<Iterator, utree()>
62         start, ref_;
63 
64     karma::rule<Iterator, utree_list()>
65         list;
66 
67     karma::rule<Iterator, utf8_symbol_range_type()>
68         symbol;
69 
70     karma::rule<Iterator, utree::nil_type()>
71         nil_;
72 
73     karma::rule<Iterator, utf8_string_range_type()>
74         utf8;
75 
76     karma::rule<Iterator, binary_range_type()>
77         binary;
78 
generatorsexpr::generator79     generator() : generator::base_type(start)
80     {
81         using standard::char_;
82         using standard::string;
83         using karma::bool_generator;
84         using karma::uint_generator;
85         using karma::double_;
86         using karma::int_;
87         using karma::lit;
88         using karma::right_align;
89 
90         uint_generator<unsigned char, 16> hex2;
91         bool_generator<bool, bool_output_policies> boolean;
92 
93         start = nil_
94               | double_
95               | int_
96               | boolean
97               | utf8
98               | symbol
99               | binary
100               | list
101               | ref_;
102 
103         ref_ = start;
104 
105         list = '(' << -(start % ' ') << ')';
106 
107         utf8 = '"' << *(&char_('"') << "\\\"" | char_) << '"';
108 
109         symbol = string;
110 
111         binary = '#' << *right_align(2, '0')[hex2] << '#';
112 
113         nil_ = karma::attr_cast(lit("nil"));
114 
115         start.name("sexpr");
116         ref_.name("ref");
117         list.name("list");
118         utf8.name("string");
119         symbol.name("symbol");
120         binary.name("binary");
121         nil_.name("nil");
122     }
123 };
124 
125 } // sexpr
126 
127 #endif // BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_GENERATOR_HPP
128 
129