• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2003 Daniel Nuffer
3     http://spirit.sourceforge.net/
4 
5     Use, modification and distribution is subject to the Boost Software
6     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7     http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #include <boost/spirit/include/classic_core.hpp>
10 #include <boost/spirit/include/classic_ast.hpp>
11 #include <boost/assert.hpp>
12 
13 #include <iostream>
14 #include <stack>
15 #include <functional>
16 #include <string>
17 
18 // This example shows how to use an AST and tree_iter_node instead of
19 // tree_val_node
20 ////////////////////////////////////////////////////////////////////////////
21 using namespace std;
22 using namespace BOOST_SPIRIT_CLASSIC_NS;
23 
24 typedef char const*         iterator_t;
25 typedef tree_match<iterator_t, node_iter_data_factory<> >
26     parse_tree_match_t;
27 
28 typedef parse_tree_match_t::tree_iterator iter_t;
29 
30 typedef ast_match_policy<iterator_t, node_iter_data_factory<> > match_policy_t;
31 typedef scanner<iterator_t, scanner_policies<iter_policy_t, match_policy_t> > scanner_t;
32 typedef rule<scanner_t> rule_t;
33 
34 
35 //  grammar rules
36 rule_t expression, term, factor, integer;
37 
38 ////////////////////////////////////////////////////////////////////////////
39 long evaluate(parse_tree_match_t hit);
40 long eval_expression(iter_t const& i);
41 long eval_term(iter_t const& i);
42 long eval_factor(iter_t const& i);
43 long eval_integer(iter_t const& i);
44 
evaluate(parse_tree_match_t hit)45 long evaluate(parse_tree_match_t hit)
46 {
47     return eval_expression(hit.trees.begin());
48 }
49 
eval_expression(iter_t const & i)50 long eval_expression(iter_t const& i)
51 {
52     cout << "In eval_expression. i->value = " <<
53         string(i->value.begin(), i->value.end()) <<
54         " i->children.size() = " << i->children.size() << endl;
55 
56     cout << "ID: " << i->value.id().to_long() << endl;
57 
58     if (i->value.id() == integer.id())
59     {
60         BOOST_ASSERT(i->children.size() == 0);
61         return strtol(i->value.begin(), 0, 10);
62     }
63     else if (i->value.id() == factor.id())
64     {
65         // factor can only be unary minus
66         BOOST_ASSERT(*i->value.begin() == '-');
67         return - eval_expression(i->children.begin());
68     }
69     else if (i->value.id() == term.id())
70     {
71         if (*i->value.begin() == '*')
72         {
73             BOOST_ASSERT(i->children.size() == 2);
74             return eval_expression(i->children.begin()) *
75                 eval_expression(i->children.begin()+1);
76         }
77         else if (*i->value.begin() == '/')
78         {
79             BOOST_ASSERT(i->children.size() == 2);
80             return eval_expression(i->children.begin()) /
81                 eval_expression(i->children.begin()+1);
82         }
83         else
84             BOOST_ASSERT(0);
85     }
86     else if (i->value.id() == expression.id())
87     {
88         if (*i->value.begin() == '+')
89         {
90             BOOST_ASSERT(i->children.size() == 2);
91             return eval_expression(i->children.begin()) +
92                 eval_expression(i->children.begin()+1);
93         }
94         else if (*i->value.begin() == '-')
95         {
96             BOOST_ASSERT(i->children.size() == 2);
97             return eval_expression(i->children.begin()) -
98                 eval_expression(i->children.begin()+1);
99         }
100         else
101             BOOST_ASSERT(0);
102     }
103     else
104         BOOST_ASSERT(0); // error
105 
106    return 0;
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////
110 int
main()111 main()
112 {
113     BOOST_SPIRIT_DEBUG_RULE(integer);
114     BOOST_SPIRIT_DEBUG_RULE(factor);
115     BOOST_SPIRIT_DEBUG_RULE(term);
116     BOOST_SPIRIT_DEBUG_RULE(expression);
117     //  Start grammar definition
118     integer     =   leaf_node_d[ lexeme_d[ (!ch_p('-') >> +digit_p) ] ];
119     factor      =   integer
120                 |   inner_node_d[ch_p('(') >> expression >> ch_p(')')]
121                 |   (root_node_d[ch_p('-')] >> factor);
122     term        =   factor >>
123                     *(  (root_node_d[ch_p('*')] >> factor)
124                       | (root_node_d[ch_p('/')] >> factor)
125                     );
126     expression  =   term >>
127                     *(  (root_node_d[ch_p('+')] >> term)
128                       | (root_node_d[ch_p('-')] >> term)
129                     );
130     //  End grammar definition
131 
132 
133     cout << "/////////////////////////////////////////////////////////\n\n";
134     cout << "\t\tThe simplest working calculator...\n\n";
135     cout << "/////////////////////////////////////////////////////////\n\n";
136     cout << "Type an expression...or [q or Q] to quit\n\n";
137 
138     string str;
139     while (getline(cin, str))
140     {
141         if (str.empty() || str[0] == 'q' || str[0] == 'Q')
142             break;
143 
144         const char* str_begin = str.c_str();
145         const char* str_end = str.c_str();
146         while (*str_end)
147             ++str_end;
148 
149         scanner_t scan(str_begin, str_end);
150 
151         parse_tree_match_t hit = expression.parse(scan);
152 
153 
154         if (hit && str_begin == str_end)
155         {
156 #if defined(BOOST_SPIRIT_DUMP_PARSETREE_AS_XML)
157             // dump parse tree as XML
158             std::map<rule_id, std::string> rule_names;
159             rule_names[&integer] = "integer";
160             rule_names[&factor] = "factor";
161             rule_names[&term] = "term";
162             rule_names[&expression] = "expression";
163             tree_to_xml(cout, hit.trees, str.c_str(), rule_names);
164 #endif
165 
166             // print the result
167             cout << "parsing succeeded\n";
168             cout << "result = " << evaluate(hit) << "\n\n";
169         }
170         else
171         {
172             cout << "parsing failed\n";
173         }
174     }
175 
176     cout << "Bye... :-) \n\n";
177     return 0;
178 }
179 
180 
181