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 #if !defined(BOOST_SPIRIT_CALC8_AST_HPP)
8 #define BOOST_SPIRIT_CALC8_AST_HPP
9 
10 #include <boost/config/warning_disable.hpp>
11 #include <boost/variant/recursive_variant.hpp>
12 #include <boost/fusion/include/adapt_struct.hpp>
13 #include <boost/fusion/include/io.hpp>
14 #include <boost/optional.hpp>
15 #include <list>
16 
17 namespace client { namespace ast
18 {
19     ///////////////////////////////////////////////////////////////////////////
20     //  The AST
21     ///////////////////////////////////////////////////////////////////////////
22     struct tagged
23     {
24         int id; // Used to annotate the AST with the iterator position.
25                 // This id is used as a key to a map<int, Iterator>
26                 // (not really part of the AST.)
27     };
28 
29     struct nil {};
30     struct unary;
31     struct expression;
32 
33     struct variable : tagged
34     {
variableclient::ast::variable35         variable(std::string const& name = "") : name(name) {}
36         std::string name;
37     };
38 
39     typedef boost::variant<
40             nil
41           , bool
42           , unsigned int
43           , variable
44           , boost::recursive_wrapper<unary>
45           , boost::recursive_wrapper<expression>
46         >
47     operand;
48 
49     enum optoken
50     {
51         op_plus,
52         op_minus,
53         op_times,
54         op_divide,
55         op_positive,
56         op_negative,
57         op_not,
58         op_equal,
59         op_not_equal,
60         op_less,
61         op_less_equal,
62         op_greater,
63         op_greater_equal,
64         op_and,
65         op_or
66     };
67 
68     struct unary
69     {
70         optoken operator_;
71         operand operand_;
72     };
73 
74     struct operation
75     {
76         optoken operator_;
77         operand operand_;
78     };
79 
80     struct expression
81     {
82         operand first;
83         std::list<operation> rest;
84     };
85 
86     struct assignment
87     {
88         variable lhs;
89         expression rhs;
90     };
91 
92     struct variable_declaration
93     {
94         assignment assign;
95     };
96 
97     struct if_statement;
98     struct while_statement;
99     struct statement_list;
100 
101     typedef boost::variant<
102             variable_declaration
103           , assignment
104           , boost::recursive_wrapper<if_statement>
105           , boost::recursive_wrapper<while_statement>
106           , boost::recursive_wrapper<statement_list>
107         >
108     statement;
109 
110     struct statement_list : std::list<statement> {};
111 
112     struct if_statement
113     {
114         expression condition;
115         statement then;
116         boost::optional<statement> else_;
117     };
118 
119     struct while_statement
120     {
121         expression condition;
122         statement body;
123     };
124 
125     // print functions for debugging
operator <<(std::ostream & out,nil)126     inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
operator <<(std::ostream & out,variable const & var)127     inline std::ostream& operator<<(std::ostream& out, variable const& var) { out << var.name; return out; }
128 }}
129 
130 BOOST_FUSION_ADAPT_STRUCT(
131     client::ast::unary,
132     (client::ast::optoken, operator_)
133     (client::ast::operand, operand_)
134 )
135 
136 BOOST_FUSION_ADAPT_STRUCT(
137     client::ast::operation,
138     (client::ast::optoken, operator_)
139     (client::ast::operand, operand_)
140 )
141 
142 BOOST_FUSION_ADAPT_STRUCT(
143     client::ast::expression,
144     (client::ast::operand, first)
145     (std::list<client::ast::operation>, rest)
146 )
147 
148 BOOST_FUSION_ADAPT_STRUCT(
149     client::ast::variable_declaration,
150     (client::ast::assignment, assign)
151 )
152 
153 BOOST_FUSION_ADAPT_STRUCT(
154     client::ast::assignment,
155     (client::ast::variable, lhs)
156     (client::ast::expression, rhs)
157 )
158 
159 BOOST_FUSION_ADAPT_STRUCT(
160     client::ast::if_statement,
161     (client::ast::expression, condition)
162     (client::ast::statement, then)
163     (boost::optional<client::ast::statement>, else_)
164 )
165 
166 BOOST_FUSION_ADAPT_STRUCT(
167     client::ast::while_statement,
168     (client::ast::expression, condition)
169     (client::ast::statement, body)
170 )
171 
172 #endif
173