/// <summary> /// Returns true if the given pre-processed expression evaluates to true. /// </summary> /// <param name="preprocExpression"></param> /// <param name="definedFunc"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public static bool IsExpressionTrue(string preprocExpression, Func<string, int> definedFunc = null) { preprocExpression = preprocExpression.Trim().ToLower(); preprocExpression = ReplaceDefinedFunction(preprocExpression, definedFunc, out bool usedDefinedProc); if (ExpressionResults.ContainsKey(preprocExpression)) { return ExpressionResults[preprocExpression]; } if (CanEvaluateFromString(preprocExpression, out bool result)) { if (!usedDefinedProc) { // defined() depends on the current context (which var is defined at this line), so don't store. ExpressionResults.Add(preprocExpression, result); } return result; } if (!string.IsNullOrEmpty(ProEnvironment.Current?.ProwinPath)) { var dlcPath = Path.Combine(Path.GetDirectoryName(ProEnvironment.Current.ProwinPath) ?? "", ".."); using (var ev = new UoePreprocessedExpressionEvaluator(dlcPath)) { result = ev.IsTrue(preprocExpression); ExpressionResults.Add(preprocExpression, result); return result; } } throw new Exception($"Could not evaluate expression: {preprocExpression}."); }
/// <summary> /// Matches a &IF expression &THEN pre-processed statement (extractes the evaluated expression in BlockDescription) /// </summary> private ParsedScopePreProcIfBlock CreateParsedIfEndIfPreProc(Token ifToken, bool lastPreProcIfBlockWasTrue) { List <Token> expressionTokens; StringBuilder expression = new StringBuilder(); bool expressionResult; // do we need to extract an expression from this IF/ELSEIF? (or is it an ELSE) if (ifToken.Value.ToLower().EndsWith("if")) { expressionTokens = new List <Token>(); int i = 0; do { i++; // need to replace in case we use for instance a {&var} in a scope-define value ReplaceIncludeAndPreprocVariablesAhead(i + 1); var token = PeekAt(i); if (token is TokenComment) { continue; } if (token is TokenEof) { break; } if (token is TokenPreProcDirective) { break; } expressionTokens.Add(token); } while (true); // we directly set the new token position there (it will be just 1 token before the &THEN) _tokenPos += i - 1; AddLineInfo(PeekAt(0)); // since we didn't use MoveNext we also manually replace the includes ahead ReplaceIncludeAndPreprocVariablesAhead(2); foreach (var token in expressionTokens) { expression.Append(token.Value); } try { expressionResult = !lastPreProcIfBlockWasTrue && UoePreprocessedExpressionEvaluator.IsExpressionTrue(expression.ToString(), s => { return(_parsedIncludes[ifToken.OwnerNumber].GetScopedPreProcVariableDefinedLevel(s)); }); } catch (Exception e) { ErrorHandler.LogError(e); expressionResult = false; } } else { // it's an &ELSE expressionResult = !lastPreProcIfBlockWasTrue; } var newIf = new ParsedScopePreProcIfBlock(ifToken.Value, ifToken) { EvaluatedExpression = expression.ToString().Trim(), ExpressionResult = expressionResult }; AddParsedItem(newIf, ifToken.OwnerNumber); return(newIf); }