• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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