Beispiel #1
0
        /// <summary>
        /// Returns a compiled expression for specified source string.
        /// </summary>
        public CompiledExpression Compile(PreparedExpression preparedExpression)
        {
            if (preparedExpression == null)
            {
                throw new ArgumentNullException("preparedExpression");
            }
            //
            OperationsStack operationsStack = new OperationsStack(operationsRegistry);

            //
            for (int itemIndex = 0; itemIndex < preparedExpression.PreparedExpressionItems.Count; itemIndex++)
            {
                PreparedExpressionItem item = preparedExpression.PreparedExpressionItems[itemIndex];
                // If constant or variable - add to result
                if (item.Kind == PreparedExpressionItemKind.Constant)
                {
                    operationsStack.PushConstant(item.Constant);
                }
                if (item.Kind == PreparedExpressionItemKind.Variable)
                {
                    operationsStack.PushVariable(item.VariableName);
                }
                // If delimiter
                if (item.Kind == PreparedExpressionItemKind.Delimiter)
                {
                    operationsStack.PushDelimiter(item.DelimiterKind);
                }
                // Signature (operator signature / part of signature / function)
                if (item.Kind == PreparedExpressionItemKind.Signature)
                {
                    List <Operation> operations = new List <Operation>(operationsRegistry.GetOperationsUsingSignature(item.Signature));
                    operations.Sort(new Comparison <Operation>(compareOperationsByOperandsCount));
                    //
                    for (int i = 0; i < operations.Count; i++)
                    {
                        Operation operation = operations[i];
                        // Operator
                        if (operation.Kind == OperationKind.Operator)
                        {
                            // Unary operator
                            if (operation.OperandsCount == 1)
                            {
                                // If operator placed at the start of subexpression
                                if ((itemIndex == 0) ||
                                    ((itemIndex > 0) && (preparedExpression.PreparedExpressionItems[itemIndex - 1].Kind == PreparedExpressionItemKind.Delimiter) && (preparedExpression.PreparedExpressionItems[itemIndex - 1].DelimiterKind == DelimiterKind.OpeningBrace) || (preparedExpression.PreparedExpressionItems[itemIndex - 1].DelimiterKind == DelimiterKind.Comma)))
                                {
                                    //
                                    operationsStack.PushUnaryOperator(operation);
                                    break;
                                }
                            }
                            // Binary operator
                            if (operation.OperandsCount == 2)
                            {
                                operationsStack.PushBinaryOperator(operation);
                                break;
                            }
                            // Ternary and more
                            if (operation.OperandsCount > 2)
                            {
                                int partNumber = 0;
                                for (int k = 0; k < operation.Signature.Length; k++)
                                {
                                    if (operation.Signature[k] == item.Signature)
                                    {
                                        partNumber = k + 1;
                                        break;
                                    }
                                }
                                // If it is start part in signature
                                if (partNumber == 1)
                                {
                                    operationsStack.PushComplexOperatorFirstSignature(operation);
                                    break;
                                }
                                //
                                operationsStack.PushComplexOperatorNonFirstSignature(operation, partNumber);
                                break;
                            }
                        }
                        // Function
                        if (operation.Kind == OperationKind.Function)
                        {
                            operationsStack.PushFunction(operation);
                            break;
                        }
                    }
                }
            }
            //
            operationsStack.DoFinalFlush();
            //
            CompiledExpression res = operationsStack.GetResult();

            if (!isCompiledExpressionStackBalanced(res))
            {
                throw new CompilerSyntaxException("Operands disbalance detected.");
            }
            return(res);
        }
Beispiel #2
0
        /// <summary>
        /// Prepares source string for compilation.
        /// </summary>
        public PreparedExpression Parse(string sourceString)
        {
            if (sourceString == null)
            {
                throw new ArgumentNullException("sourceString");
            }
            if (sourceString.Length == 0)
            {
                throw new ArgumentException("String is empty.", "sourceString");
            }
            // Signatures lenghts
            int[] lens = _OperationsRegistry.SignaturesLens;

            List <PreparedExpressionItem> res = new List <PreparedExpressionItem>();
            bool operandStarted    = false;
            int  operandStartIndex = 0;

            for (int i = 0; i < sourceString.Length; i++)
            {
                PreparedExpressionItem additionalItem = null;
                // Check for delimiters
                if ((sourceString[i] == '(') || (sourceString[i] == ')') || (sourceString[i] == ','))
                {
                    // Storing delimiter
                    DelimiterKind delimiterKind = new DelimiterKind();
                    switch (sourceString[i])
                    {
                    case '(':
                    {
                        delimiterKind = DelimiterKind.OpeningBrace;
                        break;
                    }

                    case ')':
                    {
                        delimiterKind = DelimiterKind.ClosingBrace;
                        break;
                    }

                    case ',':
                    {
                        delimiterKind = DelimiterKind.Comma;
                        break;
                    }
                    }
                    additionalItem = new PreparedExpressionItem(PreparedExpressionItemKind.Delimiter, delimiterKind);
                }
                // If not found, check for signatures, from max length to min
                if (additionalItem == null)
                {
                    for (int j = lens.Length - 1; j >= 0; j--)
                    {
                        if (i + lens[j] <= sourceString.Length)
                        {
                            // If signature found
                            if (_OperationsRegistry.IsSignatureDefined(sourceString.Substring(i, lens[j])))
                            {
                                // Storing signature
                                additionalItem = new PreparedExpressionItem(PreparedExpressionItemKind.Signature, sourceString.Substring(i, lens[j]));
                                break;
                            }
                        }
                    }
                }
                // If not found, working with operand
                if (additionalItem == null)
                {
                    if (!operandStarted)
                    {
                        operandStarted    = true;
                        operandStartIndex = i;
                    }
                }
                else
                {
                    // NOTE: Duplicate code
                    // Storing operand (constant or variable)
                    if (operandStarted)
                    {
                        string operandString = sourceString.Substring(operandStartIndex, i - operandStartIndex);
                        double constant;
                        if (Double.TryParse(operandString, System.Globalization.NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out constant))
                        {
                            res.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Constant, constant));
                        }
                        else
                        {
                            if (!IsValidVariableName(operandString))
                            {
                                throw new CompilerSyntaxException(String.Format("{0} is not valid variable identifier.", operandString));
                            }

                            res.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Variable, operandString));
                        }
                        operandStarted = false;
                    }
                    // Delayed storing a delimiter or signature
                    res.Add(additionalItem);
                    // If additionalItem was a signature, we should add correct i index according to signature lenght
                    if (additionalItem.Kind == PreparedExpressionItemKind.Signature)
                    {
                        i += additionalItem.Signature.Length - 1;
                    }
                }
            }
            // Storing operand (constant or variable)
            if (operandStarted)
            {
                string operandString = sourceString.Substring(operandStartIndex);
                double constant;
                if (Double.TryParse(operandString.Replace('.', ','), out constant))
                {
                    res.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Constant, constant));
                }
                else
                {
                    if (!IsValidVariableName(operandString))
                    {
                        throw new CompilerSyntaxException(String.Format("{0} is not valid variable identifier.", operandString));
                    }

                    res.Add(new PreparedExpressionItem(PreparedExpressionItemKind.Variable, operandString));
                }
            }

            return(new PreparedExpression(res));
        }