Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
ExpressionParserTypes.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
6#include "Templates/PointerIsConvertibleFromTo.h"
7#include "Templates/UnrealTemplate.h"
8#include "Containers/Array.h"
9#include "Containers/UnrealString.h"
10#include "Templates/Function.h"
11#include "Containers/Set.h"
12#include "Containers/Map.h"
13#include "Misc/Optional.h"
14#include "Internationalization/Text.h"
15#include "Internationalization/Internationalization.h"
16#include "Misc/Guid.h"
17#include "Templates/ValueOrError.h"
18
19class FExpressionNode;
20struct FExpressionError;
21
22namespace Impl
23{
25}
26
28
29/** Simple error structure used for reporting parse errors */
31{
32 FExpressionError(const FText& InText) : Text(InText) {}
33
35};
36
37/** Simple struct that defines a specific token contained in an FTokenStream */
39{
40public:
41 FStringToken() : TokenStart(nullptr), TokenEnd(nullptr), LineNumber(0), CharacterIndex(0) {}
42
43 /** Get the string representation of this token */
45
46 /** Check if this token is valid */
47 bool IsValid() const { return TokenEnd != TokenStart; }
48
49 /** Get the position of the start and end of this token in the stream */
50 const TCHAR* GetTokenStartPos() const { return TokenStart; }
51 const TCHAR* GetTokenEndPos() const { return TokenEnd; }
52
53 /** Contextual information about this token */
54 int32 GetCharacterIndex() const { return CharacterIndex; }
55 int32 GetLineNumber() const { return LineNumber; }
56
57 /** Accumulate another token into this one */
58 void Accumulate(const FStringToken& InToken) { if (InToken.TokenEnd > TokenEnd) { TokenEnd = InToken.TokenEnd; } }
59
60protected:
61 friend class FTokenStream;
62
63 FStringToken(const TCHAR* InStart, int32 Line = 0, int32 Character = 0)
64 : TokenStart(InStart), TokenEnd(InStart), LineNumber(Line), CharacterIndex(Character)
65 {}
66
67 /** The start of the token */
68 const TCHAR* TokenStart;
69 /** The end of the token */
70 const TCHAR* TokenEnd;
71 /** Line number and Character index */
73};
74
75/** Enum specifying how to treat the currently parsing character. */
76enum class EParseState
77{
78 /** Include this character in the token and continue consuming */
80 /** Include this character in the token and stop consuming */
82 /** Exclude this character from the token and stop consuming */
84 /** Cancel parsing this token, and return nothing. */
85 Cancel,
86};
87
88/** A token stream wraps up a raw string, providing accessors into it for consuming tokens */
90{
91public:
92
93 /**
94 * Parse out a token using the supplied predicate.
95 * Will keep consuming characters into the resulting token provided the predicate returns EParseState::Continue or EParseState::StopAfter.
96 * Optionally supply a token to accumulate into
97 * Returns a string token for the stream, or empty on error
98 */
99 TOptional<FStringToken> ParseToken(TFunctionRef<EParseState(TCHAR)> Pred, FStringToken* Accumulate = nullptr) const;
100
101 /** Attempt parse out the specified pre-defined string from the current read position (or accumulating into the specified existing token) */
102 TOptional<FStringToken> ParseToken(const TCHAR* Symbol, FStringToken* Accumulate = nullptr) const;
103 TOptional<FStringToken> ParseTokenIgnoreCase(const TCHAR* Symbol, FStringToken* Accumulate = nullptr) const;
104
105 /** Return a string token for the next character in the stream (or accumulating into the specified existing token) */
106 TOptional<FStringToken> ParseSymbol(FStringToken* Accumulate = nullptr) const;
107
108 /** Attempt parse out the specified pre-defined string from the current read position (or accumulating into the specified existing token) */
109 TOptional<FStringToken> ParseSymbol(TCHAR Symbol, FStringToken* Accumulate = nullptr) const;
110
111 /** Parse a whitespace token */
112 TOptional<FStringToken> ParseWhitespace(FStringToken* Accumulate = nullptr) const;
113
114 /** Generate a token for the specified number of chars, at the current read position (or end of Accumulate) */
115 TOptional<FStringToken> GenerateToken(int32 NumChars, FStringToken* Accumulate = nullptr) const;
116
117public:
118
119 /** Constructor. The stream is only valid for the lifetime of the string provided */
120 FTokenStream(const TCHAR* In);
121
122 /** Peek at the character at the specified offset from the current read position */
123 TCHAR PeekChar(int32 Offset = 0) const;
124
125 /** Get the number of characters remaining in the stream after the current read position */
126 int32 CharsRemaining() const;
127
128 /** Check if it is valid to read (the optional number of characters) from the specified position */
129 bool IsReadPosValid(const TCHAR* InPos, int32 MinNumChars = 1) const;
130
131 /** Check if the stream is empty */
132 bool IsEmpty() const;
133
134 /** Get the current read position from the start of the stream */
135 int32 GetPosition() const;
136
137 const TCHAR* GetStart() const { return Start; }
138 const TCHAR* GetRead() const { return ReadPos; }
139 const TCHAR* GetEnd() const { return End; }
140
141 /** Get the error context from the current read position */
143
144 /** Set the current read position to the character proceeding the specified token */
145 void SetReadPos(const FStringToken& Token);
146
147private:
148
149 /** The start of the expression */
150 const TCHAR* Start;
151 /** The end of the expression */
152 const TCHAR* End;
153 /** The current read position in the expression */
154 const TCHAR* ReadPos;
155};
156
157/** Helper macro to define the necessary template specialization for a particular expression node type */
158/** Variable length arguments are passed the FGuid constructor. Must be unique per type */
159#define DEFINE_EXPRESSION_NODE_TYPE(TYPE, ...) template
160 <> struct TGetExpressionNodeTypeId<TYPE>\
161{
162 static const FGuid& GetTypeId()
163 {
164 static FGuid Global(__VA_ARGS__);
165 return Global;
166 }\
167};
168template<typename T> struct TGetExpressionNodeTypeId;
169
170/** Primitive types should only be declared once inside the codebase to avoid conflicts */
171DEFINE_EXPRESSION_NODE_TYPE(bool, 0xCACBC715, 0x505A6B4A, 0x8808809F, 0x897AA5F6)
172DEFINE_EXPRESSION_NODE_TYPE(double, 0x8444A8A3, 0x19AE4E13, 0xBCFA75EE, 0x39982BD6)
173
174/**
175 * A node in an expression.
176 * Can be constructed from any C++ type that has a corresponding DEFINE_EXPRESSION_NODE_TYPE.
177 * Evaluation behaviour (unary/binary operator etc) is defined in the expression grammar, rather than the type itself.
178 */
180{
181public:
182
183 /** Default constructor */
185
186 /** Construction from client expression data type */
187 template<typename T>
188 FExpressionNode(T In,
189 /** @todo: make this a default function template parameter when VS2012 support goes */
190 typename TEnableIf<!TPointerIsConvertibleFromTo<T, FExpressionNode>::Value>::Type* = nullptr
191 );
192
194
195 /** Move construction/assignment */
198
199 /** Get the type identifier of this node */
200 const FGuid& GetTypeId() const;
201
202 /** Cast this node to the specified type. Will return nullptr if the types do not match. */
203 template<typename T>
204 const T* Cast() const;
205
206 /** Copy this node and its wrapped data */
208
209private:
210
211 /** The maximum size of type we will allow allocation on the stack (for efficiency). Anything larger will be allocated on the heap. */
212 static constexpr uint32 MaxStackAllocationSize = 64 - sizeof(FGuid);
213
214 /** Helper accessor to the data interface. Returns null for empty containers. */
217
218 /** TypeID - 16 bytes */
220 alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) uint8 InlineBytes[MaxStackAllocationSize];
221};
222
223/** A specific token in a stream. Comprises an expression node, and the stream token it was created from */
225{
226public:
228 : Node(MoveTemp(InNode))
229 , Context(InContext)
230 {
231 }
232
234 FExpressionToken& operator=(FExpressionToken&& In) { Node = MoveTemp(In.Node); Context = In.Context; return *this; }
235
238};
239
240/** A compiled token, holding the token itself, and any compiler information required to evaluate it */
242{
243 // Todo: add callable types here?
245
246 FCompiledToken(EType InType, FExpressionToken InToken, TOptional<int32> InShortCircuitIndex = TOptional<int32>())
247 : FExpressionToken(MoveTemp(InToken)), Type(InType), ShortCircuitIndex(InShortCircuitIndex)
248 {}
249
251 FCompiledToken& operator=(FCompiledToken&& In) { FExpressionToken::operator=(MoveTemp(In)); Type = In.Type; return *this; }
252
255};
256
257/** Struct used to identify a function for a specific operator overload */
259{
263
264 friend bool operator==(const FOperatorFunctionID& A, const FOperatorFunctionID& B)
265 {
266 return A.OperatorType == B.OperatorType &&
269 }
270
271 friend uint32 GetTypeHash(const FOperatorFunctionID& In)
272 {
273 const uint32 Hash = HashCombine(GetTypeHash(In.OperatorType), GetTypeHash(In.LeftOperandType));
274 return HashCombine(GetTypeHash(In.RightOperandType), Hash);
275 }
276};
277
278/** Jump table specifying how to execute an operator with different types */
279template<typename ContextType=void>
281{
282 /** Execute the specified token as a unary operator, if such an overload exists */
283 FExpressionResult ExecPreUnary(const FExpressionToken& Operator, const FExpressionToken& R, const ContextType* Context) const;
284 /** Execute the specified token as a unary operator, if such an overload exists */
285 FExpressionResult ExecPostUnary(const FExpressionToken& Operator, const FExpressionToken& L, const ContextType* Context) const;
286 /** Execute the specified token as a binary operator, if such an overload exists */
287 FExpressionResult ExecBinary(const FExpressionToken& Operator, const FExpressionToken& L, const FExpressionToken& R, const ContextType* Context) const;
288 /** Check whether we should short circuit the specified operator */
289 bool ShouldShortCircuit(const FExpressionToken& Operator, const FExpressionToken& L, const ContextType* Context) const;
290
291 /**
292 * Map an expression node to a pre-unary operator with the specified implementation.
293 *
294 * The callable type must match the declaration Ret(Operand[, Context]), where:
295 * Ret = Any DEFINE_EXPRESSION_NODE_TYPE type, OR FExpressionResult
296 * Operand = Any DEFINE_EXPRESSION_NODE_TYPE type
297 * Context = (optional) const ptr to user-supplied arbitrary context
298 *
299 * Examples that binds a '!' token to a function that attempts to do a boolean 'not':
300 * JumpTable.MapPreUnary<FExclamation>([](bool A){ return !A; });
301 * JumpTable.MapPreUnary<FExclamation>([](bool A, FMyContext* Ctxt){ if (Ctxt->IsBooleanNotOpEnabled()) { return !A; } else { return A; } });
302 * JumpTable.MapPreUnary<FExclamation>([](bool A, const FMyContext* Ctxt) -> FExpressionResult {
303
304 * if (Ctxt->IsBooleanNotOpEnabled())
305 * {
306 * return MakeValue(!A);
307 * }
308 * return MakeError(FExpressionError(LOCTEXT("NotNotEnabled", "Boolean not is not enabled.")));
309 * });
310 */
311 template<typename OperatorType, typename FuncType>
312 void MapPreUnary(FuncType InFunc);
313
314 /**
315 * Map an expression node to a post-unary operator with the specified implementation.
316 * The same function signature rules apply here as with MapPreUnary.
317 */
318 template<typename OperatorType, typename FuncType>
319 void MapPostUnary(FuncType InFunc);
320
321 /**
322 * Map an expression node to a binary operator with the specified implementation.
323 *
324 * The callable type must match the declaration Ret(OperandL, OperandR, [, Context]), where:
325 * Ret = Any DEFINE_EXPRESSION_NODE_TYPE type, OR FExpressionResult
326 * OperandL = Any DEFINE_EXPRESSION_NODE_TYPE type
327 * OperandR = Any DEFINE_EXPRESSION_NODE_TYPE type
328 * Context = (optional) const ptr to user-supplied arbitrary context
329 *
330 * Examples that binds a '/' token to a function that attempts to do a division:
331 * JumpTable.MapUnary<FForwardSlash>([](double A, double B){ return A / B; }); // Runtime exception on div/0
332 * JumpTable.MapUnary<FForwardSlash>([](double A, double B, FMyContext* Ctxt){
333 * if (!Ctxt->IsMathEnabled())
334 * {
335 * return A;
336 * }
337 * return A / B; // Runtime exception on div/0
338 * });
339 * JumpTable.MapUnary<FForwardSlash>([](double A, double B, const FMyContext* Ctxt) -> FExpressionResult {
340 * if (!Ctxt->IsMathEnabled())
341 * {
342 * return MakeError(FExpressionError(LOCTEXT("MathNotEnabled", "Math is not enabled.")));
343 * }
344 * else if (B == 0)
345 * {
346 * return MakeError(FExpressionError(LOCTEXT("DivisionByZero", "Division by zero.")));
347 * }
348 *
349 * return MakeValue(!A);
350 * });
351 */
352 template<typename OperatorType, typename FuncType>
353 void MapBinary(FuncType InFunc);
354
355 template<typename OperatorType, typename FuncType>
356 void MapShortCircuit(FuncType InFunc);
357
358public:
359
360 typedef TFunction<FExpressionResult(const FExpressionNode&, const ContextType* Context)> FUnaryFunction;
361 typedef TFunction<FExpressionResult(const FExpressionNode&, const FExpressionNode&, const ContextType* Context)> FBinaryFunction;
362 typedef TFunction<bool(const FExpressionNode&, const ContextType* Context)> FShortCircuit;
363
364private:
365
366 /** Maps of unary/binary operators */
371};
372
374
375/** Structures used for managing the evaluation environment for operators in an expression. This class manages the evaluation context
376 * to avoid templating the whole evaluation code on a context type
377 */
379{
380 /** Execute the specified token as a unary operator, if such an overload exists */
381 virtual FExpressionResult ExecPreUnary(const FExpressionToken& Operator, const FExpressionToken& R) const = 0;
382 /** Execute the specified token as a unary operator, if such an overload exists */
383 virtual FExpressionResult ExecPostUnary(const FExpressionToken& Operator, const FExpressionToken& L) const = 0;
384 /** Execute the specified token as a binary operator, if such an overload exists */
385 virtual FExpressionResult ExecBinary(const FExpressionToken& Operator, const FExpressionToken& L, const FExpressionToken& R) const = 0;
386 /** Check whether we should short circuit the specified operator */
387 virtual bool ShouldShortCircuit(const FExpressionToken& Operator, const FExpressionToken& L) const = 0;
388};
389template<typename ContextType = void>
391{
392 TOperatorEvaluationEnvironment(const TOperatorJumpTable<ContextType>& InOperators, const ContextType* InContext)
394 {}
395
396 virtual FExpressionResult ExecPreUnary(const FExpressionToken& Operator, const FExpressionToken& R) const override
397 {
399 }
400 virtual FExpressionResult ExecPostUnary(const FExpressionToken& Operator, const FExpressionToken& L) const override
401 {
403 }
404 virtual FExpressionResult ExecBinary(const FExpressionToken& Operator, const FExpressionToken& L, const FExpressionToken& R) const override
405 {
407 }
408 virtual bool ShouldShortCircuit(const FExpressionToken& Operator, const FExpressionToken& L) const override
409 {
411 }
412
413private:
414 const TOperatorJumpTable<ContextType>& Operators;
415 const ContextType* Context;
416};
417
419
420/** Class used to consume tokens from a string */
422{
423public:
424 /** Construction from a raw string. The consumer is only valid as long as the string is valid */
425 FExpressionTokenConsumer(const TCHAR* InExpression);
426
427 /** Extract the list of tokens from this consumer */
429
430 /** Add an expression node to the consumer, specifying the FStringToken this node relates to.
431 * Adding a node to the consumer will move its stream read position to the end of the added token.
432 */
433 void Add(const FStringToken& SourceToken, FExpressionNode&& Node);
434
435 /** Get the expression stream */
437
438private:
441
442 /** Array of added tokens */
444
445 /** Stream that looks at the constructed expression */
447};
448
449/**
450 * Typedef that defines a function used to consume tokens
451 * Definitions may add FExpressionNodes parsed from the provided consumer's stream, or return an optional error.
452 * Where a definition performs no mutable operations, subsequent token definitions will be invoked.
453 */
455
456
457/** A lexeme dictionary defining how to lex an expression. */
459{
460public:
462
463 /** Define the grammar to ignore whitespace between tokens, unless explicitly included in a token */
465
466 /** Define a token by way of a function to be invoked to attempt to parse a token from a stream */
467 void DefineToken(TFunction<FExpressionDefinition>&& Definition);
468
469public:
470
471 /** Check if the grammar ignores whitespace */
473
474 /** Consume a token for the specified consumer */
476
477private:
478
480
481private:
482
485};
486
487
488/**
489 * Enum specifying the associativity (order of execution) for binary operators
490 */
492{
495};
496
497/**
498 * Struct for storing binary operator definition parameters
499 */
501{
502 /** The precedence of the operator */
504
505 /** The associativity of the operator */
507
508 /** Whether this operator can be short circuited or not */
510
511 FOpParameters(int32 InPrecedence, EAssociativity InAssociativity, bool bInCanShortCircuit)
512 : Precedence(InPrecedence)
513 , Associativity(InAssociativity)
514 , bCanShortCircuit(bInCanShortCircuit)
515 {
516 }
517};
518
519/** A lexical gammer defining how to parse an expression. Clients must define the tokens and operators to be interpreted by the parser. */
521{
522public:
523 /** Define a grouping operator from two expression node types */
524 template<typename TStartGroup, typename TEndGroup>
526
527 /** Define a pre-unary operator for the specified symbol */
528 template<typename TExpressionNode>
530
531 /** Define a post-unary operator for the specified symbol */
532 template<typename TExpressionNode>
534
535 /**
536 * Define a binary operator for the specified symbol, with the specified precedence and associativity
537 * NOTE: Associativity defaults to RightToLeft for legacy reasons.
538 *
539 * @param InPrecedence The precedence (priority of execution) this operator should have
540 * @param InAssociativity With operators of the same precedence, determines whether they execute left to right, or right to left
541 */
542 template<typename TExpressionNode>
543 void DefineBinaryOperator(int32 InPrecedence, EAssociativity InAssociativity=EAssociativity::RightToLeft, bool bCanShortCircuit = false)
544 {
545#if DO_CHECK
547 {
548 const FOpParameters& CurValue = It.Value();
549
551 {
552 // Operators of the same precedence, must all have the same associativity
554 }
555 }
556#endif
557
559 }
560
561public:
562
563 /** Retrieve the corresponding grouping token for the specified open group type, or nullptr if it's not a group token */
564 const FGuid* GetGrouping(const FGuid& TypeId) const;
565
566 /** Check if this grammar defines a pre-unary operator for the specified symbol */
567 bool HasPreUnaryOperator(const FGuid& TypeId) const;
568
569 /** Check if this grammar defines a post-unary operator for the specified symbol */
570 bool HasPostUnaryOperator(const FGuid& TypeId) const;
571
572 /** Get the binary operator precedence and associativity parameters, for the specified symbol, if any */
574
575private:
576
581};
582
583#include "Misc/ExpressionParserTypes.inl" // IWYU pragma: export
#define DO_CHECK
Definition Build.h:311
EParseState
Definition Enums.h:12786
EAssociativity
Definition Enums.h:8076
#define DEFINE_EXPRESSION_NODE_TYPE(TYPE,...)
typedef TOptional< FExpressionError >(FExpressionDefinition)(FExpressionTokenConsumer &)
TOperatorJumpTable FOperatorJumpTable
TOperatorEvaluationEnvironment FOperatorEvaluationEnvironment
TValueOrError< FExpressionNode, FExpressionError > FExpressionResult
const FGuid * GetGrouping(const FGuid &TypeId) const
TMap< FGuid, FGuid > Groupings
void DefineBinaryOperator(int32 InPrecedence, EAssociativity InAssociativity=EAssociativity::RightToLeft, bool bCanShortCircuit=false)
bool HasPostUnaryOperator(const FGuid &TypeId) const
const FOpParameters * GetBinaryOperatorDefParameters(const FGuid &TypeId) const
TMap< FGuid, FOpParameters > BinaryOperators
bool HasPreUnaryOperator(const FGuid &TypeId) const
const FGuid & GetTypeId() const
FExpressionNode(FExpressionNode &&In)
uint8 InlineBytes[MaxStackAllocationSize]
static constexpr uint32 MaxStackAllocationSize
FExpressionNode(T In, typename TEnableIf<!TPointerIsConvertibleFromTo< T, FExpressionNode >::Value >::Type *=nullptr)
FExpressionNode & operator=(FExpressionNode &&In)
Impl::IExpressionNodeStorage * GetData()
FExpressionNode Copy() const
const Impl::IExpressionNodeStorage * GetData() const
TArray< FExpressionToken > Extract()
FExpressionTokenConsumer(const FExpressionTokenConsumer &)
FExpressionTokenConsumer(const TCHAR *InExpression)
TArray< FExpressionToken > Tokens
void Add(const FStringToken &SourceToken, FExpressionNode &&Node)
FExpressionTokenConsumer & operator=(const FExpressionTokenConsumer &)
FExpressionToken & operator=(FExpressionToken &&In)
FExpressionToken(const FStringToken &InContext, FExpressionNode InNode)
FExpressionToken(FExpressionToken &&In)
ARK_API FString(int32 Len, const WIDECHAR *Str)
Definition String.cpp:254
int32 GetCharacterIndex() const
const TCHAR * TokenEnd
FStringToken(const TCHAR *InStart, int32 Line=0, int32 Character=0)
const TCHAR * TokenStart
int32 GetLineNumber() const
const TCHAR * GetTokenStartPos() const
FString GetString() const
void Accumulate(const FStringToken &InToken)
const TCHAR * GetTokenEndPos() const
Definition Text.h:357
TArray< TFunction< FExpressionDefinition > > Definitions
void DefineToken(TFunction< FExpressionDefinition > &&Definition)
TOptional< FExpressionError > ConsumeToken(FExpressionTokenConsumer &Consumer) const
TOptional< FExpressionError > ConsumeTokens(FExpressionTokenConsumer &Consumer) const
TOptional< FStringToken > ParseWhitespace(FStringToken *Accumulate=nullptr) const
const TCHAR * GetRead() const
TOptional< FStringToken > ParseSymbol(TCHAR Symbol, FStringToken *Accumulate=nullptr) const
bool IsEmpty() const
int32 GetPosition() const
void SetReadPos(const FStringToken &Token)
TOptional< FStringToken > GenerateToken(int32 NumChars, FStringToken *Accumulate=nullptr) const
TOptional< FStringToken > ParseTokenIgnoreCase(const TCHAR *Symbol, FStringToken *Accumulate=nullptr) const
FTokenStream(const TCHAR *In)
const TCHAR * GetEnd() const
FString GetErrorContext() const
const TCHAR * ReadPos
TOptional< FStringToken > ParseToken(const TCHAR *Symbol, FStringToken *Accumulate=nullptr) const
bool IsReadPosValid(const TCHAR *InPos, int32 MinNumChars=1) const
int32 CharsRemaining() const
TOptional< FStringToken > ParseToken(TFunctionRef< EParseState(TCHAR)> Pred, FStringToken *Accumulate=nullptr) const
TOptional< FStringToken > ParseSymbol(FStringToken *Accumulate=nullptr) const
TCHAR PeekChar(int32 Offset=0) const
const TCHAR * GetStart() const
FCompiledToken(EType InType, FExpressionToken InToken, TOptional< int32 > InShortCircuitIndex=TOptional< int32 >())
FCompiledToken(FCompiledToken &&In)
TOptional< int32 > ShortCircuitIndex
FCompiledToken & operator=(FCompiledToken &&In)
FExpressionError(const FText &InText)
Definition Guid.h:108
friend bool operator==(const FGuid &X, const FGuid &Y)
Definition Guid.h:148
FGuid(uint32 InA, uint32 InB, uint32 InC, uint32 InD)
Definition Guid.h:127
FGuid()
Definition Guid.h:112
friend uint32 GetTypeHash(const FGuid &Guid)
Definition Guid.h:350
FOpParameters(int32 InPrecedence, EAssociativity InAssociativity, bool bInCanShortCircuit)
EAssociativity Associativity
friend bool operator==(const FOperatorFunctionID &A, const FOperatorFunctionID &B)
friend uint32 GetTypeHash(const FOperatorFunctionID &In)
virtual FExpressionResult ExecBinary(const FExpressionToken &Operator, const FExpressionToken &L, const FExpressionToken &R) const =0
virtual FExpressionResult ExecPostUnary(const FExpressionToken &Operator, const FExpressionToken &L) const =0
virtual FExpressionResult ExecPreUnary(const FExpressionToken &Operator, const FExpressionToken &R) const =0
virtual bool ShouldShortCircuit(const FExpressionToken &Operator, const FExpressionToken &L) const =0
virtual FExpressionResult ExecPostUnary(const FExpressionToken &Operator, const FExpressionToken &L) const override
virtual bool ShouldShortCircuit(const FExpressionToken &Operator, const FExpressionToken &L) const override
const TOperatorJumpTable< ContextType > & Operators
TOperatorEvaluationEnvironment(const TOperatorJumpTable< ContextType > &InOperators, const ContextType *InContext)
virtual FExpressionResult ExecPreUnary(const FExpressionToken &Operator, const FExpressionToken &R) const override
virtual FExpressionResult ExecBinary(const FExpressionToken &Operator, const FExpressionToken &L, const FExpressionToken &R) const override
FExpressionResult ExecPreUnary(const FExpressionToken &Operator, const FExpressionToken &R, const ContextType *Context) const
TMap< FOperatorFunctionID, FUnaryFunction > PostUnaryOps
TMap< FOperatorFunctionID, FBinaryFunction > BinaryOps
void MapShortCircuit(FuncType InFunc)
TFunction< bool(const FExpressionNode &, const ContextType *Context) FShortCircuit)
bool ShouldShortCircuit(const FExpressionToken &Operator, const FExpressionToken &L, const ContextType *Context) const
void MapPostUnary(FuncType InFunc)
FExpressionResult ExecBinary(const FExpressionToken &Operator, const FExpressionToken &L, const FExpressionToken &R, const ContextType *Context) const
FExpressionResult ExecPostUnary(const FExpressionToken &Operator, const FExpressionToken &L, const ContextType *Context) const
void MapBinary(FuncType InFunc)
TFunction< FExpressionResult(const FExpressionNode &, const ContextType *Context) FUnaryFunction)
TMap< FOperatorFunctionID, FShortCircuit > BinaryShortCircuits
TMap< FOperatorFunctionID, FUnaryFunction > PreUnaryOps
TFunction< FExpressionResult(const FExpressionNode &, const FExpressionNode &, const ContextType *Context) FBinaryFunction)
void MapPreUnary(FuncType InFunc)