1 /*=============================================================================
2 Copyright (c) 2001-2014 Joel de Guzman
3 Copyright (c) 2013-2014 Agustin Berge
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 ///////////////////////////////////////////////////////////////////////////////
10 // A Calculator example demonstrating generation of AST. The AST,
11 // once created, is traversed, 1) To print its contents and
12 // 2) To evaluate the result.
14 // [ JDG April 28, 2008 ] For BoostCon 2008
15 // [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
16 // [ JDG January 9, 2013 ] Spirit X3
18 ///////////////////////////////////////////////////////////////////////////////
21 # pragma warning(disable: 4345)
24 #include <boost/spirit/home/x3.hpp>
25 #include <boost/spirit/home/x3/support/ast/variant.hpp>
26 #include <boost/variant/recursive_variant.hpp>
27 #include <boost/variant/apply_visitor.hpp>
28 #include <boost/fusion/include/adapt_struct.hpp>
33 namespace x3 = boost::spirit::x3;
35 namespace client { namespace ast
37 ///////////////////////////////////////////////////////////////////////////
39 ///////////////////////////////////////////////////////////////////////////
47 , x3::forward_ast<signed_>
48 , x3::forward_ast<program>
67 std::list<operation> rest;
71 BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_,
75 BOOST_FUSION_ADAPT_STRUCT(client::ast::operation,
79 BOOST_FUSION_ADAPT_STRUCT(client::ast::program,
83 namespace client { namespace ast
85 ///////////////////////////////////////////////////////////////////////////
87 ///////////////////////////////////////////////////////////////////////////
90 typedef void result_type;
92 void operator()(nil) const {}
93 void operator()(unsigned int n) const { std::cout << n; }
95 void operator()(operation const& x) const
97 boost::apply_visitor(*this, x.operand_);
100 case '+': std::cout << " add"; break;
101 case '-': std::cout << " subt"; break;
102 case '*': std::cout << " mult"; break;
103 case '/': std::cout << " div"; break;
107 void operator()(signed_ const& x) const
109 boost::apply_visitor(*this, x.operand_);
112 case '-': std::cout << " neg"; break;
113 case '+': std::cout << " pos"; break;
117 void operator()(program const& x) const
119 boost::apply_visitor(*this, x.first);
120 for (operation const& oper: x.rest)
128 ///////////////////////////////////////////////////////////////////////////
130 ///////////////////////////////////////////////////////////////////////////
133 typedef int result_type;
135 int operator()(nil) const { BOOST_ASSERT(0); return 0; }
136 int operator()(unsigned int n) const { return n; }
138 int operator()(int lhs, operation const& x) const
140 int rhs = boost::apply_visitor(*this, x.operand_);
143 case '+': return lhs + rhs;
144 case '-': return lhs - rhs;
145 case '*': return lhs * rhs;
146 case '/': return lhs / rhs;
152 int operator()(signed_ const& x) const
154 int rhs = boost::apply_visitor(*this, x.operand_);
157 case '-': return -rhs;
158 case '+': return +rhs;
164 int operator()(program const& x) const
166 return std::accumulate( x.rest.begin(), x.rest.end()
167 , boost::apply_visitor(*this, x.first)
175 ///////////////////////////////////////////////////////////////////////////////
176 // The calculator grammar
177 ///////////////////////////////////////////////////////////////////////////////
178 namespace calculator_grammar
182 std::string::const_iterator
184 , decltype(x3::make_context<x3::skipper_tag>(x3::ascii::space))
187 parser_type calculator();
190 auto const calculator = calculator_grammar::calculator();