Ejemplo n.º 1
0
            static string?ReplaceFunctionsLocal(
                string source,
                string openParenthesisSymbol,
                string closeParenthesisSymbol,
                string parameterSeparatorSymbol,
                Dictionary <string, ConstantNodeBase> constantsTableReference,
                Dictionary <string, string> reverseConstantsTableReference,
                Dictionary <string, ExpressionSymbol> symbolTableReference,
                Dictionary <string, string> reverseSymbolTableReference,
                LevelDictionary <Type, IConstantInterpreter> interpretersReference,
                IParameterRegistry parametersTableReference,
                string expressionSymbol,
                string[] allSymbolsSymbols)
            {
                var op  = -1;
                var opl = openParenthesisSymbol.Length;
                var cpl = closeParenthesisSymbol.Length;

                while (true)
                {
                    op = source.InvariantCultureIndexOf(
                        openParenthesisSymbol,
                        op + opl);

                    if (op == -1)
                    {
                        return(null);
                    }

                    if (op == 0)
                    {
                        continue;
                    }

                    var functionHeaderCheck = source.Substring(
                        0,
                        op);

                    if (allSymbolsSymbols.Any(
                            (
                                p,
                                check) => check.InvariantCultureEndsWith(p),
                            functionHeaderCheck))
                    {
                        continue;
                    }

                    var functionHeader = functionHeaderCheck.Split(
                        allSymbolsSymbols,
                        StringSplitOptions.None).Last();

                    var oop = source.InvariantCultureIndexOf(
                        openParenthesisSymbol,
                        op + opl);
                    var cp = source.InvariantCultureIndexOf(
                        closeParenthesisSymbol,
                        op + cpl);

                    while (oop < cp && oop != -1 && cp != -1)
                    {
                        oop = source.InvariantCultureIndexOf(
                            openParenthesisSymbol,
                            oop + opl);
                        cp = source.InvariantCultureIndexOf(
                            closeParenthesisSymbol,
                            cp + cpl);
                    }

                    if (cp == -1)
                    {
                        continue;
                    }

                    var arguments = source.Substring(
                        op + opl,
                        cp - op - opl);
                    var originalArguments = arguments;

                    var q = arguments;
                    while (q != null)
                    {
                        arguments = q;
                        q         = ReplaceFunctionsLocal(
                            q,
                            openParenthesisSymbol,
                            closeParenthesisSymbol,
                            parameterSeparatorSymbol,
                            constantsTableReference,
                            reverseConstantsTableReference,
                            symbolTableReference,
                            reverseSymbolTableReference,
                            interpretersReference,
                            parametersTableReference,
                            expressionSymbol,
                            allSymbolsSymbols);
                    }

                    var argPlaceholders = new List <string>();
                    foreach (var s in arguments.Split(
                                 new[] { parameterSeparatorSymbol },
                                 StringSplitOptions.RemoveEmptyEntries))
                    {
                        TablePopulationGenerator.PopulateTables(
                            s,
                            constantsTableReference,
                            reverseConstantsTableReference,
                            symbolTableReference,
                            reverseSymbolTableReference,
                            parametersTableReference,
                            interpretersReference,
                            expressionSymbol,
                            openParenthesisSymbol,
                            allSymbolsSymbols);

                        // We check whether or not this is actually a constant
                        argPlaceholders.Add(
                            ConstantsGenerator.CheckAndAdd(
                                constantsTableReference,
                                reverseConstantsTableReference,
                                interpretersReference,
                                expressionSymbol,
                                s) ?? (!parametersTableReference.Exists(s)
                                ? SymbolExpressionGenerator.GenerateSymbolExpression(
                                           symbolTableReference,
                                           reverseSymbolTableReference,
                                           s,
                                           false)
                                : s));
                    }

                    var functionCallBody =
                        $"{functionHeader}{openParenthesisSymbol}{string.Join(parameterSeparatorSymbol, argPlaceholders)}{closeParenthesisSymbol}";
                    var functionCallToReplace =
                        $"{functionHeader}{openParenthesisSymbol}{originalArguments}{closeParenthesisSymbol}";
                    var functionCallItem = SymbolExpressionGenerator.GenerateSymbolExpression(
                        symbolTableReference,
                        reverseSymbolTableReference,
                        functionCallBody,
                        true);

                    return(source.Replace(
                               functionCallToReplace,
                               functionCallItem));
                }
            }
    internal static void FormatParentheses(
        string openParenthesis,
        string closeParenthesis,
        string parameterSeparator,
        string[] allOperatorsInOrder,
        Dictionary <string, ExpressionSymbol> symbolTable,
        Dictionary <string, string> reverseSymbolTable)
    {
        var itemsToProcess = new List <string>();

        KeyValuePair <string, ExpressionSymbol> itemToProcess;

        // Select the first expression that hasn't already been parsed
        while ((itemToProcess = symbolTable.Where(
                    (
                        p,
                        itemsToProcessL1) => !itemsToProcessL1.Contains(p.Key) && !p.Value.IsFunctionCall,
                    itemsToProcess).FirstOrDefault()).Value != null)
        {
            try
            {
                FormatParenthesis(
                    itemToProcess.Key,
                    openParenthesis,
                    closeParenthesis,
                    parameterSeparator,
                    allOperatorsInOrder,
                    symbolTable,
                    reverseSymbolTable);
            }
            finally
            {
                itemsToProcess.Add(itemToProcess.Key);
            }
        }

        void FormatParenthesis(
            string key,
            string openParenthesisL1,
            string closeParenthesisL1,
            string parameterSeparatorL1,
            string[] allOperatorsInOrderL1,
            Dictionary <string, ExpressionSymbol> symbolTableL1,
            Dictionary <string, string> reverseSymbolTableL1)
        {
            ExpressionSymbol symbol = symbolTableL1[key];

            if (symbol.IsFunctionCall)
            {
                return;
            }

            var replacedPreviously = string.Empty;
            var replaced           = symbol.Expression;

            while (replaced != replacedPreviously)
            {
                symbolTableL1[key].Expression = replaced;
                replacedPreviously            = replaced;
                replaced = ReplaceParenthesis(
                    replaced,
                    openParenthesisL1,
                    closeParenthesisL1,
                    parameterSeparatorL1,
                    allOperatorsInOrderL1,
                    symbolTableL1,
                    reverseSymbolTableL1);
            }

            string ReplaceParenthesis(
                string?source,
                string openParenthesisL2,
                string closeParenthesisL2,
                string parameterSeparatorSymbolL2,
                string[] allOperatorsInOrderSymbolsL2,
                Dictionary <string, ExpressionSymbol> symbolTableL2,
                Dictionary <string, string> reverseSymbolTableL2)
            {
                if (string.IsNullOrWhiteSpace(source))
                {
                    return(string.Empty);
                }

                var src = source !;

                var openingParenthesisLocation = src.InvariantCultureIndexOf(
                    openParenthesisL2);
                var closingParenthesisLocation = src.InvariantCultureIndexOf(
                    closeParenthesisL2);

beginning:
                if (openingParenthesisLocation != -1)
                {
                    if (closingParenthesisLocation == -1)
                    {
                        throw new InvalidOperationException();
                    }

                    if (openingParenthesisLocation < closingParenthesisLocation)
                    {
                        var resultingSubExpression = ReplaceParenthesis(
                            src.Substring(openingParenthesisLocation + openParenthesisL2.Length),
                            openParenthesisL2,
                            closeParenthesisL2,
                            parameterSeparatorSymbolL2,
                            allOperatorsInOrderSymbolsL2,
                            symbolTableL2,
                            reverseSymbolTableL2);

                        if (openingParenthesisLocation == 0)
                        {
                            src = resultingSubExpression;
                        }
                        else
                        {
                            var expr4 = src.Substring(
                                0,
                                openingParenthesisLocation);

                            if (!allOperatorsInOrderSymbolsL2.Any(
                                    (
                                        p,
                                        expr4L1) => expr4L1.InvariantCultureEndsWith(p),
                                    expr4))
                            {
                                // We have a function call
#pragma warning disable HAA0603 // Delegate allocation from a method group - Unavoidable
                                var inx = allOperatorsInOrderSymbolsL2.Max(expr4.LastIndexOf);
#pragma warning restore HAA0603 // Delegate allocation from a method group
                                var expr5 = inx == -1 ? expr4 : expr4.Substring(inx);
                                var op1   = allOperatorsInOrderSymbolsL2.OrderByDescending(p => p.Length)
                                            .FirstOrDefault(
                                    (
                                        p,
                                        expr5L1) => expr5L1.InvariantCultureStartsWith(p),
                                    expr5);
                                var expr6 = op1 == null ? expr5 : expr5.Substring(op1.Length);

                                // ReSharper disable once AssignmentIsFullyDiscarded - We're interested only in having the symbol in the table, and nothing more
                                _ = SymbolExpressionGenerator.GenerateSymbolExpression(
                                    symbolTableL2,
                                    reverseSymbolTableL2,
                                    $"{expr6}{openParenthesisL2}item{(symbolTableL2.Count - 1).ToString(CultureInfo.InvariantCulture)}{closeParenthesisL2}",
                                    false);

                                expr4 = expr6 == expr4
                                    ? string.Empty
                                    : expr4.Substring(
                                    0,
                                    expr4.Length - expr6.Length);

                                resultingSubExpression = resultingSubExpression.Replace(
                                    $"item{(symbolTableL2.Count - 1).ToString(CultureInfo.InvariantCulture)}",
                                    $"item{symbolTableL2.Count.ToString(CultureInfo.InvariantCulture)}");
                            }

                            src = $"{expr4}{resultingSubExpression}";
                        }

                        openingParenthesisLocation = src.InvariantCultureIndexOf(
                            openParenthesisL2);
                        closingParenthesisLocation = src.InvariantCultureIndexOf(
                            closeParenthesisL2);

                        goto beginning;
                    }

                    return(ProcessSubExpression(
                               closingParenthesisLocation,
                               closeParenthesisL2,
                               src,
                               parameterSeparatorSymbolL2,
                               symbolTableL2,
                               reverseSymbolTableL2));
                }

                if (closingParenthesisLocation == -1)
                {
                    return(src);
                }

                return(ProcessSubExpression(
                           closingParenthesisLocation,
                           closeParenthesisL2,
                           src,
                           parameterSeparatorSymbolL2,
                           symbolTableL2,
                           reverseSymbolTableL2));

                string ProcessSubExpression(
                    int cp,
                    string closeParenthesisL3,
                    string sourceL3,
                    string parameterSeparatorL3,
                    Dictionary <string, ExpressionSymbol> symbolTableL3,
                    Dictionary <string, string> reverseSymbolTableL3)
                {
                    var expr1 = sourceL3.Substring(
                        0,
                        cp);

                    string[] parameters = expr1.Split(
                        new[] { parameterSeparatorL3 },
                        StringSplitOptions.None);

                    var parSymbols = new List <string>(parameters.Length);

                    // ReSharper disable once LoopCanBeConvertedToQuery - We are looking for best-performance linearity here
                    foreach (var s in parameters)
                    {
                        parSymbols.Add(
                            SymbolExpressionGenerator.GenerateSymbolExpression(
                                symbolTableL3,
                                reverseSymbolTableL3,
                                s,
                                false));
                    }

                    var k = cp + closeParenthesisL3.Length;

                    return
                        ($"{string.Join(parameterSeparatorL3, parSymbols)}{(sourceL3.Length == k ? string.Empty : sourceL3.Substring(k))}");
                }
            }
        }
    }