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/spirit/include/qi.hpp>
27
28#include <iostream>
29#include <string>
30
31namespace client
32{
33 namespace qi = boost::spirit::qi;
34 namespace ascii = boost::spirit::ascii;
35
36 ///////////////////////////////////////////////////////////////////////////////
37 // Semantic actions
38 ////////////////////////////////////////////////////////1///////////////////////
39 namespace
40 {
41 void do_int(int n) { std::cout << "push " << n << std::endl; }
42 void do_add() { std::cout << "add\n"; }
43 void do_subt() { std::cout << "subtract\n"; }
44 void do_mult() { std::cout << "mult\n"; }
45 void do_div() { std::cout << "divide\n"; }
46 void do_neg() { std::cout << "negate\n"; }
47 }
48
49 ///////////////////////////////////////////////////////////////////////////////
50 // Our calculator grammar
51 ///////////////////////////////////////////////////////////////////////////////
52 template <typename Iterator>
53 struct calculator : qi::grammar<Iterator, ascii::space_type>
54 {
55 calculator() : calculator::base_type(expression)
56 {
57 qi::uint_type uint_;
58
59 expression =
60 term
61 >> *( ('+' >> term [&do_add])
62 | ('-' >> term [&do_subt])
63 )
64 ;
65
66 term =
67 factor
68 >> *( ('*' >> factor [&do_mult])
69 | ('/' >> factor [&do_div])
70 )
71 ;
72
73 factor =
74 uint_ [&do_int]
75 | '(' >> expression >> ')'
76 | ('-' >> factor [&do_neg])
77 | ('+' >> factor)
78 ;
79 }
80
81 qi::rule<Iterator, ascii::space_type> expression, term, factor;
82 };
83}
84
85///////////////////////////////////////////////////////////////////////////////
86// Main program
87///////////////////////////////////////////////////////////////////////////////
88int
89main()
90{
91 std::cout << "/////////////////////////////////////////////////////////\n\n";
92 std::cout << "Expression parser...\n\n";
93 std::cout << "/////////////////////////////////////////////////////////\n\n";
94 std::cout << "Type an expression...or [q or Q] to quit\n\n";
95
96 typedef std::string::const_iterator iterator_type;
97 typedef client::calculator<iterator_type> calculator;
98
99 boost::spirit::ascii::space_type space; // Our skipper
100 calculator calc; // Our grammar
101
102 std::string str;
103 while (std::getline(is&: std::cin, str&: str))
104 {
105 if (str.empty() || str[0] == 'q' || str[0] == 'Q')
106 break;
107
108 std::string::const_iterator iter = str.begin();
109 std::string::const_iterator end = str.end();
110 bool r = phrase_parse(first&: iter, last: end, expr&: calc, skipper: space);
111
112 if (r && iter == end)
113 {
114 std::cout << "-------------------------\n";
115 std::cout << "Parsing succeeded\n";
116 std::cout << "-------------------------\n";
117 }
118 else
119 {
120 std::string rest(iter, end);
121 std::cout << "-------------------------\n";
122 std::cout << "Parsing failed\n";
123 std::cout << "stopped at: \" " << rest << "\"\n";
124 std::cout << "-------------------------\n";
125 }
126 }
127
128 std::cout << "Bye... :-) \n\n";
129 return 0;
130}
131

source code of boost/libs/spirit/example/qi/compiler_tutorial/calc2.cpp