CompileResultType Compile(const TCHAR* InExpression, const FTokenDefinitions& InTokenDefinitions, const FExpressionGrammar& InGrammar) { TValueOrError<TArray<FExpressionToken>, FExpressionError> Result = Lex(InExpression, InTokenDefinitions); if (!Result.IsValid()) { return MakeError(Result.GetError()); } return Compile(MoveTemp(Result.GetValue()), InGrammar); }
FExpressionResult Evaluate(const TCHAR* InExpression, const FTokenDefinitions& InTokenDefinitions, const FExpressionGrammar& InGrammar, const IOperatorEvaluationEnvironment& InEnvironment) { TValueOrError<TArray<FCompiledToken>, FExpressionError> CompilationResult = Compile(InExpression, InTokenDefinitions, InGrammar); if (!CompilationResult.IsValid()) { return MakeError(CompilationResult.GetError()); } return Evaluate(CompilationResult.GetValue(), InEnvironment); }
void FTextFormatData::Compile_NoLock() { LexedExpression.Reset(); if (SourceType == ESourceType::Text) { SourceExpression = SourceText.ToString(); CompiledTextSnapshot = FTextSnapshot(SourceText); } CompiledExpressionType = FTextFormat::EExpressionType::Simple; BaseFormatStringLength = 0; FormatArgumentEstimateMultiplier = 1; TValueOrError<TArray<FExpressionToken>, FExpressionError> Result = ExpressionParser::Lex(*SourceExpression, FTextFormatter::Get().GetTextFormatDefinitions()); bool bValidExpression = Result.IsValid(); if (bValidExpression) { LexedExpression = Result.StealValue(); // Quickly make sure the tokens are valid (argument modifiers may only follow an argument token) for (int32 TokenIndex = 0; TokenIndex < LexedExpression.Num(); ++TokenIndex) { const FExpressionToken& Token = LexedExpression[TokenIndex]; if (const auto* Literal = Token.Node.Cast<TextFormatTokens::FStringLiteral>()) { BaseFormatStringLength += Literal->StringLen; } else if (auto* Escaped = Token.Node.Cast<TextFormatTokens::FEscapedCharacter>()) { BaseFormatStringLength += 1; } else if (const auto* ArgumentToken = Token.Node.Cast<TextFormatTokens::FArgumentTokenSpecifier>()) { CompiledExpressionType = FTextFormat::EExpressionType::Complex; if (LexedExpression.IsValidIndex(TokenIndex + 1)) { const FExpressionToken& NextToken = LexedExpression[TokenIndex + 1]; // Peek to see if the next token is an argument modifier if (const auto* ArgumentModifierToken = NextToken.Node.Cast<TextFormatTokens::FArgumentModifierTokenSpecifier>()) { int32 ArgModLength = 0; bool ArgModUsesFormatArgs = false; ArgumentModifierToken->TextFormatArgumentModifier->EstimateLength(ArgModLength, ArgModUsesFormatArgs); BaseFormatStringLength += ArgModLength; FormatArgumentEstimateMultiplier += (ArgModUsesFormatArgs) ? 1 : 0; ++TokenIndex; // walk over the argument token so that the next iteration will skip over the argument modifier continue; } } } else if (Token.Node.Cast<TextFormatTokens::FArgumentModifierTokenSpecifier>()) { // Unexpected argument modifier token! const FText ErrorSourceText = FText::FromString(Token.Context.GetString()); Result = MakeError(FExpressionError(FText::Format(LOCTEXT("UnexpectedArgumentModifierToken", "Unexpected 'argument modifier' token: {0} (token started at index {1})"), ErrorSourceText, Token.Context.GetCharacterIndex()))); bValidExpression = false; break; } } } if (!bValidExpression) { LexedExpression.Reset(); CompiledExpressionType = FTextFormat::EExpressionType::Invalid; UE_LOG(LogTextFormatter, Warning, TEXT("Failed to compile text format string '%s': %s"), *SourceExpression, *Result.GetError().Text.ToString()); } }