QGIS API Documentation 4.3.0-Master (bd2f5e21fd1)
Loading...
Searching...
No Matches
qgsesriarcadescript.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsesriarcadescript.cpp
3 -----------------------
4 begin : October 2026
5 copyright : (C) 2026 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsesriarcadescript.h"
17
18#include <cmath>
19
20#include "qgis.h"
21#include "qgsvariantutils.h"
22
23#include <QRegularExpression>
24#include <QString>
25
26using namespace Qt::StringLiterals;
27
28// external parser entry point
29extern QgsEsriArcadeBlockStatement *parseArcadeScript( const QString &scriptText, QString &parserErrorMessage );
30
31const char *QgsEsriArcadeBinaryOperatorExpression::BINARY_OPERATOR_TEXT[] = { "+", "-", "*", "/", "%", "==", "!=", "<", ">", "<=", ">=", "&&", "||", "&", "|", "^", "<<", ">>", ">>>" };
32
33const char *QgsEsriArcadeUnaryOperatorExpression::UNARY_OPERATOR_TEXT[] = { "!", "-", "+", "~", "++", "--", "++", "--" };
34
35const char *QgsEsriArcadeAssignmentStatement::ASSIGNMENT_OPERATOR_TEXT[] = { "=", "+=", "-=", "*=", "/=" };
36
37//
38// QgsEsriArcadeBlockStatement
39//
40
42 : mStatements( statements )
43{}
44
46{
47 qDeleteAll( mStatements );
48}
49
51{
52 mStatements.append( statement );
53}
54
56{
57 QStringList parts;
58 parts.reserve( mStatements.size() );
59 for ( QgsEsriArcadeStatement *statement : std::as_const( mStatements ) )
60 {
61 parts << statement->dump();
62 }
63 return parts.join( '\n' );
64}
65
67{
68 QList<QgsEsriArcadeStatement *> clonedList;
69 clonedList.reserve( mStatements.size() );
70 for ( QgsEsriArcadeStatement *statement : std::as_const( mStatements ) )
71 {
72 clonedList.append( dynamic_cast<QgsEsriArcadeStatement *>( statement->clone() ) );
73 }
74 return new QgsEsriArcadeBlockStatement( clonedList );
75}
76
78{
79 visitor.visit( *this );
80}
81
82//
83// QgsEsriArcadeVariableDeclarationStatement
84//
85
90
92{
93 if ( mInitializer )
94 return u"var %1 = %2;"_s.arg( mVariableName, mInitializer->dump() );
95 else
96 return u"var %1;"_s.arg( mVariableName );
97}
98
100{
101 return new QgsEsriArcadeVariableDeclarationStatement( mVariableName, mInitializer ? dynamic_cast<QgsEsriArcadeExpression *>( mInitializer->clone() ) : nullptr );
102}
103
105{
106 visitor.visit( *this );
107}
108
109//
110// QgsEsriArcadeAssignmentStatement
111//
112
118
120{
121 return u"%1 %2 %3;"_s.arg( mTarget ? mTarget->dump() : QString(), ASSIGNMENT_OPERATOR_TEXT[static_cast<int>( mAssignmentOperator )], mValue ? mValue->dump() : QString() );
122}
123
125{
126 QgsEsriArcadeExpression *clonedTarget = mTarget ? dynamic_cast<QgsEsriArcadeExpression *>( mTarget->clone() ) : nullptr;
127 QgsEsriArcadeExpression *clonedValue = mValue ? dynamic_cast<QgsEsriArcadeExpression *>( mValue->clone() ) : nullptr;
128 return new QgsEsriArcadeAssignmentStatement( mAssignmentOperator, clonedTarget, clonedValue );
129}
130
132{
133 visitor.visit( *this );
134}
135
136//
137// QgsEsriArcadeReturnStatement
138//
139
143
145{
146 if ( mExpression )
147 return u"return %1;"_s.arg( mExpression->dump() );
148 else
149 return u"return;"_s;
150}
151
153{
154 return new QgsEsriArcadeReturnStatement( mExpression ? dynamic_cast<QgsEsriArcadeExpression *>( mExpression->clone() ) : nullptr );
155}
156
158{
159 visitor.visit( *this );
160}
161
162//
163// QgsEsriArcadeFunctionDeclarationStatement
164//
165
167 : mFunctionName( functionName )
168 , mParameters( parameters )
169 , mBody( body )
170{}
171
173{
174 QString body;
175 if ( mBody )
176 body = mBody->dump();
177
178 return u"function %1(%2) {\n%3\n}"_s.arg( mFunctionName, mParameters.join( ", "_L1 ), body );
179}
180
182{
183 return new QgsEsriArcadeFunctionDeclarationStatement( mFunctionName, mParameters, mBody ? dynamic_cast<QgsEsriArcadeBlockStatement *>( mBody->clone() ) : nullptr );
184}
185
187{
188 visitor.visit( *this );
189}
190
191//
192// QgsEsriArcadeExpressionStatement
193//
194
198
200{
201 if ( mExpression )
202 return u"%1;"_s.arg( mExpression->dump() );
203 else
204 return u";"_s;
205}
206
208{
209 return new QgsEsriArcadeExpressionStatement( mExpression ? dynamic_cast<QgsEsriArcadeExpression *>( mExpression->clone() ) : nullptr );
210}
211
213{
214 visitor.visit( *this );
215}
216
217//
218// QgsEsriArcadeLiteralExpression
219//
220
224
226{
227 if ( QgsVariantUtils::isNull( mValue ) )
228 return u"null"_s;
229
230 switch ( mValue.userType() )
231 {
232 case QMetaType::Type::Int:
233 return QString::number( mValue.toInt() );
234 case QMetaType::Type::LongLong:
235 return QString::number( mValue.toLongLong() );
236 case QMetaType::Type::Double:
237 {
238 const double value = mValue.toDouble();
239 if ( std::isnan( value ) )
240 return u"NaN"_s;
241 if ( std::isinf( value ) )
242 return value < 0 ? u"-Infinity"_s : u"Infinity"_s;
243 return qgsDoubleToString( value );
244 }
245 case QMetaType::Type::QString:
246 return mValue.toString();
247 case QMetaType::Type::Bool:
248 return mValue.toBool() ? u"true"_s : u"false"_s;
249 default:
250 return mValue.toString();
251 }
252}
253
255{
256 if ( QgsVariantUtils::isNull( mValue ) )
257 return u"null"_s;
258
259 if ( mValue.userType() == QMetaType::Type::QString )
260 return QgsEsriArcadeScript::quotedString( mValue.toString() );
261
262 return valueAsString();
263}
264
269
271{
272 visitor.visit( *this );
273}
274
275//
276// QgsEsriArcadeVariableReferenceExpression
277//
278
282
284{
285 return mName;
286}
287
292
294{
295 visitor.visit( *this );
296}
297
298//
299// QgsEsriArcadeProfileVariableReferenceExpression
300//
301
305
307{
308 return mName;
309}
310
315
317{
318 visitor.visit( *this );
319}
320
321//
322// QgsEsriArcadeMemberAccessExpression
323//
324
330
332{
333 return u"%1%2%3"_s.arg( mContainerExpression ? mContainerExpression->dump() : QString(), mIsSafeAccess ? "?."_L1 : "."_L1, mMemberName );
334}
335
337{
338 QgsEsriArcadeExpression *clonedContainer = mContainerExpression ? dynamic_cast<QgsEsriArcadeExpression *>( mContainerExpression->clone() ) : nullptr;
339 return new QgsEsriArcadeMemberAccessExpression( clonedContainer, mMemberName, mIsSafeAccess );
340}
341
343{
344 visitor.visit( *this );
345}
346
347//
348// QgsEsriArcadeBinaryOperatorExpression
349//
350
356
358{
359 return BINARY_OPERATOR_TEXT[static_cast<int>( mBinaryOperator )];
360}
361
363{
364 switch ( mBinaryOperator )
365 {
367 return 1;
369 return 2;
371 return 3;
373 return 4;
375 return 5;
378 return 6;
383 return 7;
387 return 8;
390 return 9;
394 return 10;
395 }
396 return -1;
397}
398
400{
401 return true;
402}
403
405{
406 QgsEsriArcadeBinaryOperatorExpression *leftBinary = dynamic_cast<QgsEsriArcadeBinaryOperatorExpression *>( mLeftOperand.get() );
407 QgsEsriArcadeBinaryOperatorExpression *rightBinary = dynamic_cast<QgsEsriArcadeBinaryOperatorExpression *>( mRightOperand.get() );
408
409 const QString leftDump = leftBinary && ( leftBinary->precedence() < precedence() ) ? u"(%1)"_s.arg( mLeftOperand->dump() ) : mLeftOperand->dump();
410
411 const QString rightDump = rightBinary && ( rightBinary->precedence() <= precedence() ) ? u"(%1)"_s.arg( mRightOperand->dump() ) : mRightOperand->dump();
412
413 return u"%1 %2 %3"_s.arg( leftDump, text(), rightDump );
414}
415
417{
418 QgsEsriArcadeExpression *leftClone = mLeftOperand ? dynamic_cast<QgsEsriArcadeExpression *>( mLeftOperand->clone() ) : nullptr;
419 QgsEsriArcadeExpression *rightClone = mRightOperand ? dynamic_cast<QgsEsriArcadeExpression *>( mRightOperand->clone() ) : nullptr;
420 return new QgsEsriArcadeBinaryOperatorExpression( mBinaryOperator, leftClone, rightClone );
421}
422
424{
425 visitor.visit( *this );
426}
427
428//
429// QgsEsriArcadeUnaryOperatorExpression
430//
431
436
438{
439 return UNARY_OPERATOR_TEXT[static_cast<int>( mUnaryOperator )];
440}
441
443{
444 if ( mUnaryOperator == UnaryOperator::PostIncrement || mUnaryOperator == UnaryOperator::PostDecrement )
445 return u"%1%2"_s.arg( mOperand ? mOperand->dump() : QString(), text() );
446 else
447 return u"%1%2"_s.arg( text(), mOperand ? mOperand->dump() : QString() );
448}
449
451{
452 return new QgsEsriArcadeUnaryOperatorExpression( mUnaryOperator, mOperand ? dynamic_cast<QgsEsriArcadeExpression *>( mOperand->clone() ) : nullptr );
453}
454
456{
457 visitor.visit( *this );
458}
459
460//
461// QgsEsriArcadeFunctionCallExpression
462//
463
465 : mFunctionName( functionName )
466 , mArguments( arguments )
467{}
468
473
475{
476 QStringList argumentStrings;
477 argumentStrings.reserve( mArguments.size() );
478 for ( QgsEsriArcadeExpression *argument : std::as_const( mArguments ) )
479 {
480 argumentStrings.append( argument->dump() );
481 }
482 return u"%1(%2)"_s.arg( mFunctionName, argumentStrings.join( ", "_L1 ) );
483}
484
486{
487 QList<QgsEsriArcadeExpression *> clonedArguments;
488 clonedArguments.reserve( mArguments.size() );
489 for ( QgsEsriArcadeExpression *argument : std::as_const( mArguments ) )
490 {
491 clonedArguments.append( dynamic_cast<QgsEsriArcadeExpression *>( argument->clone() ) );
492 }
493 return new QgsEsriArcadeFunctionCallExpression( mFunctionName, clonedArguments );
494}
495
497{
498 visitor.visit( *this );
499}
500
501//
502// QgsEsriArcadeIndexExpression
503//
504
509
511{
512 return u"%1[%2]"_s.arg( mContainerExpression ? mContainerExpression->dump() : QString(), mIndexExpression ? mIndexExpression->dump() : QString() );
513}
514
516{
517 QgsEsriArcadeExpression *clonedContainer = mContainerExpression ? dynamic_cast<QgsEsriArcadeExpression *>( mContainerExpression->clone() ) : nullptr;
518 QgsEsriArcadeExpression *clonedIndex = mIndexExpression ? dynamic_cast<QgsEsriArcadeExpression *>( mIndexExpression->clone() ) : nullptr;
519 return new QgsEsriArcadeIndexExpression( clonedContainer, clonedIndex );
520}
521
523{
524 visitor.visit( *this );
525}
526
527//
528// QgsEsriArcadeArrayLiteralExpression
529//
530
532 : mElements( elements )
533{}
534
539
541{
542 QStringList elementStrings;
543 elementStrings.reserve( mElements.size() );
544 for ( QgsEsriArcadeExpression *element : std::as_const( mElements ) )
545 {
546 elementStrings.append( element->dump() );
547 }
548 return u"[%1]"_s.arg( elementStrings.join( ", "_L1 ) );
549}
550
552{
553 QList<QgsEsriArcadeExpression *> clonedElements;
554 clonedElements.reserve( mElements.size() );
555 for ( QgsEsriArcadeExpression *element : std::as_const( mElements ) )
556 {
557 clonedElements.append( dynamic_cast<QgsEsriArcadeExpression *>( element->clone() ) );
558 }
559 return new QgsEsriArcadeArrayLiteralExpression( clonedElements );
560}
561
563{
564 visitor.visit( *this );
565}
566
567//
568// QgsEsriArcadeDictionaryElement
569//
570
572 : mKey( key )
573 , mValue( value )
574 , mIsAutoKey( isAutoKey )
575{}
576
578
580{
581 if ( mIsAutoKey )
582 return mKey;
583
584 return u"%1: %2"_s.arg( QgsEsriArcadeScript::quotedString( mKey ), mValue ? mValue->dump() : QString() );
585}
586
588{
589 QgsEsriArcadeExpression *clonedValue = mValue ? dynamic_cast<QgsEsriArcadeExpression *>( mValue->clone() ) : nullptr;
590 return new QgsEsriArcadeDictionaryElement( mKey, clonedValue, mIsAutoKey );
591}
592
593//
594// QgsEsriArcadeDictionaryLiteralExpression
595//
596
598 : mElements( elements )
599{}
600
605
607{
608 if ( mElements.isEmpty() )
609 return u"{}"_s;
610
611 QStringList elementStrings;
612 elementStrings.reserve( mElements.size() );
613 for ( QgsEsriArcadeDictionaryElement *element : std::as_const( mElements ) )
614 {
615 elementStrings.append( element->dump() );
616 }
617 return u"{ %1 }"_s.arg( elementStrings.join( ", "_L1 ) );
618}
619
621{
622 QList<QgsEsriArcadeDictionaryElement *> clonedElements;
623 clonedElements.reserve( mElements.size() );
624 for ( QgsEsriArcadeDictionaryElement *element : std::as_const( mElements ) )
625 {
626 clonedElements.append( element->clone() );
627 }
628 return new QgsEsriArcadeDictionaryLiteralExpression( clonedElements );
629}
630
632{
633 visitor.visit( *this );
634}
635
636
637//
638// QgsEsriArcadeIfStatement
639//
640
646
648{
649 QString result = u"if (%1) {\n%2}"_s.arg( mCondition ? mCondition->dump() : QString(), mTrueBlock ? mTrueBlock->dump() : QString() );
650 if ( mFalseBlock )
651 {
652 if ( mFalseBlock->nodeType() == NodeType::IfStatement )
653 result += u" else %1"_s.arg( mFalseBlock->dump() );
654 else
655 result += u" else {\n%1}"_s.arg( mFalseBlock->dump() );
656 }
657 return result;
658}
659
661{
662 QgsEsriArcadeExpression *clonedCondition = mCondition ? dynamic_cast<QgsEsriArcadeExpression *>( mCondition->clone() ) : nullptr;
663 QgsEsriArcadeBlockStatement *clonedTrueBlock = mTrueBlock ? dynamic_cast<QgsEsriArcadeBlockStatement *>( mTrueBlock->clone() ) : nullptr;
664 QgsEsriArcadeBlockStatement *clonedFalseBlock = mFalseBlock ? dynamic_cast<QgsEsriArcadeBlockStatement *>( mFalseBlock->clone() ) : nullptr;
665 return new QgsEsriArcadeIfStatement( clonedCondition, clonedTrueBlock, clonedFalseBlock );
666}
667
669{
670 visitor.visit( *this );
671}
672
673//
674// QgsEsriArcadeForStatement
675//
676
683
685{
686 QString initDump;
687 if ( mInitialization )
688 {
689 initDump = mInitialization->dump().trimmed();
690 if ( initDump.endsWith( ';'_L1 ) )
691 initDump.chop( 1 );
692 }
693
694 return u"for (%1; %2; %3) {\n%4}"_s.arg( initDump, mCondition ? mCondition->dump() : QString(), mStep ? mStep->dump() : QString(), mBody ? mBody->dump() : QString() );
695}
696
698{
699 QgsEsriArcadeStatement *clonedInit = mInitialization ? dynamic_cast<QgsEsriArcadeStatement *>( mInitialization->clone() ) : nullptr;
700 QgsEsriArcadeExpression *clonedCondition = mCondition ? dynamic_cast<QgsEsriArcadeExpression *>( mCondition->clone() ) : nullptr;
701 QgsEsriArcadeNode *clonedStep = mStep ? mStep->clone() : nullptr;
702 QgsEsriArcadeBlockStatement *clonedBody = mBody ? dynamic_cast<QgsEsriArcadeBlockStatement *>( mBody->clone() ) : nullptr;
703 return new QgsEsriArcadeForStatement( clonedInit, clonedCondition, clonedStep, clonedBody );
704}
705
707{
708 visitor.visit( *this );
709}
710
711//
712// QgsEsriArcadeForInStatement
713//
714
717)
718 : mIterationType( iterationType )
719 , mVariableName( variableName )
720 , mIsVariableDeclaration( isVariableDeclaration )
721 , mCollection( collection )
722 , mBody( body )
723{}
724
726{
727 const QString keyword = mIterationType == IterationType::ForIn ? u"in"_s : u"of"_s;
728 return u"for (%1%2 %3 %4) {\n%5}"_s.arg( mIsVariableDeclaration ? "var "_L1 : ""_L1, mVariableName, keyword, mCollection ? mCollection->dump() : QString(), mBody ? mBody->dump() : QString() );
729}
730
732{
733 QgsEsriArcadeExpression *clonedCollection = mCollection ? dynamic_cast<QgsEsriArcadeExpression *>( mCollection->clone() ) : nullptr;
734 QgsEsriArcadeBlockStatement *clonedBody = mBody ? dynamic_cast<QgsEsriArcadeBlockStatement *>( mBody->clone() ) : nullptr;
735 return new QgsEsriArcadeForInStatement( mIterationType, mVariableName, mIsVariableDeclaration, clonedCollection, clonedBody );
736}
737
739{
740 visitor.visit( *this );
741}
742
743//
744// QgsEsriArcadeWhileStatement
745//
746
751
753{
754 return u"while (%1) {\n%2}"_s.arg( mCondition ? mCondition->dump() : QString(), mBody ? mBody->dump() : QString() );
755}
756
758{
759 QgsEsriArcadeExpression *clonedCondition = mCondition ? dynamic_cast<QgsEsriArcadeExpression *>( mCondition->clone() ) : nullptr;
760 QgsEsriArcadeBlockStatement *clonedBody = mBody ? dynamic_cast<QgsEsriArcadeBlockStatement *>( mBody->clone() ) : nullptr;
761 return new QgsEsriArcadeWhileStatement( clonedCondition, clonedBody );
762}
763
765{
766 visitor.visit( *this );
767}
768
769//
770// QgsEsriArcadeBreakStatement
771//
772
774{
775 return u"break;"_s;
776}
777
782
784{
785 visitor.visit( *this );
786}
787
788//
789// QgsEsriArcadeContinueStatement
790//
791
793{
794 return u"continue;"_s;
795}
796
801
803{
804 visitor.visit( *this );
805}
806
807
808//
809// QgsEsriArcadeRecursiveVisitor
810//
811
813{
814 const QList<QgsEsriArcadeStatement *> statements = node.statements();
815 for ( QgsEsriArcadeStatement *statement : statements )
816 {
817 statement->accept( *this );
818 }
819}
820
822{
823 if ( node.initializer() )
824 node.initializer()->accept( *this );
825}
826
828{
829 if ( node.target() )
830 node.target()->accept( *this );
831 if ( node.value() )
832 node.value()->accept( *this );
833}
834
836{
837 if ( node.expression() )
838 node.expression()->accept( *this );
839}
840
842{
843 if ( node.body() )
844 node.body()->accept( *this );
845}
846
848{
849 if ( node.expression() )
850 node.expression()->accept( *this );
851}
852
855
858
861
867
869{
870 if ( node.leftOperand() )
871 node.leftOperand()->accept( *this );
872 if ( node.rightOperand() )
873 node.rightOperand()->accept( *this );
874}
875
877{
878 if ( node.operand() )
879 node.operand()->accept( *this );
880}
881
883{
884 const QList<QgsEsriArcadeExpression *> arguments = node.arguments();
885 for ( QgsEsriArcadeExpression *argument : arguments )
886 {
887 argument->accept( *this );
888 }
889}
890
892{
893 if ( node.containerExpression() )
894 node.containerExpression()->accept( *this );
895 if ( node.indexExpression() )
896 node.indexExpression()->accept( *this );
897}
898
900{
901 const QList<QgsEsriArcadeExpression *> elements = node.elements();
902 for ( QgsEsriArcadeExpression *element : elements )
903 {
904 element->accept( *this );
905 }
906}
907
909{
910 const QList<QgsEsriArcadeDictionaryElement *> elements = node.elements();
911 for ( QgsEsriArcadeDictionaryElement *element : elements )
912 {
913 if ( element->value() )
914 element->value()->accept( *this );
915 }
916}
917
919{
920 if ( node.condition() )
921 node.condition()->accept( *this );
922 if ( node.trueBlock() )
923 node.trueBlock()->accept( *this );
924 if ( node.falseBlock() )
925 node.falseBlock()->accept( *this );
926}
927
929{
930 if ( node.initialization() )
931 node.initialization()->accept( *this );
932 if ( node.condition() )
933 node.condition()->accept( *this );
934 if ( node.step() )
935 node.step()->accept( *this );
936 if ( node.body() )
937 node.body()->accept( *this );
938}
939
941{
942 if ( node.collection() )
943 node.collection()->accept( *this );
944 if ( node.body() )
945 node.body()->accept( *this );
946}
947
949{
950 if ( node.condition() )
951 node.condition()->accept( *this );
952 if ( node.body() )
953 node.body()->accept( *this );
954}
955
958
961
962//
963// QgsEsriArcadeScript
964//
965
967 : mScript( scriptText )
968{
969 if ( !scriptText.isEmpty() )
970 {
971 mRootBlock.reset( parseArcadeScript( scriptText, mParserErrorString ) );
972 }
973}
974
976 : mScript( other.mScript )
978{
979 if ( other.mRootBlock )
980 {
981 mRootBlock.reset( dynamic_cast<QgsEsriArcadeBlockStatement *>( other.mRootBlock->clone() ) );
982 }
983}
984
986{
987 if ( this != &other )
988 {
989 mScript = other.mScript;
991 if ( other.mRootBlock )
992 {
993 mRootBlock.reset( dynamic_cast<QgsEsriArcadeBlockStatement *>( other.mRootBlock->clone() ) );
994 }
995 else
996 {
997 mRootBlock.reset();
998 }
999 }
1000 return *this;
1001}
1002
1004
1006{
1007 return !mParserErrorString.isEmpty() || ( !mScript.trimmed().isEmpty() && !mRootBlock );
1008}
1009
1011{
1012 return mParserErrorString;
1013}
1014
1016{
1017 return mRootBlock.get();
1018}
1019
1021{
1022 if ( !mScript.isEmpty() )
1023 return mScript;
1024
1025 return dump();
1026}
1027
1029{
1030 if ( !mRootBlock )
1031 return QString();
1032
1033 return mRootBlock->dump();
1034}
1035
1037{
1038 if ( mRootBlock )
1039 mRootBlock->accept( visitor );
1040}
1041
1042QString QgsEsriArcadeScript::quotedString( const QString &text )
1043{
1044 QString escaped = text;
1045 escaped.replace( '\\'_L1, "\\\\"_L1 );
1046 escaped.replace( '\"'_L1, "\\\""_L1 );
1047 escaped.replace( '\n'_L1, "\\n"_L1 );
1048 escaped.replace( '\t'_L1, "\\t"_L1 );
1049 escaped.replace( '\r'_L1, "\\r"_L1 );
1050 return u"\"%1\""_s.arg( escaped );
1051}
Represents an array literal expression.
QgsEsriArcadeArrayLiteralExpression(const QList< QgsEsriArcadeExpression * > &elements)
Constructor for QgsEsriArcadeArrayLiteralExpression.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QList< QgsEsriArcadeExpression * > elements() const
Returns the list of element expressions.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
QString dump() const override
Returns the formatted script representation of the node.
Represents a variable reassignment statement.
AssignmentOperator
Assignment operator types.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeExpression * value() const
Returns the assigned value expression.
static const char * ASSIGNMENT_OPERATOR_TEXT[]
QgsEsriArcadeAssignmentStatement(AssignmentOperator assignmentOperator, QgsEsriArcadeExpression *target, QgsEsriArcadeExpression *value)
Constructor for QgsEsriArcadeAssignmentStatement.
QString dump() const override
Returns the formatted script representation of the node.
QgsEsriArcadeExpression * target() const
Returns the target expression being assigned to.
AssignmentOperator assignmentOperator() const
Returns the assignment operator.
Represents a binary operation expression.
QgsEsriArcadeBinaryOperatorExpression(BinaryOperator binaryOperator, QgsEsriArcadeExpression *leftOperand, QgsEsriArcadeExpression *rightOperand)
Constructor for QgsEsriArcadeBinaryOperatorExpression.
BinaryOperator binaryOperator() const
Returns the binary operator.
QString dump() const override
Returns the formatted script representation of the node.
BinaryOperator
Binary operator enumeration.
@ BitwiseSignedRightShift
Bitwise right shift, eg "7 >> 14".
@ BitwiseUnsignedRightShift
Bitwise unsigned right shift, eg "7 >>> 14".
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeExpression * rightOperand() const
Returns the right-hand operand expression.
bool leftAssociative() const
Returns true if operator is left-associative.
QgsEsriArcadeExpression * leftOperand() const
Returns the left-hand operand expression.
int precedence() const
Returns operator precedence value.
QString text() const
Returns text representation of the operator.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
Represents a sequence or block of statements enclosed in braces.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QString dump() const override
Returns the formatted script representation of the node.
QList< QgsEsriArcadeStatement * > statements() const
Returns the list of statements contained within this block.
void appendStatement(QgsEsriArcadeStatement *statement)
Appends a statement to the block.
Represents a break loop control statement.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
QgsEsriArcadeBreakStatement()=default
Constructor for QgsEsriArcadeBreakStatement.
QString dump() const override
Returns the formatted script representation of the node.
Represents a continue loop control statement.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeContinueStatement()=default
Constructor for QgsEsriArcadeContinueStatement.
QString dump() const override
Returns the formatted script representation of the node.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
Represents a key-value entry in an Esri Arcade dictionary literal.
QgsEsriArcadeDictionaryElement * clone() const
Creates a deep copy of the element.
QString dump() const
Formats the element as string.
QString key() const
Returns the entry key.
bool isAutoKey() const
Returns true if the entry was defined using auto-keys.
QgsEsriArcadeExpression * value() const
Returns the entry value expression.
QgsEsriArcadeDictionaryElement(const QString &key, QgsEsriArcadeExpression *value, bool isAutoKey=false)
Constructor for QgsEsriArcadeDictionaryElement.
Represents a dictionary literal expression.
QgsEsriArcadeDictionaryLiteralExpression(const QList< QgsEsriArcadeDictionaryElement * > &elements)
Constructor for QgsEsriArcadeDictionaryLiteralExpression.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
QString dump() const override
Returns the formatted script representation of the node.
QList< QgsEsriArcadeDictionaryElement * > elements() const
Returns the dictionary elements.
Represents an expression evaluated as a statement.
QgsEsriArcadeExpressionStatement(QgsEsriArcadeExpression *expression)
Constructor for QgsEsriArcadeExpressionStatement.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
QString dump() const override
Returns the formatted script representation of the node.
QgsEsriArcadeExpression * expression() const
Returns the underlying expression.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
Base class for expression nodes in an Esri Arcade script.
Represents a range based for...in or for...of iteration statement.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
IterationType iterationType() const
Returns the iteration type (for...in or for...of).
QgsEsriArcadeForInStatement(IterationType iterationType, const QString &variableName, bool isVariableDeclaration, QgsEsriArcadeExpression *collection, QgsEsriArcadeBlockStatement *body)
Constructor for QgsEsriArcadeForInStatement.
QgsEsriArcadeExpression * collection() const
Returns the collection expression being iterated over.
QgsEsriArcadeBlockStatement * body() const
Returns the loop body block statement.
QString dump() const override
Returns the formatted script representation of the node.
IterationType
Type of iteration loop.
QString variableName() const
Returns the loop variable identifier name.
bool isVariableDeclaration() const
Returns true if the loop variable was declared with the var keyword.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
Represents a standard counter-based for loop.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
QgsEsriArcadeNode * step() const
Returns the step expression or statement, or nullptr if none.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeBlockStatement * body() const
Returns the loop body block statement.
QgsEsriArcadeStatement * initialization() const
Returns the initialization statement, or nullptr if none.
QgsEsriArcadeForStatement(QgsEsriArcadeStatement *initialization, QgsEsriArcadeExpression *condition, QgsEsriArcadeNode *step, QgsEsriArcadeBlockStatement *body)
Constructor for QgsEsriArcadeForStatement.
QString dump() const override
Returns the formatted script representation of the node.
QgsEsriArcadeExpression * condition() const
Returns the loop condition expression, or nullptr if none.
Represents a function call expression.
QList< QgsEsriArcadeExpression * > arguments() const
Returns the list of argument expressions.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
QString functionName() const
Returns the function name.
QString dump() const override
Returns the formatted script representation of the node.
QgsEsriArcadeFunctionCallExpression(const QString &functionName, const QList< QgsEsriArcadeExpression * > &arguments)
Constructor for QgsEsriArcadeFunctionCallExpression.
Represents a function declaration statement.
QString functionName() const
Returns the function name.
QStringList parameters() const
Returns the parameter names.
QString dump() const override
Returns the formatted script representation of the node.
QgsEsriArcadeBlockStatement * body() const
Returns the function body block.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
QgsEsriArcadeFunctionDeclarationStatement(const QString &functionName, const QStringList &parameters, QgsEsriArcadeBlockStatement *body)
Constructor for QgsEsriArcadeFunctionDeclarationStatement.
Represents an if statement.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeExpression * condition() const
Returns the condition expression.
QgsEsriArcadeIfStatement(QgsEsriArcadeExpression *condition, QgsEsriArcadeBlockStatement *trueBlock, QgsEsriArcadeBlockStatement *falseBlock=nullptr)
Constructor for QgsEsriArcadeIfStatement.
QString dump() const override
Returns the formatted script representation of the node.
QgsEsriArcadeBlockStatement * falseBlock() const
Returns the statement block executed when the condition evaluates to false, or nullptr if none.
QgsEsriArcadeBlockStatement * trueBlock() const
Returns the statement block executed when the condition evaluates to true.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
Represents an array or dictionary index subscript expression.
QgsEsriArcadeExpression * indexExpression() const
Returns the index expression.
QgsEsriArcadeIndexExpression(QgsEsriArcadeExpression *containerExpression, QgsEsriArcadeExpression *indexExpression)
Constructor for QgsEsriArcadeIndexExpression.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeExpression * containerExpression() const
Returns the container expression being indexed.
QString dump() const override
Returns the formatted script representation of the node.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
Represents a literal value (number, text string, boolean, or null).
QString dump() const override
Returns the formatted script representation of the node.
QVariant value() const
Returns the literal value.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
QString valueAsString() const
Returns a string representation of the literal value.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeLiteralExpression(const QVariant &value)
Constructor for QgsEsriArcadeLiteralExpression.
Represents a member access expression using dot or bracket notation.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
bool isSafeAccess() const
Returns true if member access uses the safe access operator "?.".
QgsEsriArcadeExpression * containerExpression() const
Returns the container expression being accessed.
QString memberName() const
Returns the member attribute name.
QString dump() const override
Returns the formatted script representation of the node.
QgsEsriArcadeMemberAccessExpression(QgsEsriArcadeExpression *containerExpression, const QString &memberName, bool isSafeAccess=false)
Constructor for QgsEsriArcadeMemberAccessExpression.
Represents an abstract node for an Esri Arcade script.
virtual void accept(QgsEsriArcadeVisitor &visitor) const =0
Accepts a visitor to traverse the node.
virtual QgsEsriArcadeNode * clone() const =0
Creates a copy of the node.
Represents a reference to a profile variable.
QgsEsriArcadeProfileVariableReferenceExpression(const QString &name)
Constructor for QgsEsriArcadeProfileVariableReferenceExpression.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
QString dump() const override
Returns the formatted script representation of the node.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QString name() const
Returns the profile variable name, including the leading $ symbol.
void visit(const QgsEsriArcadeBlockStatement &node) override
Visit a QgsEsriArcadeBlockStatement node.
Represents a return statement.
QgsEsriArcadeReturnStatement(QgsEsriArcadeExpression *expression=nullptr)
Constructor for QgsEsriArcadeReturnStatement.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
QString dump() const override
Returns the formatted script representation of the node.
QgsEsriArcadeExpression * expression() const
Returns the expression returned by the statement, or nullptr if void return.
QString dump() const
Dumps the abstract syntax tree back into an Arcade script string.
std::unique_ptr< QgsEsriArcadeBlockStatement > mRootBlock
void acceptVisitor(QgsEsriArcadeVisitor &visitor) const
Accepts a visitor to traverse the script abstract syntax tree.
const QgsEsriArcadeBlockStatement * rootBlock() const
Returns the root block statement node, or nullptr if parsing failed.
QgsEsriArcadeScript & operator=(const QgsEsriArcadeScript &other)
bool hasParserError() const
Returns true if a parsing error occurred.
static QString quotedString(const QString &text)
Returns a properly quoted string literal (enclosed in double quotes with escape sequences).
QgsEsriArcadeScript(const QString &scriptText=QString())
Creates a new script from scriptText.
QString script() const
Returns the original script text.
QString parserErrorString() const
Returns parser error description.
Base class for statement nodes in an Esri Arcade script.
Represents a unary operation expression.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeUnaryOperatorExpression(UnaryOperator unaryOperator, QgsEsriArcadeExpression *operand)
Constructor for QgsEsriArcadeUnaryOperatorExpression.
QgsEsriArcadeExpression * operand() const
Returns the operand expression.
QString text() const
Returns text representation of the operator.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
UnaryOperator unaryOperator() const
Returns the unary operator.
QString dump() const override
Returns the formatted script representation of the node.
UnaryOperator
Unary operator enumeration.
Represents a variable declaration statement.
QString dump() const override
Returns the formatted script representation of the node.
QgsEsriArcadeVariableDeclarationStatement(const QString &variableName, QgsEsriArcadeExpression *initializer=nullptr)
Constructor for QgsEsriArcadeVariableDeclarationStatement.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeExpression * initializer() const
Returns the optional initializer expression, or nullptr if uninitialized.
QString variableName() const
Returns the declared variable name.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
Represents a reference to a variable identifier.
QString dump() const override
Returns the formatted script representation of the node.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QString name() const
Returns the variable identifier name.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
QgsEsriArcadeVariableReferenceExpression(const QString &name)
Constructor for QgsEsriArcadeVariableReferenceExpression.
Abstract visitor interface for traversing Esri Arcade abstract syntax trees.
virtual void visit(const QgsEsriArcadeBlockStatement &node)=0
Visit a QgsEsriArcadeBlockStatement node.
Represents a while loop statement.
QgsEsriArcadeBlockStatement * body() const
Returns the loop body block statement.
QgsEsriArcadeWhileStatement(QgsEsriArcadeExpression *condition, QgsEsriArcadeBlockStatement *body)
Constructor for QgsEsriArcadeWhileStatement.
QgsEsriArcadeExpression * condition() const
Returns the loop condition expression.
QString dump() const override
Returns the formatted script representation of the node.
void accept(QgsEsriArcadeVisitor &visitor) const override
Accepts a visitor to traverse the node.
QgsEsriArcadeNode * clone() const override
Creates a copy of the node.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:7690
QgsEsriArcadeBlockStatement * parseArcadeScript(const QString &scriptText, QString &parserErrorMessage)