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
36class Expression : public RefCounted {
37 GDCLASS(Expression, RefCounted);
38
39private:
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
262protected:
263 static void _bind_methods();
264
265public:
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