1 /*
2 * Copyright (c) 2003-2018, John Wiegley. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of New Artisans LLC nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /**
33 * @addtogroup expr
34 */
35
36 /**
37 * @file expr.h
38 * @author John Wiegley
39 *
40 * @ingroup expr
41 */
42 #ifndef _EXPR_H
43 #define _EXPR_H
44
45 #include "exprbase.h"
46 #include "value.h"
47
48 namespace ledger {
49
50 class expr_t : public expr_base_t<value_t>
51 {
52 class parser_t;
53 typedef expr_base_t<value_t> base_type;
54
55 public:
56 struct token_t;
57 class op_t;
58 typedef intrusive_ptr<op_t> ptr_op_t;
59 typedef intrusive_ptr<const op_t> const_ptr_op_t;
60
61 enum check_expr_kind_t {
62 EXPR_GENERAL,
63 EXPR_ASSERTION,
64 EXPR_CHECK
65 };
66
67 typedef std::pair<expr_t, check_expr_kind_t> check_expr_pair;
68 typedef std::list<check_expr_pair> check_expr_list;
69
70 protected:
71 ptr_op_t ptr;
72
73 public:
74 expr_t();
75 expr_t(const expr_t& other);
76 expr_t(ptr_op_t _ptr, scope_t * _context = NULL);
77
78 expr_t(const string& _str, const parse_flags_t& flags = PARSE_DEFAULT);
79 expr_t(std::istream& in, const parse_flags_t& flags = PARSE_DEFAULT);
80
81 virtual ~expr_t();
82
83 expr_t& operator=(const expr_t& _expr);
84
85 virtual operator bool() const throw();
86
87 ptr_op_t get_op() throw();
88
89 void parse(const string& str, const parse_flags_t& flags = PARSE_DEFAULT) {
90 std::istringstream stream(str);
91 return parse(stream, flags, str);
92 }
93
94 virtual void parse(std::istream& in,
95 const parse_flags_t& flags = PARSE_DEFAULT,
96 const optional<string>& original_string = none);
97 virtual void compile(scope_t& scope);
98 virtual value_t real_calc(scope_t& scope);
99
100 bool is_constant() const;
101 value_t& constant_value();
102 const value_t& constant_value() const;
103 bool is_function() const;
104 func_t& get_function();
105
106 virtual string context_to_str() const;
107 virtual void print(std::ostream& out) const;
108 virtual void dump(std::ostream& out) const;
109 };
110
111 /**
112 * Dealing with expr pointers tucked into value objects.
113 */
is_expr(const value_t & val)114 inline bool is_expr(const value_t& val) {
115 return val.is_any() && val.as_any().type() == typeid(expr_t::ptr_op_t);
116 }
117
118 expr_t::ptr_op_t as_expr(const value_t& val);
119 void set_expr(value_t& val, expr_t::ptr_op_t op);
120 value_t expr_value(expr_t::ptr_op_t op);
121
122 // A merged expression allows one to set an expression term, "foo", and
123 // a base expression, "bar", and then merge in later expressions that
124 // utilize foo. For example:
125 //
126 // foo: bar
127 // merge: foo * 10
128 // merge: foo + 20
129 //
130 // When this expression is finally compiled, the base and merged
131 // elements are written into this:
132 //
133 // __tmp=(foo=bar; foo=foo*10; foo=foo+20);__tmp
134 //
135 // This allows users to select flags like -O, -B or -I at any time, and
136 // also combine flags such as -V and -A.
137
138 class merged_expr_t : public expr_t
139 {
140 public:
141 string term;
142 string base_expr;
143 string merge_operator;
144
145 std::list<string> exprs;
146
147 merged_expr_t(const string& _term, const string& expr,
148 const string& merge_op = ";")
expr_t()149 : expr_t(), term(_term), base_expr(expr), merge_operator(merge_op) {
150 TRACE_CTOR(merged_expr_t, "string, string, string");
151 }
~merged_expr_t()152 virtual ~merged_expr_t() {
153 TRACE_DTOR(merged_expr_t);
154 }
155
set_term(const string & _term)156 void set_term(const string& _term) {
157 term = _term;
158 }
set_base_expr(const string & expr)159 void set_base_expr(const string& expr) {
160 base_expr = expr;
161 }
set_merge_operator(const string & merge_op)162 void set_merge_operator(const string& merge_op) {
163 merge_operator = merge_op;
164 }
165
166 bool check_for_single_identifier(const string& expr);
167
prepend(const string & expr)168 void prepend(const string& expr) {
169 if (! check_for_single_identifier(expr))
170 exprs.push_front(expr);
171 }
append(const string & expr)172 void append(const string& expr) {
173 if (! check_for_single_identifier(expr))
174 exprs.push_back(expr);
175 }
remove(const string & expr)176 void remove(const string& expr) {
177 exprs.remove(expr);
178 }
179
180 virtual void compile(scope_t& scope);
181 };
182
183 class call_scope_t;
184 value_t source_command(call_scope_t& scope);
185
186 } // namespace ledger
187
188 #endif // _EXPR_H
189