1 /*=============================================================================
2 Copyright (c) 2001-2014 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 ///////////////////////////////////////////////////////////////////////////////
8 //
9 // A Calculator example demonstrating the grammar and semantic actions
10 // using lambda functions. The parser prints code suitable for a stack
11 // based virtual machine.
12 //
13 // [ JDG May 10, 2002 ] spirit 1
14 // [ JDG March 4, 2007 ] spirit 2
15 // [ JDG February 21, 2011 ] spirit 2.5
16 // [ JDG June 6, 2014 ] spirit x3 (from qi calc2, but using lambda functions)
17 //
18 ///////////////////////////////////////////////////////////////////////////////
19
20 #include <boost/config/warning_disable.hpp>
21 #include <boost/spirit/home/x3.hpp>
22 #include <boost/spirit/home/x3/support/ast/variant.hpp>
23 #include <boost/fusion/include/adapt_struct.hpp>
24
25 #include <iostream>
26 #include <string>
27 #include <list>
28 #include <numeric>
29
30 namespace x3 = boost::spirit::x3;
31
32 namespace client
33 {
34 ///////////////////////////////////////////////////////////////////////////////
35 // Semantic actions
36 ////////////////////////////////////////////////////////1///////////////////////
37 namespace
38 {
39 using x3::_attr;
40
__anon4415f1c90202(auto& ctx) 41 auto do_int = [](auto& ctx) { std::cout << "push " << _attr(ctx) << std::endl; };
__anon4415f1c90302null42 auto do_add = []{ std::cout << "add\n"; };
__anon4415f1c90402null43 auto do_subt = []{ std::cout << "subtract\n"; };
__anon4415f1c90502null44 auto do_mult = []{ std::cout << "mult\n"; };
__anon4415f1c90602null45 auto do_div = []{ std::cout << "divide\n"; };
__anon4415f1c90702null46 auto do_neg = []{ std::cout << "negate\n"; };
47 }
48
49 ///////////////////////////////////////////////////////////////////////////////
50 // The calculator grammar
51 ///////////////////////////////////////////////////////////////////////////////
52 namespace calculator_grammar
53 {
54 using x3::uint_;
55 using x3::char_;
56
57 x3::rule<class expression> const expression("expression");
58 x3::rule<class term> const term("term");
59 x3::rule<class factor> const factor("factor");
60
61 auto const expression_def =
62 term
63 >> *( ('+' >> term [do_add])
64 | ('-' >> term [do_subt])
65 )
66 ;
67
68 auto const term_def =
69 factor
70 >> *( ('*' >> factor [do_mult])
71 | ('/' >> factor [do_div])
72 )
73 ;
74
75 auto const factor_def =
76 uint_ [do_int]
77 | '(' >> expression >> ')'
78 | ('-' >> factor [do_neg])
79 | ('+' >> factor)
80 ;
81
82 BOOST_SPIRIT_DEFINE(
83 expression
84 , term
85 , factor
86 );
87
88 auto calculator = expression;
89 }
90
91 using calculator_grammar::calculator;
92
93 }
94
95 ///////////////////////////////////////////////////////////////////////////////
96 // Main program
97 ///////////////////////////////////////////////////////////////////////////////
98 int
main()99 main()
100 {
101 std::cout << "/////////////////////////////////////////////////////////\n\n";
102 std::cout << "Expression parser...\n\n";
103 std::cout << "/////////////////////////////////////////////////////////\n\n";
104 std::cout << "Type an expression...or [q or Q] to quit\n\n";
105
106 typedef std::string::const_iterator iterator_type;
107
108 std::string str;
109 while (std::getline(std::cin, str))
110 {
111 if (str.empty() || str[0] == 'q' || str[0] == 'Q')
112 break;
113
114 auto& calc = client::calculator; // Our grammar
115
116 iterator_type iter = str.begin();
117 iterator_type end = str.end();
118 boost::spirit::x3::ascii::space_type space;
119 bool r = phrase_parse(iter, end, calc, space);
120
121 if (r && iter == end)
122 {
123 std::cout << "-------------------------\n";
124 std::cout << "Parsing succeeded\n";
125 std::cout << "-------------------------\n";
126 }
127 else
128 {
129 std::string rest(iter, end);
130 std::cout << "-------------------------\n";
131 std::cout << "Parsing failed\n";
132 std::cout << "stopped at: \"" << rest << "\"\n";
133 std::cout << "-------------------------\n";
134 }
135 }
136
137 std::cout << "Bye... :-) \n\n";
138 return 0;
139 }
140