1 /*=============================================================================
2 Copyright (c) 2001-2007 Hartmut Kaiser
3 http://spirit.sourceforge.net/
5 Use, modification and distribution is subject to the Boost Software
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
10 #include <boost/detail/lightweight_test.hpp>
11 #include <boost/preprocessor/cat.hpp>
12 #include <boost/spirit/include/classic_core.hpp>
13 #include <boost/spirit/include/classic_ast.hpp>
14 #include <boost/spirit/include/classic_tree_to_xml.hpp>
17 # pragma warning(push)
18 # pragma warning(disable: 4702) // unreachable code
20 #include <boost/iostreams/stream.hpp>
29 using namespace BOOST_SPIRIT_CLASSIC_NS;
31 ///////////////////////////////////////////////////////////////////////////////
32 struct calculator : public grammar<calculator>
34 static const int integerID = 1;
35 static const int factorID = 2;
36 static const int termID = 3;
37 static const int expressionID = 4;
39 template <typename ScannerT>
42 definition(calculator const& /*self*/)
44 // Start grammar definition
45 integer = leaf_node_d[ lexeme_d[
46 (!ch_p('-') >> +digit_p)
50 | inner_node_d[ch_p('(') >> expression >> ch_p(')')]
51 | (root_node_d[ch_p('-')] >> factor);
54 *( (root_node_d[ch_p('*')] >> factor)
55 | (root_node_d[ch_p('/')] >> factor)
59 *( (root_node_d[ch_p('+')] >> term)
60 | (root_node_d[ch_p('-')] >> term)
62 // End grammar definition
64 // turn on the debugging info.
65 BOOST_SPIRIT_DEBUG_RULE(integer);
66 BOOST_SPIRIT_DEBUG_RULE(factor);
67 BOOST_SPIRIT_DEBUG_RULE(term);
68 BOOST_SPIRIT_DEBUG_RULE(expression);
71 rule<ScannerT, parser_context<>, parser_tag<expressionID> > expression;
72 rule<ScannerT, parser_context<>, parser_tag<termID> > term;
73 rule<ScannerT, parser_context<>, parser_tag<factorID> > factor;
74 rule<ScannerT, parser_context<>, parser_tag<integerID> > integer;
76 rule<ScannerT, parser_context<>, parser_tag<expressionID> > const&
77 start() const { return expression; }
81 ///////////////////////////////////////////////////////////////////////////////
82 /// this is a Boost.IoStreams source device usable to create a istream on
83 /// top of a random access container (i.e. vector<>)
84 template<typename Container>
85 class container_device
88 typedef typename Container::value_type char_type;
89 typedef boost::iostreams::sink_tag category;
91 container_device(Container& container)
92 : container_(container), pos_(0)
95 /// Write up to n characters to the underlying data sink into the
96 /// buffer s, returning the number of characters written
97 std::streamsize write(const char_type* s, std::streamsize n)
99 std::streamsize result = 0;
100 if (pos_ != container_.size()) {
101 std::streamsize amt =
102 static_cast<std::streamsize>(container_.size() - pos_);
103 result = (std::min)(n, amt);
104 std::copy(s, s + result, container_.begin() + pos_);
105 pos_ += static_cast<size_type>(result);
108 container_.insert(container_.end(), s, s + n);
109 pos_ = container_.size();
114 Container& container() { return container_; }
117 typedef typename Container::size_type size_type;
118 Container& container_;
122 ///////////////////////////////////////////////////////////////////////////////
123 #define EXPECTED_XML_OUTPUT "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n\
124 <!DOCTYPE parsetree SYSTEM \"parsetree.dtd\">\n\
126 <parsetree version=\"1.0\">\n\
138 #define EXPECTED_XML_OUTPUT_WIDE BOOST_PP_CAT(L, EXPECTED_XML_OUTPUT)
140 bool test(wchar_t const *text)
142 typedef std::basic_string<wchar_t>::iterator iterator_t;
144 std::basic_string<wchar_t> input(text);
146 tree_parse_info<iterator_t> ast_info =
147 ast_parse(iterator_t(input.begin()), iterator_t(input.end()),
148 calc >> end_p, space_p);
150 std::basic_string<wchar_t> out;
152 typedef container_device<std::basic_string<wchar_t> > device_type;
153 boost::iostreams::stream<device_type> outsink(out);
154 basic_tree_to_xml<wchar_t>(outsink, ast_info.trees, input);
156 return out == EXPECTED_XML_OUTPUT_WIDE;
159 bool test(char const *text)
161 typedef std::string::iterator iterator_t;
163 std::string input(text);
165 tree_parse_info<iterator_t> ast_info =
166 ast_parse(iterator_t(input.begin()), iterator_t(input.end()),
167 calc >> end_p, space_p);
171 typedef container_device<std::string> device_type;
172 boost::iostreams::stream<device_type> outsink(out);
173 basic_tree_to_xml<char>(outsink, ast_info.trees, input);
175 return out == EXPECTED_XML_OUTPUT;
180 BOOST_TEST(test("1+2"));
181 if (std::has_facet<std::ctype<wchar_t> >(std::locale()))
183 BOOST_TEST(test(L"1+2"));
185 return boost::report_errors();