• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2011 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 plain functions. The parser prints code suitable for a stack
11 //  based virtual machine.
12 //
13 //  [ JDG May 10, 2002 ]        spirit1
14 //  [ JDG March 4, 2007 ]       spirit2
15 //  [ JDG February 21, 2011 ]   spirit2.5
16 //
17 ///////////////////////////////////////////////////////////////////////////////
18 
19 // Spirit v2.5 allows you to suppress automatic generation
20 // of predefined terminals to speed up complation. With
21 // BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
22 // responsible in creating instances of the terminals that
23 // you need (e.g. see qi::uint_type uint_ below).
24 #define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
25 
26 #include <boost/config/warning_disable.hpp>
27 #include <boost/spirit/include/qi.hpp>
28 
29 #include <iostream>
30 #include <string>
31 
32 namespace client
33 {
34     namespace qi = boost::spirit::qi;
35     namespace ascii = boost::spirit::ascii;
36 
37     ///////////////////////////////////////////////////////////////////////////////
38     //  Semantic actions
39     ////////////////////////////////////////////////////////1///////////////////////
40     namespace
41     {
do_int(int n)42         void do_int(int n)  { std::cout << "push " << n << std::endl; }
do_add()43         void do_add()       { std::cout << "add\n"; }
do_subt()44         void do_subt()      { std::cout << "subtract\n"; }
do_mult()45         void do_mult()      { std::cout << "mult\n"; }
do_div()46         void do_div()       { std::cout << "divide\n"; }
do_neg()47         void do_neg()       { std::cout << "negate\n"; }
48     }
49 
50     ///////////////////////////////////////////////////////////////////////////////
51     //  Our calculator grammar
52     ///////////////////////////////////////////////////////////////////////////////
53     template <typename Iterator>
54     struct calculator : qi::grammar<Iterator, ascii::space_type>
55     {
calculatorclient::calculator56         calculator() : calculator::base_type(expression)
57         {
58             qi::uint_type uint_;
59 
60             expression =
61                 term
62                 >> *(   ('+' >> term            [&do_add])
63                     |   ('-' >> term            [&do_subt])
64                     )
65                 ;
66 
67             term =
68                 factor
69                 >> *(   ('*' >> factor          [&do_mult])
70                     |   ('/' >> factor          [&do_div])
71                     )
72                 ;
73 
74             factor =
75                 uint_                           [&do_int]
76                 |   '(' >> expression >> ')'
77                 |   ('-' >> factor              [&do_neg])
78                 |   ('+' >> factor)
79                 ;
80         }
81 
82         qi::rule<Iterator, ascii::space_type> expression, term, factor;
83     };
84 }
85 
86 ///////////////////////////////////////////////////////////////////////////////
87 //  Main program
88 ///////////////////////////////////////////////////////////////////////////////
89 int
main()90 main()
91 {
92     std::cout << "/////////////////////////////////////////////////////////\n\n";
93     std::cout << "Expression parser...\n\n";
94     std::cout << "/////////////////////////////////////////////////////////\n\n";
95     std::cout << "Type an expression...or [q or Q] to quit\n\n";
96 
97     typedef std::string::const_iterator iterator_type;
98     typedef client::calculator<iterator_type> calculator;
99 
100     boost::spirit::ascii::space_type space; // Our skipper
101     calculator calc; // Our grammar
102 
103     std::string str;
104     while (std::getline(std::cin, str))
105     {
106         if (str.empty() || str[0] == 'q' || str[0] == 'Q')
107             break;
108 
109         std::string::const_iterator iter = str.begin();
110         std::string::const_iterator end = str.end();
111         bool r = phrase_parse(iter, end, calc, space);
112 
113         if (r && iter == end)
114         {
115             std::cout << "-------------------------\n";
116             std::cout << "Parsing succeeded\n";
117             std::cout << "-------------------------\n";
118         }
119         else
120         {
121             std::string rest(iter, end);
122             std::cout << "-------------------------\n";
123             std::cout << "Parsing failed\n";
124             std::cout << "stopped at: \" " << rest << "\"\n";
125             std::cout << "-------------------------\n";
126         }
127     }
128 
129     std::cout << "Bye... :-) \n\n";
130     return 0;
131 }
132