Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "SPPugExpression.h"
24 :
25 : namespace STAPPLER_VERSIONIZED stappler::pug {
26 :
27 7600 : inline void Lexer_parseBufferString(StringView &r, const Lexer::OutStream &stream) {
28 : #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
29 : static const char escape[256] = {
30 : Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, '\'', 0, 0, 0, 0, 0, 0, 0,'/',
31 : Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
32 : 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
33 : 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34 : Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
35 : };
36 : #undef Z16
37 7600 : char quot = 0;
38 7600 : if (r.is('"')) { r ++; quot = '"'; }
39 7600 : if (r.is('\'')) { r ++; quot = '\''; }
40 :
41 7600 : if (quot) {
42 : do {
43 7650 : auto s = (quot == '"') ? r.readUntil<StringView::Chars<'"', '\\'>>() : r.readUntil<StringView::Chars<'\'', '\\'>>();
44 7650 : stream << s;
45 7650 : if (r.is('\\')) {
46 75 : ++ r;
47 75 : if (r.is('u') && r.size() >= 5) {
48 25 : ++ r;
49 0 : unicode::utf8EncodeCb([&] (char c) {
50 25 : stream << c;
51 25 : }, char16_t(base16::hexToChar(r[0], r[1]) << 8 | base16::hexToChar(r[2], r[3]) ));
52 25 : r += 4;
53 : } else {
54 50 : auto tmp = escape[(uint8_t)r[0]];
55 50 : if (tmp) {
56 50 : stream << tmp;
57 : } else {
58 0 : stream << r[0];
59 : }
60 50 : ++ r;
61 : }
62 : }
63 7650 : } while (!r.empty() && !r.is(quot));
64 7600 : if (r.is(quot)) { ++ r; }
65 : } else {
66 0 : stream << r.readChars<StringView::CharGroup<CharGroupId::Alphanumeric>, StringView::Chars<'_'>>();
67 : }
68 7600 : }
69 :
70 45300 : static uint8_t Lexer_Expression_priority(Expression::Op o) {
71 : static const uint8_t p_arr[] = {
72 : 0, 1, // NoOp, Var
73 : 1, 1, // ++ --
74 : 1, 1, 1, 1, 1, 1, // # . : () [] {}
75 : 2, 2, // ++ --
76 : 2, 2, 2, // - not ~
77 : 3, 3, 3, // * / %
78 : 4, 4, // + -
79 : 5, 5, // << >>
80 : 6, 6, 6, 6, // < <= > >=
81 : 7, 7, // == !=
82 : 8, 9, 10, // & ^ |
83 : 11, 12, // and or
84 : 13, 14, // ?:
85 : 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, // = += -= *= /= %= <<= >>= &= ^= |=
86 : 16, 17, 18 // ?: : , ;
87 : };
88 45300 : return p_arr[toInt(o)];
89 : }
90 :
91 14925 : static bool Lexer_Expression_associativity(Expression::Op o) { // false for Left-to-right, true for Right-to-left
92 : static const bool p_arr[] = {
93 : false, false, // NoOp, Var Left-to-right
94 : false, false, // ++ --
95 : false, false, false, false, false, false, // # . :: () [] {} Left-to-right
96 : true, true, // ++ --
97 : true, true, true, // - not ~ Right-to-left
98 : false, false, false, // * / % Left-to-right
99 : false, false, // + - Left-to-right
100 : false, false, // << >> Left-to-right
101 : false, false, false, false, // < <= > >= Left-to-right
102 : false, false, // == != Left-to-right
103 : false, false, false, // & ^ | Left-to-right
104 : false, false, // and or
105 : true, true, // ?:
106 : true, true, true, true, true, true, true, true, true, true, true, // = Right-to-left
107 : false, false, false // , ; Left-to-right
108 : };
109 14925 : return p_arr[toInt(o)];
110 : }
111 :
112 :
113 25 : Expression::Expression() : op(NoOp) { new (&value) Value(); }
114 30750 : Expression::Expression(Op op) : op (op) { new (&value) Value(); }
115 14925 : Expression::Expression(Op op, Expression *l, Expression *r) : op(op), left(l), right(r) { new (&value) Value(); }
116 25 : Expression::Expression(Op op, Expression *l, Expression *r, const StringView & t) : op(op), left(l), right(r) {
117 25 : isToken = true;
118 25 : value.setString(t);
119 25 : }
120 25 : Expression::Expression(Op op, Expression *l, Expression *r, Value && d) : op(op), left(l), right(r), value(move(d)) { }
121 :
122 75 : Expression::~Expression() { }
123 :
124 10950 : void Expression::set(Value && d) {
125 10950 : isToken = false;
126 10950 : value = std::move(d);
127 10950 : }
128 17775 : void Expression::set(const StringView & t) {
129 17775 : isToken = true;
130 17775 : value.setString(t);
131 17775 : }
132 :
133 75 : bool Expression::empty() const {
134 75 : return value.empty();
135 : }
136 :
137 11900 : static bool Expression_isConst(const Expression &expr, Expression::Op op) {
138 11900 : if (expr.op == Expression::Call) {
139 300 : return false;
140 : }
141 11600 : if (expr.left && expr.right) {
142 3800 : return Expression_isConst(*expr.left, expr.op) && Expression_isConst(*expr.right, Expression::NoOp);
143 7800 : } else if (expr.left) {
144 125 : return Expression_isConst(*expr.left, Expression::NoOp);
145 : } else {
146 7675 : return !expr.isToken || op == Expression::Colon;
147 : }
148 : }
149 :
150 7075 : bool Expression::isConst() const {
151 7075 : return Expression_isConst(*this, NoOp);
152 : }
153 :
154 : static bool Lexer_readExpression(Expression **node, StringView &r, const Expression::Options &opts, bool isRoot);
155 : static bool Lexer_Expression_readOperand(Expression **node, StringView &r, Expression::Op op, const Expression::Options &opts);
156 : static bool Lexer_Expression_readOperandValue(Expression *current, StringView &r, Expression::Op op, const Expression::Options &opts);
157 :
158 28000 : static Expression::Op Lexer_Expression_readOperator(StringView &r, char brace, const Expression::Options &opts) {
159 14800 : auto checkOperator = [&] (Expression::Op op) {
160 14800 : return opts.hasOperator(op) ? op : Expression::NoOp;
161 28000 : };
162 :
163 28000 : if (r.is("+=")) { r += 2; return checkOperator(Expression::SumAssignment); }
164 27825 : else if (r.is("-=")) { r += 2; return checkOperator(Expression::DiffAssignment); }
165 27750 : else if (r.is("*=")) { r += 2; return checkOperator(Expression::MultAssignment); }
166 27675 : else if (r.is("/=")) { r += 2; return checkOperator(Expression::DivAssignment); }
167 27600 : else if (r.is("%=")) { r += 2; return checkOperator(Expression::RemAssignment); }
168 27525 : else if (r.is("<<=")) { r += 3; return checkOperator(Expression::LShiftAssignment); }
169 27450 : else if (r.is(">>=")) { r += 3; return checkOperator(Expression::RShiftAssignment); }
170 27375 : else if (r.is("&=")) { r += 2; return checkOperator(Expression::AndAssignment); }
171 27300 : else if (r.is("^=")) { r += 2; return checkOperator(Expression::XorAssignment); }
172 27225 : else if (r.is("|=")) { r += 2; return checkOperator(Expression::OrAssignment); }
173 27150 : else if (r.is("&&")) { r += 2; return checkOperator(Expression::And); }
174 26975 : else if (r.is("||")) { r += 2; return checkOperator(Expression::Or); }
175 26800 : else if (r.is("++")) { r += 2; return checkOperator(Expression::SuffixIncr); }
176 26675 : else if (r.is("--")) { r += 2; return checkOperator(Expression::SuffixDecr); }
177 26550 : else if (r.is("<<")) { r += 2; return checkOperator(Expression::ShiftLeft); }
178 26475 : else if (r.is(">>")) { r += 2; return checkOperator(Expression::ShiftRight); }
179 26400 : else if (r.is("<=")) { r += 2; return checkOperator(Expression::LtEq); }
180 26175 : else if (r.is(">=")) { r += 2; return checkOperator(Expression::GtEq); }
181 25950 : else if (r.is("==")) { r += 2; return checkOperator(Expression::Eq); }
182 25825 : else if (r.is("!=")) { r += 2; return checkOperator(Expression::NotEq); }
183 25700 : else if (r.is("::")) { r += 2; return checkOperator(Expression::Scope); }
184 25650 : else if (r.is('=')) { ++ r; return checkOperator(Expression::Assignment); }
185 23000 : else if (r.is('#')) { ++ r; return checkOperator(Expression::Sharp); }
186 22975 : else if (r.is('.')) { ++ r; return checkOperator(Expression::Dot); }
187 20300 : else if (r.is('?')) { return checkOperator(Expression::Conditional); }
188 20175 : else if (r.is('(')) { return checkOperator(Expression::Call); }
189 19600 : else if (r.is('[')) { return checkOperator(Expression::Subscript); }
190 19325 : else if (r.is('{')) { return checkOperator(Expression::Construct); }
191 19300 : else if (r.is('*')) { ++ r; return checkOperator(Expression::Mult); }
192 19200 : else if (r.is('/')) { ++ r; return checkOperator(Expression::Div); }
193 19125 : else if (r.is('%')) { ++ r; return checkOperator(Expression::Rem); }
194 19025 : else if (r.is('+')) { ++ r; return checkOperator(Expression::Sum); }
195 16125 : else if (r.is('-')) { ++ r; return checkOperator(Expression::Sub); }
196 16000 : else if (r.is('<')) { ++ r; return checkOperator(Expression::Lt); }
197 15750 : else if (r.is('>')) { ++ r; return checkOperator(Expression::Gt); }
198 15525 : else if (r.is('&')) { ++ r; return checkOperator(Expression::BitAnd); }
199 15450 : else if (r.is('^')) { ++ r; return checkOperator(Expression::BitXor); }
200 15375 : else if (r.is('|')) { ++ r; return checkOperator(Expression::BitOr); }
201 15300 : else if (r.is(':') && (brace || !opts.hasFlag(Expression::StopOnRootColon))) { ++ r; return checkOperator(Expression::Colon); }
202 14650 : else if (r.is(',') && (brace || !opts.hasFlag(Expression::StopOnRootComma))) { ++ r; return checkOperator(Expression::Comma); }
203 13225 : else if (r.is(';') && (brace || !opts.hasFlag(Expression::StopOnRootSequence))) { ++ r; return checkOperator(Expression::Sequence); }
204 :
205 13200 : return Expression::NoOp;
206 : }
207 :
208 1850 : static Expression **Lexer_Expression_pushUnaryOp(Expression *node, Expression::Op op) {
209 1850 : node->op = op;
210 1850 : node->left = new Expression{Expression::Op::NoOp};
211 1850 : return &node->left;
212 : }
213 :
214 14925 : static Expression *Lexer_Expression_insertOp(Expression **node, Expression::Op op) {
215 14925 : Expression **insert = node;
216 14925 : Expression *prev = nullptr;
217 14925 : Expression *current = *node;
218 18900 : while (Lexer_Expression_priority(current->op) > Lexer_Expression_priority(op) && (current->right || current->left) && !current->block) {
219 3975 : prev = current;
220 3975 : if (current->right) {
221 3975 : insert = &prev->right;
222 3975 : current = current->right;
223 : } else {
224 0 : insert = &prev->left;
225 0 : current = current->left;
226 : }
227 : }
228 :
229 14925 : if (Lexer_Expression_associativity(op) && Lexer_Expression_priority(current->op) >= Lexer_Expression_priority(op)) {
230 0 : while (current->right->left && Lexer_Expression_priority(current->right->op) == Lexer_Expression_priority(op)) {
231 0 : current = current->right;
232 : }
233 0 : current->right = new Expression(op, current->right, new Expression{Expression::NoOp});
234 0 : return current->right;
235 : } else {
236 14925 : *insert = new Expression(op, current,
237 14800 : (op != Expression::SuffixIncr && op != Expression::SuffixDecr)
238 29725 : ? new Expression{Expression::NoOp}
239 14925 : : nullptr);
240 14925 : return *insert;
241 : }
242 : }
243 :
244 28850 : static bool Lexer_Expression_readOperandValue(Expression *current, StringView &r, Expression::Op op, const Expression::Options &opts) {
245 28850 : bool ret = false;
246 28850 : if (r.is('\'') || r.is('"')) {
247 7600 : String stream;
248 7600 : Lexer_parseBufferString(r, [&] (StringView str) {
249 7725 : stream.append(str.data(), str.size());
250 7725 : });
251 7600 : current->set(Value(stream));
252 7600 : ret = true;
253 28850 : } else if (r.is<StringView::CharGroup<CharGroupId::Numbers>>()) { // numeric literal
254 2850 : bool isFloat = false;
255 2850 : auto tmp = r;
256 2850 : r.skipChars<StringView::CharGroup<CharGroupId::Numbers>>();
257 2850 : if (r.is('.')) {
258 375 : isFloat = true;
259 375 : ++ r;
260 375 : r.skipChars<StringView::CharGroup<CharGroupId::Numbers>>();
261 : }
262 2850 : if (r.is('E') || r.is('e')) {
263 25 : isFloat = true;
264 25 : ++ r;
265 25 : if (r.is('+') || r.is('-')) {
266 25 : ++ r;
267 : }
268 25 : r.skipChars<StringView::CharGroup<CharGroupId::Numbers>>();
269 : }
270 :
271 2850 : auto value = StringView(tmp.data(), tmp.size() - r.size());
272 2850 : if (isFloat) {
273 375 : current->set(Value(value.readDouble().get()));
274 : } else {
275 2475 : current->set(Value(value.readInteger().get()));
276 : }
277 2850 : ret = true;
278 : } else { // token literal
279 18400 : if (op == Expression::Dot || op == Expression::Colon || op == Expression::Sharp) {
280 2850 : auto tmp = r;
281 2850 : if (op == Expression::Colon && (r.is('+') || r.is('-'))) {
282 0 : ++ r;
283 : }
284 2850 : r.skipChars<StringView::CharGroup<CharGroupId::Alphanumeric>, StringView::Chars<'_'>>();
285 2850 : auto value = StringView(tmp.data(), tmp.size() - r.size());
286 2850 : current->set(String(value.data(), value.size()));
287 2850 : ret = true;
288 2850 : } else {
289 15550 : auto value = r.readChars<StringView::CharGroup<CharGroupId::Alphanumeric>, StringView::Chars<'_'>>();
290 :
291 15550 : if (value.empty() && (op == Expression::Call || op == Expression::Subscript || op == Expression::Construct)) {
292 125 : current->isToken = true;
293 15425 : } else if (value == "true") {
294 225 : current->set(Value(true));
295 15200 : } else if (value == "false") {
296 175 : current->set(Value(false));
297 15025 : } else if (value == "null") {
298 50 : current->set(Value());
299 14975 : } else if (value == "inf") {
300 25 : current->set(Value(std::numeric_limits<double>::infinity()));
301 14950 : } else if (value == "nan") {
302 25 : current->set(Value(nan()));
303 14925 : } else if (!value.empty()) {
304 14925 : current->set(String(value.data(), value.size()));
305 : } else {
306 0 : return false;
307 : }
308 15550 : ret = true;
309 : }
310 : }
311 28850 : return ret;
312 : }
313 :
314 90200 : static bool Lexer_Expression_skipWhitespace(StringView &r, const Expression::Options &opts, bool isFinalizable) {
315 50 : auto tryEmptyString = [] (StringView &r, const StringView &token) -> bool {
316 50 : auto tmp = r;
317 50 : if (tmp.is("\r\n")) { tmp += 2; }
318 50 : else if (tmp.is('\n') || tmp.is('\r')) { ++ tmp; }
319 50 : tmp.skipChars<StringView::Chars<' ', '\t'>>();
320 50 : if (tmp.is('\n') || tmp.is('\r')) {
321 0 : r = tmp;
322 0 : return true;
323 : }
324 50 : return false;
325 : };
326 :
327 90200 : if (opts.hasFlag(Expression::UseNewlineToken)) {
328 750 : while (r.is<StringView::Chars<' ', '\t', '\n', '\r'>>()) {
329 200 : r.skipChars<StringView::Chars<' ', '\t'>>();
330 200 : if (r.is('\n') || r.is('\r')) {
331 50 : if (!tryEmptyString(r, opts.newlineToken)) {
332 50 : if (isFinalizable || !r.is(opts.newlineToken)) {
333 25 : return false;
334 : } else {
335 25 : r += opts.newlineToken.size();
336 25 : r.skipChars<StringView::Chars<' ', '\t'>>();
337 : }
338 : }
339 : }
340 175 : r.skipChars<StringView::Chars<' ', '\t'>>();
341 : }
342 550 : return !r.empty();
343 89625 : } else if (!opts.hasFlag(Expression::StopOnNewLine)) {
344 5475 : if (isFinalizable) {
345 1975 : r.skipChars<StringView::Chars<' ', '\t'>>();
346 1975 : if (r.is('\n') || r.is('\r')) {
347 0 : return false;
348 : }
349 : }
350 5475 : r.skipChars<StringView::CharGroup<CharGroupId::WhiteSpace>>();
351 5475 : return !r.empty();
352 : } else {
353 84150 : r.skipChars<StringView::Chars<' ', '\t'>>();
354 84150 : if (r.is('\n' || r.is('\r'))) {
355 0 : return false;
356 : }
357 84150 : r.skipChars<StringView::Chars<' ', '\t'>>();
358 84150 : return !r.empty();
359 : }
360 : }
361 :
362 29725 : static bool Lexer_Expression_readOperand(Expression **node, StringView &r, Expression::Op op, const Expression::Options &opts) {
363 29725 : if (!Lexer_Expression_skipWhitespace(r, opts, false)) {
364 0 : return false;
365 : }
366 :
367 29725 : if (op != Expression::Dot && op != Expression::Sharp) {
368 27025 : bool finalized = false;
369 : do {
370 28875 : r.skipChars<StringView::CharGroup<CharGroupId::WhiteSpace>>();
371 28875 : if (r.is('!')) {
372 100 : ++ r;
373 100 : node = (Lexer_Expression_pushUnaryOp(*node, Expression::Neg));
374 28775 : } else if (r.is('-')) {
375 425 : ++ r;
376 425 : node = (Lexer_Expression_pushUnaryOp(*node, Expression::Minus));
377 28350 : } else if (r.is('~')) {
378 50 : ++ r;
379 50 : node = (Lexer_Expression_pushUnaryOp(*node, Expression::BitNot));
380 28300 : } else if (r.is("++")) {
381 175 : r += 2;
382 175 : node = (Lexer_Expression_pushUnaryOp(*node, Expression::PrefixIncr));
383 28125 : } else if (r.is("--")) {
384 0 : r += 2;
385 0 : node = (Lexer_Expression_pushUnaryOp(*node, Expression::PrefixDecr));
386 28125 : } else if (r.is('+')) {
387 0 : ++ r;
388 28125 : } else if (r.is("var")) {
389 1100 : auto tmp = r;
390 1100 : tmp += 3;
391 1100 : if (tmp.is<StringView::Chars<' ', '\t'>>()) {
392 1100 : tmp.skipChars<StringView::Chars<' ', '\t'>>();
393 1100 : r = tmp;
394 1100 : node = (Lexer_Expression_pushUnaryOp(*node, Expression::Var));
395 : } else {
396 0 : finalized = true;
397 : }
398 : } else {
399 27025 : finalized = true;
400 : }
401 28875 : } while (!finalized);
402 : }
403 :
404 : // read as expression
405 29725 : if (r.is('(') || r.is('[') || r.is('{')) {
406 875 : if (Lexer_readExpression(node, r, opts, false)) {
407 875 : return true;
408 : }
409 0 : return false;
410 : }
411 :
412 : // read as literal
413 28850 : return Lexer_Expression_readOperandValue(*node, r, op, opts);
414 : }
415 :
416 16100 : static bool Lexer_readExpression(Expression **node, StringView &r, const Expression::Options &opts, bool isRoot) {
417 16100 : Expression::Op targetOp = Expression::NoOp;
418 16100 : Expression::Block block = Expression::Block::Parentesis;
419 16100 : char brace = 0;
420 16100 : if ((r.is('(') || r.is('[') || r.is('{') || r.is('?')) && !isRoot) {
421 1875 : auto tmp = r[0];
422 1875 : switch (tmp) {
423 975 : case '(': brace = ')'; block = Expression::Parentesis; targetOp = Expression::Call; break;
424 125 : case '?': brace = ':'; block = Expression::Parentesis; targetOp = Expression::Conditional; break;
425 475 : case '[': brace = ']'; block = Expression::Composition; targetOp = Expression::Subscript; break;
426 300 : case '{': brace = '}'; block = Expression::Operator; targetOp = Expression::Construct; break;
427 0 : default: break;
428 : }
429 1875 : ++ r;
430 1875 : if (!Lexer_Expression_skipWhitespace(r, opts, false)) {
431 0 : return false;
432 : }
433 :
434 1875 : if (brace == '}' && r.is('}')) {
435 25 : ++ r;
436 25 : (*node)->op = Expression::Construct;
437 25 : (*node)->block = Expression::Operator;
438 25 : return true;
439 : }
440 1850 : if (brace == ']' && r.is(']')) {
441 25 : ++ r;
442 25 : (*node)->op = Expression::Subscript;
443 25 : (*node)->block = Expression::Composition;
444 25 : return true;
445 : }
446 : }
447 :
448 : // read first operand
449 16050 : if (!Lexer_Expression_readOperand(node, r, targetOp, opts)) {
450 0 : return false;
451 : }
452 16050 : if (!Lexer_Expression_skipWhitespace(r, opts, isRoot)) {
453 125 : return isRoot;
454 : }
455 :
456 15925 : Expression *current = *node;
457 : // if there is only first operand - no other ops will be executed
458 29850 : while (!r.empty() && (brace == 0 || !r.is(brace))) {
459 : // read operator
460 28000 : if (!Lexer_Expression_skipWhitespace(r, opts, false)) {
461 0 : return isRoot;
462 : }
463 28000 : auto op = Lexer_Expression_readOperator(r, brace, opts);
464 28000 : if (op == Expression::NoOp) {
465 13200 : return isRoot;
466 : }
467 :
468 14800 : current = Lexer_Expression_insertOp(node, op);
469 14800 : if (op == Expression::Conditional) {
470 125 : if (!Lexer_readExpression(¤t->right, r, opts, false)) {
471 0 : return false;
472 : }
473 125 : current = Lexer_Expression_insertOp(node, Expression::ConditionalSwitch);
474 125 : if (!Lexer_Expression_readOperand(¤t->right, r, current->op, opts)) {
475 0 : return false;
476 : }
477 125 : if (!Lexer_Expression_skipWhitespace(r, opts, isRoot)) {
478 0 : return isRoot;
479 : }
480 14675 : } else if (op == Expression::Call || op == Expression::Subscript || op == Expression::Construct) {
481 875 : if (!Lexer_readExpression(¤t->right, r, opts, false)) {
482 0 : return false;
483 : }
484 875 : if (!Lexer_Expression_skipWhitespace(r, opts, false)) {
485 75 : return isRoot;
486 : }
487 13800 : } else if (op == Expression::SuffixIncr || op == Expression::SuffixDecr) {
488 : // pass thru
489 : } else {
490 13550 : if (!Lexer_Expression_readOperand(¤t->right, r, current->op, opts)) {
491 0 : return false;
492 : }
493 13550 : if (!Lexer_Expression_skipWhitespace(r, opts, isRoot)) {
494 800 : return isRoot;
495 : }
496 : }
497 : }
498 :
499 1850 : (*node)->block = block;
500 1850 : if (brace != 0 && r.is(brace)) {
501 1825 : ++ r;
502 : }
503 1850 : return true;
504 : }
505 :
506 2975 : static void stl_print_expression_op(const Lexer::OutStream &stream, Expression::Op op) {
507 2975 : switch (op) {
508 :
509 0 : case Expression::NoOp: stream << "<noop>"; break;
510 350 : case Expression::Var: stream << "<var>"; break;
511 25 : case Expression::SuffixIncr: stream << "() ++"; break;
512 25 : case Expression::SuffixDecr: stream << "() --"; break;
513 :
514 25 : case Expression::Sharp: stream << "# <sharp>"; break;
515 125 : case Expression::Dot: stream << ". <dot>"; break;
516 50 : case Expression::Scope: stream << ":: <scope>"; break;
517 75 : case Expression::Call: stream << "() <call>"; break;
518 25 : case Expression::Subscript: stream << "[] <subscript>"; break;
519 25 : case Expression::Construct: stream << "{} <construct>"; break;
520 :
521 25 : case Expression::PrefixIncr: stream << "++ ()"; break;
522 0 : case Expression::PrefixDecr: stream << "-- ()"; break;
523 :
524 75 : case Expression::Minus: stream << "- <minus>"; break;
525 25 : case Expression::Neg: stream << "! <neg>"; break;
526 25 : case Expression::BitNot: stream << "~ <bit-not>"; break;
527 :
528 25 : case Expression::Mult: stream << "* <mult>"; break;
529 25 : case Expression::Div: stream << "/ <div>"; break;
530 50 : case Expression::Rem: stream << "% <rem>"; break;
531 :
532 225 : case Expression::Sum: stream << "+ <sum>"; break;
533 25 : case Expression::Sub: stream << "- <sub>"; break;
534 :
535 25 : case Expression::ShiftLeft: stream << "<< <shift-left>"; break;
536 25 : case Expression::ShiftRight: stream << ">> <shift-right>"; break;
537 :
538 50 : case Expression::Lt: stream << "< <lt>"; break;
539 25 : case Expression::LtEq: stream << "<= <lt-eq>"; break;
540 25 : case Expression::Gt: stream << "> <gt>"; break;
541 25 : case Expression::GtEq: stream << ">= <gt-eq>"; break;
542 :
543 25 : case Expression::Eq: stream << "== <eq>"; break;
544 25 : case Expression::NotEq: stream << "!= <eq>"; break;
545 :
546 25 : case Expression::BitAnd: stream << "& <bit-and>"; break;
547 25 : case Expression::BitXor: stream << "^ <bit-xor>"; break;
548 25 : case Expression::BitOr: stream << "| <bit-or>"; break;
549 :
550 25 : case Expression::And: stream << "&& <and>"; break;
551 25 : case Expression::Or: stream << "|| <or>"; break;
552 :
553 50 : case Expression::Conditional: stream << "? <conditional>"; break;
554 50 : case Expression::ConditionalSwitch: stream << "?: <conditional-switch>"; break;
555 :
556 475 : case Expression::Assignment: stream << "= <assignment>"; break;
557 25 : case Expression::SumAssignment: stream << "+= <assignment>"; break;
558 25 : case Expression::DiffAssignment: stream << "-= <assignment>"; break;
559 25 : case Expression::MultAssignment: stream << "*= <assignment>"; break;
560 25 : case Expression::DivAssignment: stream << "/= <assignment>"; break;
561 25 : case Expression::RemAssignment: stream << "%= <assignment>"; break;
562 25 : case Expression::LShiftAssignment: stream << "<<= <assignment>"; break;
563 25 : case Expression::RShiftAssignment: stream << ">>= <assignment>"; break;
564 25 : case Expression::AndAssignment: stream << "&= <assignment>"; break;
565 25 : case Expression::XorAssignment: stream << "^= <assignment>"; break;
566 25 : case Expression::OrAssignment: stream << "|= <assignment>"; break;
567 :
568 200 : case Expression::Colon: stream << ": <colon>"; break;
569 350 : case Expression::Comma: stream << ", <comma>"; break;
570 25 : case Expression::Sequence: stream << "; <sequence>"; break;
571 :
572 : }
573 2975 : }
574 :
575 2425 : static void stl_print_expression_open_block(const Lexer::OutStream &stream, Expression::Block b, uint16_t depth) {
576 2425 : switch (b) {
577 2200 : case Expression::None:
578 2200 : break;
579 75 : case Expression::Parentesis:
580 375 : for (size_t i = 0; i < depth; ++ i) { stream << " "; }
581 75 : stream << "(\n";
582 75 : break;
583 50 : case Expression::Composition:
584 350 : for (size_t i = 0; i < depth; ++ i) { stream << " "; }
585 50 : stream << "[\n";
586 50 : break;
587 100 : case Expression::Operator:
588 650 : for (size_t i = 0; i < depth; ++ i) { stream << " "; }
589 100 : stream << "{\n";
590 100 : break;
591 : }
592 2425 : }
593 :
594 2425 : static void stl_print_expression_close_block(const Lexer::OutStream &stream, Expression::Block b, uint16_t depth) {
595 2425 : switch (b) {
596 2200 : case Expression::None:
597 2200 : break;
598 75 : case Expression::Parentesis:
599 375 : for (size_t i = 0; i < depth; ++ i) { stream << " "; }
600 75 : stream << ")\n";
601 75 : break;
602 50 : case Expression::Composition:
603 350 : for (size_t i = 0; i < depth; ++ i) { stream << " "; }
604 50 : stream << "]\n";
605 50 : break;
606 100 : case Expression::Operator:
607 650 : for (size_t i = 0; i < depth; ++ i) { stream << " "; }
608 100 : stream << "}\n";
609 100 : break;
610 : }
611 2425 : }
612 :
613 8625 : static void stl_print_expression(const Lexer::OutStream &stream, Expression * t, uint16_t depth) {
614 8625 : if (!t->left && !t->right) {
615 32300 : for (size_t i = 0; i < depth; ++ i) { stream << " "; }
616 5650 : if (t->isToken) {
617 3525 : stream << "(token) " << data::toString<stappler::memory::PoolInterface>(t->value, false) << "\n";
618 2125 : } else if (t->op == Expression::NoOp) {
619 2075 : switch (t->value.getType()) {
620 25 : case Value::Type::EMPTY: break;
621 0 : case Value::Type::NONE: break;
622 200 : case Value::Type::BOOLEAN: stream << "(bool) "; break;
623 300 : case Value::Type::INTEGER: stream << "(int) "; break;
624 0 : case Value::Type::DOUBLE: stream << "(float) "; break;
625 1550 : case Value::Type::CHARSTRING: stream << "(string) "; break;
626 0 : case Value::Type::BYTESTRING: stream << "(bytes) "; break;
627 0 : case Value::Type::ARRAY: stream << "(array) "; break;
628 0 : case Value::Type::DICTIONARY: stream << "(dict) "; break;
629 : }
630 2075 : stream << data::toString<stappler::memory::PoolInterface>(t->value, false) << "\n";
631 : } else {
632 50 : switch (t->op) {
633 25 : case Expression::Subscript: stream << "[] <subscript>\n"; break;
634 25 : case Expression::Construct: stream << "{} <construct>\n"; break;
635 0 : default: break;
636 : }
637 : }
638 8625 : } else if (t->left && t->right) {
639 2425 : stl_print_expression_open_block(stream, t->block, depth);
640 2425 : stl_print_expression(stream, t->left, depth + 1);
641 :
642 11225 : for (size_t i = 0; i < depth; ++ i) { stream << " "; }
643 2425 : stream << "-> ";
644 2425 : stl_print_expression_op(stream, t->op);
645 2425 : stream << "\n";
646 :
647 2425 : stl_print_expression(stream, t->right, depth + 1);
648 2425 : stl_print_expression_close_block(stream, t->block, depth);
649 2975 : } else if (t->left) {
650 2850 : for (size_t i = 0; i < depth; ++ i) { stream << " "; }
651 :
652 550 : switch (t->block) {
653 525 : case Expression::None: break;
654 25 : case Expression::Parentesis: stream << "( "; break;
655 0 : case Expression::Composition: stream << "{ "; break;
656 0 : case Expression::Operator: stream << "[ "; break;
657 : }
658 :
659 550 : stl_print_expression_op(stream, t->op);
660 :
661 550 : switch (t->block) {
662 525 : case Expression::None: break;
663 25 : case Expression::Parentesis: stream << " )"; break;
664 0 : case Expression::Composition: stream << " }"; break;
665 0 : case Expression::Operator: stream << " ]"; break;
666 : }
667 :
668 550 : stream << "\n";
669 :
670 550 : stl_print_expression(stream, t->left, depth + 1);
671 : }
672 8625 : }
673 :
674 3225 : void Expression::describe(const OutStream &stream, size_t depth) {
675 3225 : stl_print_expression(stream, this, depth);
676 3225 : }
677 :
678 :
679 13200 : Expression::Options Expression::Options::getDefaultInline() {
680 13200 : return Options().enableAllOperators().setFlags({StopOnNewLine, StopOnRootColon, StopOnRootComma, StopOnRootSequence});
681 : }
682 1000 : Expression::Options Expression::Options::getDefaultScript() {
683 1000 : return Options().enableAllOperators().setFlags({StopOnRootColon, StopOnRootComma, StopOnRootSequence});
684 : }
685 25 : Expression::Options Expression::Options::getWithNewlineToken(const StringView &token) {
686 25 : return Options().enableAllOperators().setFlags({StopOnRootColon, StopOnRootComma, StopOnRootSequence}).useNewlineToken(token);
687 : }
688 :
689 14250 : Expression::Options &Expression::Options::enableAllOperators() {
690 14250 : operators.set();
691 14250 : return *this;
692 : }
693 :
694 25 : Expression::Options &Expression::Options::disableAllOperators() {
695 25 : operators.reset();
696 25 : return *this;
697 : }
698 :
699 25 : Expression::Options &Expression::Options::enableOperators(std::initializer_list<Op> && il) {
700 50 : for (auto &it : il) { operators.set(toInt(it)); }
701 25 : return *this;
702 : }
703 25 : Expression::Options &Expression::Options::disableOperators(std::initializer_list<Op> && il) {
704 50 : for (auto &it : il) { operators.reset(toInt(it)); }
705 25 : return *this;
706 : }
707 :
708 25 : Expression::Options &Expression::Options::useNewlineToken(const StringView &str) {
709 25 : newlineToken = str;
710 25 : setFlags({UseNewlineToken});
711 25 : return *this;
712 : }
713 :
714 14250 : Expression::Options &Expression::Options::setFlags(std::initializer_list<Flags> && il) {
715 70150 : for (auto &it : il) { flags.set(toInt(it)); }
716 14250 : return *this;
717 : }
718 1000 : Expression::Options &Expression::Options::clearFlags(std::initializer_list<Flags> && il) {
719 2000 : for (auto &it : il) { flags.reset(toInt(it)); }
720 1000 : return *this;
721 : }
722 :
723 181800 : bool Expression::Options::hasFlag(Flags f) const {
724 181800 : return flags.test(toInt(f));
725 : }
726 14800 : bool Expression::Options::hasOperator(Op op) const {
727 14800 : return operators.test(toInt(op));
728 : }
729 :
730 14225 : Expression * Expression::parse(StringView &r, const Options &opts) {
731 14225 : auto root = new Expression{Op::NoOp};
732 14225 : if (!Lexer_readExpression(&root, r, opts, true)) {
733 0 : return nullptr;
734 : }
735 14225 : return root;
736 : }
737 :
738 : }
|