Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/math/expression.h
20941 views
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
#pragma once
32
33
#include "core/object/ref_counted.h"
34
35
class Expression : public RefCounted {
36
GDCLASS(Expression, RefCounted);
37
38
private:
39
String expression;
40
41
int str_ofs = 0;
42
bool expression_dirty = false;
43
44
bool _compile_expression();
45
46
enum TokenType {
47
TK_CURLY_BRACKET_OPEN,
48
TK_CURLY_BRACKET_CLOSE,
49
TK_BRACKET_OPEN,
50
TK_BRACKET_CLOSE,
51
TK_PARENTHESIS_OPEN,
52
TK_PARENTHESIS_CLOSE,
53
TK_IDENTIFIER,
54
TK_BUILTIN_FUNC,
55
TK_SELF,
56
TK_CONSTANT,
57
TK_BASIC_TYPE,
58
TK_COLON,
59
TK_COMMA,
60
TK_PERIOD,
61
TK_OP_IN,
62
TK_OP_EQUAL,
63
TK_OP_NOT_EQUAL,
64
TK_OP_LESS,
65
TK_OP_LESS_EQUAL,
66
TK_OP_GREATER,
67
TK_OP_GREATER_EQUAL,
68
TK_OP_AND,
69
TK_OP_OR,
70
TK_OP_NOT,
71
TK_OP_ADD,
72
TK_OP_SUB,
73
TK_OP_MUL,
74
TK_OP_DIV,
75
TK_OP_MOD,
76
TK_OP_POW,
77
TK_OP_SHIFT_LEFT,
78
TK_OP_SHIFT_RIGHT,
79
TK_OP_BIT_AND,
80
TK_OP_BIT_OR,
81
TK_OP_BIT_XOR,
82
TK_OP_BIT_INVERT,
83
TK_INPUT,
84
TK_EOF,
85
TK_ERROR,
86
TK_MAX
87
};
88
89
static const char *token_name[TK_MAX];
90
struct Token {
91
TokenType type;
92
Variant value;
93
};
94
95
void _set_error(const String &p_err) {
96
if (error_set) {
97
return;
98
}
99
error_str = p_err;
100
error_set = true;
101
}
102
103
Error _get_token(Token &r_token);
104
105
String error_str;
106
bool error_set = true;
107
108
struct ENode {
109
enum Type {
110
TYPE_INPUT,
111
TYPE_CONSTANT,
112
TYPE_SELF,
113
TYPE_OPERATOR,
114
TYPE_INDEX,
115
TYPE_NAMED_INDEX,
116
TYPE_ARRAY,
117
TYPE_DICTIONARY,
118
TYPE_CONSTRUCTOR,
119
TYPE_BUILTIN_FUNC,
120
TYPE_CALL
121
};
122
123
ENode *next = nullptr;
124
125
Type type = TYPE_INPUT;
126
127
virtual ~ENode() {
128
if (next) {
129
memdelete(next);
130
}
131
}
132
};
133
134
struct ExpressionNode {
135
bool is_op = false;
136
union {
137
Variant::Operator op;
138
ENode *node = nullptr;
139
};
140
};
141
142
ENode *_parse_expression();
143
144
struct InputNode : public ENode {
145
int index = 0;
146
InputNode() {
147
type = TYPE_INPUT;
148
}
149
};
150
151
struct ConstantNode : public ENode {
152
Variant value = Variant::NIL;
153
ConstantNode() {
154
type = TYPE_CONSTANT;
155
}
156
};
157
158
struct OperatorNode : public ENode {
159
Variant::Operator op = Variant::Operator::OP_ADD;
160
161
ENode *nodes[2] = { nullptr, nullptr };
162
163
OperatorNode() {
164
type = TYPE_OPERATOR;
165
}
166
};
167
168
struct SelfNode : public ENode {
169
SelfNode() {
170
type = TYPE_SELF;
171
}
172
};
173
174
struct IndexNode : public ENode {
175
ENode *base = nullptr;
176
ENode *index = nullptr;
177
178
IndexNode() {
179
type = TYPE_INDEX;
180
}
181
};
182
183
struct NamedIndexNode : public ENode {
184
ENode *base = nullptr;
185
StringName name;
186
187
NamedIndexNode() {
188
type = TYPE_NAMED_INDEX;
189
}
190
};
191
192
struct ConstructorNode : public ENode {
193
Variant::Type data_type = Variant::Type::NIL;
194
Vector<ENode *> arguments;
195
196
ConstructorNode() {
197
type = TYPE_CONSTRUCTOR;
198
}
199
};
200
201
struct CallNode : public ENode {
202
ENode *base = nullptr;
203
StringName method;
204
Vector<ENode *> arguments;
205
206
CallNode() {
207
type = TYPE_CALL;
208
}
209
};
210
211
struct ArrayNode : public ENode {
212
Vector<ENode *> array;
213
ArrayNode() {
214
type = TYPE_ARRAY;
215
}
216
};
217
218
struct DictionaryNode : public ENode {
219
Vector<ENode *> dict;
220
DictionaryNode() {
221
type = TYPE_DICTIONARY;
222
}
223
};
224
225
struct BuiltinFuncNode : public ENode {
226
StringName func;
227
Vector<ENode *> arguments;
228
BuiltinFuncNode() {
229
type = TYPE_BUILTIN_FUNC;
230
}
231
};
232
233
template <typename T>
234
T *alloc_node() {
235
T *node = memnew(T);
236
node->next = nodes;
237
nodes = node;
238
return node;
239
}
240
241
ENode *root = nullptr;
242
ENode *nodes = nullptr;
243
244
Vector<String> input_names;
245
246
bool execution_error = false;
247
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);
248
249
protected:
250
static void _bind_methods();
251
252
public:
253
Error parse(const String &p_expression, const Vector<String> &p_input_names = Vector<String>());
254
Variant execute(const Array &p_inputs = Array(), Object *p_base = nullptr, bool p_show_error = true, bool p_const_calls_only = false);
255
bool has_execute_failed() const;
256
String get_error_text() const;
257
258
~Expression();
259
};
260
261