1 | /**************************************************************************/ |
2 | /* expression.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #ifndef EXPRESSION_H |
32 | #define EXPRESSION_H |
33 | |
34 | #include "core/object/ref_counted.h" |
35 | |
36 | class Expression : public RefCounted { |
37 | GDCLASS(Expression, RefCounted); |
38 | |
39 | private: |
40 | struct Input { |
41 | Variant::Type type = Variant::NIL; |
42 | String name; |
43 | |
44 | Input() {} |
45 | }; |
46 | |
47 | Vector<Input> inputs; |
48 | Variant::Type output_type = Variant::NIL; |
49 | |
50 | String expression; |
51 | |
52 | bool sequenced = false; |
53 | int str_ofs = 0; |
54 | bool expression_dirty = false; |
55 | |
56 | bool _compile_expression(); |
57 | |
58 | enum TokenType { |
59 | TK_CURLY_BRACKET_OPEN, |
60 | TK_CURLY_BRACKET_CLOSE, |
61 | TK_BRACKET_OPEN, |
62 | TK_BRACKET_CLOSE, |
63 | TK_PARENTHESIS_OPEN, |
64 | TK_PARENTHESIS_CLOSE, |
65 | TK_IDENTIFIER, |
66 | TK_BUILTIN_FUNC, |
67 | TK_SELF, |
68 | TK_CONSTANT, |
69 | TK_BASIC_TYPE, |
70 | TK_COLON, |
71 | TK_COMMA, |
72 | TK_PERIOD, |
73 | TK_OP_IN, |
74 | TK_OP_EQUAL, |
75 | TK_OP_NOT_EQUAL, |
76 | TK_OP_LESS, |
77 | TK_OP_LESS_EQUAL, |
78 | TK_OP_GREATER, |
79 | TK_OP_GREATER_EQUAL, |
80 | TK_OP_AND, |
81 | TK_OP_OR, |
82 | TK_OP_NOT, |
83 | TK_OP_ADD, |
84 | TK_OP_SUB, |
85 | TK_OP_MUL, |
86 | TK_OP_DIV, |
87 | TK_OP_MOD, |
88 | TK_OP_POW, |
89 | TK_OP_SHIFT_LEFT, |
90 | TK_OP_SHIFT_RIGHT, |
91 | TK_OP_BIT_AND, |
92 | TK_OP_BIT_OR, |
93 | TK_OP_BIT_XOR, |
94 | TK_OP_BIT_INVERT, |
95 | TK_INPUT, |
96 | TK_EOF, |
97 | TK_ERROR, |
98 | TK_MAX |
99 | }; |
100 | |
101 | static const char *token_name[TK_MAX]; |
102 | struct Token { |
103 | TokenType type; |
104 | Variant value; |
105 | }; |
106 | |
107 | void _set_error(const String &p_err) { |
108 | if (error_set) { |
109 | return; |
110 | } |
111 | error_str = p_err; |
112 | error_set = true; |
113 | } |
114 | |
115 | Error _get_token(Token &r_token); |
116 | |
117 | String error_str; |
118 | bool error_set = true; |
119 | |
120 | struct ENode { |
121 | enum Type { |
122 | TYPE_INPUT, |
123 | TYPE_CONSTANT, |
124 | TYPE_SELF, |
125 | TYPE_OPERATOR, |
126 | TYPE_INDEX, |
127 | TYPE_NAMED_INDEX, |
128 | TYPE_ARRAY, |
129 | TYPE_DICTIONARY, |
130 | TYPE_CONSTRUCTOR, |
131 | TYPE_BUILTIN_FUNC, |
132 | TYPE_CALL |
133 | }; |
134 | |
135 | ENode *next = nullptr; |
136 | |
137 | Type type = TYPE_INPUT; |
138 | |
139 | ENode() {} |
140 | virtual ~ENode() { |
141 | if (next) { |
142 | memdelete(next); |
143 | } |
144 | } |
145 | }; |
146 | |
147 | struct ExpressionNode { |
148 | bool is_op = false; |
149 | union { |
150 | Variant::Operator op; |
151 | ENode *node = nullptr; |
152 | }; |
153 | }; |
154 | |
155 | ENode *_parse_expression(); |
156 | |
157 | struct InputNode : public ENode { |
158 | int index = 0; |
159 | InputNode() { |
160 | type = TYPE_INPUT; |
161 | } |
162 | }; |
163 | |
164 | struct ConstantNode : public ENode { |
165 | Variant value = Variant::NIL; |
166 | ConstantNode() { |
167 | type = TYPE_CONSTANT; |
168 | } |
169 | }; |
170 | |
171 | struct OperatorNode : public ENode { |
172 | Variant::Operator op = Variant::Operator::OP_ADD; |
173 | |
174 | ENode *nodes[2] = { nullptr, nullptr }; |
175 | |
176 | OperatorNode() { |
177 | type = TYPE_OPERATOR; |
178 | } |
179 | }; |
180 | |
181 | struct SelfNode : public ENode { |
182 | SelfNode() { |
183 | type = TYPE_SELF; |
184 | } |
185 | }; |
186 | |
187 | struct IndexNode : public ENode { |
188 | ENode *base = nullptr; |
189 | ENode *index = nullptr; |
190 | |
191 | IndexNode() { |
192 | type = TYPE_INDEX; |
193 | } |
194 | }; |
195 | |
196 | struct NamedIndexNode : public ENode { |
197 | ENode *base = nullptr; |
198 | StringName name; |
199 | |
200 | NamedIndexNode() { |
201 | type = TYPE_NAMED_INDEX; |
202 | } |
203 | }; |
204 | |
205 | struct ConstructorNode : public ENode { |
206 | Variant::Type data_type = Variant::Type::NIL; |
207 | Vector<ENode *> arguments; |
208 | |
209 | ConstructorNode() { |
210 | type = TYPE_CONSTRUCTOR; |
211 | } |
212 | }; |
213 | |
214 | struct CallNode : public ENode { |
215 | ENode *base = nullptr; |
216 | StringName method; |
217 | Vector<ENode *> arguments; |
218 | |
219 | CallNode() { |
220 | type = TYPE_CALL; |
221 | } |
222 | }; |
223 | |
224 | struct ArrayNode : public ENode { |
225 | Vector<ENode *> array; |
226 | ArrayNode() { |
227 | type = TYPE_ARRAY; |
228 | } |
229 | }; |
230 | |
231 | struct DictionaryNode : public ENode { |
232 | Vector<ENode *> dict; |
233 | DictionaryNode() { |
234 | type = TYPE_DICTIONARY; |
235 | } |
236 | }; |
237 | |
238 | struct BuiltinFuncNode : public ENode { |
239 | StringName func; |
240 | Vector<ENode *> arguments; |
241 | BuiltinFuncNode() { |
242 | type = TYPE_BUILTIN_FUNC; |
243 | } |
244 | }; |
245 | |
246 | template <class T> |
247 | T *alloc_node() { |
248 | T *node = memnew(T); |
249 | node->next = nodes; |
250 | nodes = node; |
251 | return node; |
252 | } |
253 | |
254 | ENode *root = nullptr; |
255 | ENode *nodes = nullptr; |
256 | |
257 | Vector<String> input_names; |
258 | |
259 | bool execution_error = false; |
260 | bool _execute(const Array &p_inputs, Object *p_instance, Expression::ENode *p_node, Variant &r_ret, bool p_const_calls_only, String &r_error_str); |
261 | |
262 | protected: |
263 | static void _bind_methods(); |
264 | |
265 | public: |
266 | Error parse(const String &p_expression, const Vector<String> &p_input_names = Vector<String>()); |
267 | Variant execute(Array p_inputs = Array(), Object *p_base = nullptr, bool p_show_error = true, bool p_const_calls_only = false); |
268 | bool has_execute_failed() const; |
269 | String get_error_text() const; |
270 | |
271 | Expression() {} |
272 | ~Expression(); |
273 | }; |
274 | |
275 | #endif // EXPRESSION_H |
276 | |