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 #if !defined(BOOST_SPIRIT_X3_CALC9_EXPRESSION_DEF_HPP)
8 #define BOOST_SPIRIT_X3_CALC9_EXPRESSION_DEF_HPP
9 
10 #include <boost/spirit/home/x3.hpp>
11 #include <boost/spirit/home/x3/support/utility/annotate_on_success.hpp>
12 #include "ast.hpp"
13 #include "ast_adapted.hpp"
14 #include "expression.hpp"
15 #include "common.hpp"
16 #include "error_handler.hpp"
17 
18 namespace client { namespace parser
19 {
20     using x3::uint_;
21     using x3::char_;
22     using x3::bool_;
23     using x3::raw;
24     using x3::lexeme;
25     using namespace x3::ascii;
26 
27     ////////////////////////////////////////////////////////////////////////////
28     // Tokens
29     ////////////////////////////////////////////////////////////////////////////
30 
31     x3::symbols<ast::optoken> equality_op;
32     x3::symbols<ast::optoken> relational_op;
33     x3::symbols<ast::optoken> logical_op;
34     x3::symbols<ast::optoken> additive_op;
35     x3::symbols<ast::optoken> multiplicative_op;
36     x3::symbols<ast::optoken> unary_op;
37     x3::symbols<> keywords;
38 
add_keywords()39     void add_keywords()
40     {
41         static bool once = false;
42         if (once)
43             return;
44         once = true;
45 
46         logical_op.add
47             ("&&", ast::op_and)
48             ("||", ast::op_or)
49             ;
50 
51         equality_op.add
52             ("==", ast::op_equal)
53             ("!=", ast::op_not_equal)
54             ;
55 
56         relational_op.add
57             ("<", ast::op_less)
58             ("<=", ast::op_less_equal)
59             (">", ast::op_greater)
60             (">=", ast::op_greater_equal)
61             ;
62 
63         additive_op.add
64             ("+", ast::op_plus)
65             ("-", ast::op_minus)
66             ;
67 
68         multiplicative_op.add
69             ("*", ast::op_times)
70             ("/", ast::op_divide)
71             ;
72 
73         unary_op.add
74             ("+", ast::op_positive)
75             ("-", ast::op_negative)
76             ("!", ast::op_not)
77             ;
78 
79         keywords.add
80             ("var")
81             ("true")
82             ("false")
83             ("if")
84             ("else")
85             ("while")
86             ;
87     }
88 
89     ////////////////////////////////////////////////////////////////////////////
90     // Main expression grammar
91     ////////////////////////////////////////////////////////////////////////////
92 
93     struct equality_expr_class;
94     struct relational_expr_class;
95     struct logical_expr_class;
96     struct additive_expr_class;
97     struct multiplicative_expr_class;
98     struct unary_expr_class;
99     struct primary_expr_class;
100 
101     typedef x3::rule<equality_expr_class, ast::expression> equality_expr_type;
102     typedef x3::rule<relational_expr_class, ast::expression> relational_expr_type;
103     typedef x3::rule<logical_expr_class, ast::expression> logical_expr_type;
104     typedef x3::rule<additive_expr_class, ast::expression> additive_expr_type;
105     typedef x3::rule<multiplicative_expr_class, ast::expression> multiplicative_expr_type;
106     typedef x3::rule<unary_expr_class, ast::operand> unary_expr_type;
107     typedef x3::rule<primary_expr_class, ast::operand> primary_expr_type;
108 
109     expression_type const expression = "expression";
110     equality_expr_type const equality_expr = "equality_expr";
111     relational_expr_type const relational_expr = "relational_expr";
112     logical_expr_type const logical_expr = "logical_expr";
113     additive_expr_type const additive_expr = "additive_expr";
114     multiplicative_expr_type const multiplicative_expr = "multiplicative_expr";
115     unary_expr_type const unary_expr = "unary_expr";
116     primary_expr_type const primary_expr = "primary_expr";
117 
118     auto const logical_expr_def =
119             equality_expr
120         >> *(logical_op > equality_expr)
121         ;
122 
123     auto const equality_expr_def =
124             relational_expr
125         >> *(equality_op > relational_expr)
126         ;
127 
128     auto const relational_expr_def =
129             additive_expr
130         >> *(relational_op > additive_expr)
131         ;
132 
133     auto const additive_expr_def =
134             multiplicative_expr
135         >> *(additive_op > multiplicative_expr)
136         ;
137 
138     auto const multiplicative_expr_def =
139             unary_expr
140         >> *(multiplicative_op > unary_expr)
141         ;
142 
143     auto const unary_expr_def =
144             primary_expr
145         |   (unary_op > primary_expr)
146         ;
147 
148     auto const primary_expr_def =
149             uint_
150         |   bool_
151         |   (!keywords >> identifier)
152         |   '(' > expression > ')'
153         ;
154 
155     auto const expression_def = logical_expr;
156 
157     BOOST_SPIRIT_DEFINE(
158         expression
159       , logical_expr
160       , equality_expr
161       , relational_expr
162       , additive_expr
163       , multiplicative_expr
164       , unary_expr
165       , primary_expr
166     );
167 
168     struct unary_expr_class : x3::annotate_on_success {};
169     struct primary_expr_class : x3::annotate_on_success {};
170 
171 }}
172 
173 namespace client
174 {
expression()175     parser::expression_type const& expression()
176     {
177         parser::add_keywords();
178         return parser::expression;
179     }
180 }
181 
182 #endif
183