示例#1
0
        /// <summary>
        /// Insert operation in a operation tree using priorities
        /// </summary>
        /// <param name="lastOperation">Previous builded operation</param>
        /// <param name="operation">Current operation</param>
        /// <param name="rootOperation">Root operation of a tree</param>
        private void InsertOperationInTree <T>(ref OperationElement lastOperation,
                                               ref T operation,
                                               ref OperationElement rootOperation)
            where T : OperationElement
        {
            if (operation.Priority > lastOperation.Priority ||
                (operation.OperationName == lastOperation.OperationName &&
                 !OperationPriority.IsCompareToThisAsLessPriority[operation.OperationName]))
            {
                operation.SetChild(0, lastOperation.Child(1));

                lastOperation.SetChild(1, operation);
            }
            else
            {
                if (lastOperation.Parent() != null)
                {
                    OperationElement parentOperation = (OperationElement)lastOperation.Parent();
                    InsertOperationInTree(ref parentOperation, ref operation, ref rootOperation);
                }
                else
                {
                    operation.SetChild(0, lastOperation);
                    rootOperation = lastOperation = operation;
                }
            }
        }
示例#2
0
 /// <summary>
 /// Takes value and insert it in a operation
 /// </summary>
 /// <param name="operation">Used operation</param>
 /// <param name="value">Used value</param>
 /// <param name="right">If true a value will be inserted as right operand, false - as left</param>
 private void InsertValInTree(OperationElement operation, ValueElement value, bool right = true)
 {
     if (right)
     {
         if (operation.HasRightOperand)
         {
             if (operation.Child(1) == null)
             {
                 operation.SetChild(1, value);
             }
             else
             {
                 Compilation.WriteError("Operation '" + operation.OperationName +
                                        "' already has right operand", value.Line);
             }
         }
         else
         {
             Compilation.WriteError("Operation '" + operation.OperationName +
                                    "' hasn't right operand", value.Line);
         }
     }
     else
     {
         if (operation.HasLeftOperand)
         {
             if (operation.Child(0) == null)
             {
                 operation.SetChild(0, value);
             }
             else
             {
                 Compilation.WriteError("Operation '" + operation.OperationName +
                                        "' already has left operand", value.Line);
             }
         }
         else
         {
             Compilation.WriteError("Operation '" + operation.OperationName +
                                    "' hasn't left operand", value.Line);
         }
     }
 }
示例#3
0
        /// <summary>
        /// Build expression element
        /// </summary>
        /// <param name="lexemes">List of lexemes</param>
        /// <param name="pos">Position of current parsed lexeme</param>
        /// <param name="endPos">Position at which function breaks. Pass -1 to parse until the end</param>
        /// <param name="flags">Control flags. ExpressionFlags.None to ignore all flags</param>
        /// <param name="elem"></param>
        /// <returns>Position of a next lexeme</returns>
        private int ParseExpression(List <Lexeme> lexemes, int pos, int endPos,
                                    ExpressionFlags flags,
                                    out ValueElement elem)
        {
            OperationElement lastOperation  = null;
            OperationElement rootOperation  = null;
            ValueElement     lastValElement = null;

            bool breakCycle = false;

            if (endPos == -1)
            {
                endPos = lexemes.Count;
            }

            for (int end = endPos; !breakCycle && pos < end;)
            {
                var currentLexeme = lexemes[pos];

                switch (currentLexeme.Source)
                {
                case ")":
                case ";":
                case "{":
                case "}":
                    breakCycle = true;
                    continue;

                case ",":
                    Compilation.WriteError("Unexpected symbol: ','." +
                                           "Did you forget '(' ?\nExample: '( SYMBOLS, SYMBOLS )'.",
                                           lexemes[pos].Line);
                    continue;

                case "+":
                case "-":
                case "*":
                case "/":
                case "^":
                case "=":
                {
                    if (lastValElement == null && lastOperation == null)
                    {
                        if (lexemes[pos].Source == "-")
                        {
                            rootOperation = lastOperation = new UnaryMinusElement();
                            ++pos;
                            continue;
                        }
                        else
                        {
                            Compilation.WriteError("Expected value or expression before '"
                                                   + lexemes[pos].Source + "'", lexemes[pos].Line);
                        }
                    }

                    OperationElement operation = null;
                    switch (lexemes[pos].Source)
                    {
                    case "+":
                        operation = new BinaryPlusElement();
                        break;

                    case "-":
                        operation = new BinaryMinusElement();
                        break;

                    case "*":
                        operation = new BinaryMultiplicationElement();
                        break;

                    case "/":
                        operation = new BinaryDivisionElement();
                        break;

                    case "^":
                        operation = new BinaryExponentiationElement();
                        break;

                    case "=":
                    {
                        operation = new CopyElement();

                        if (lastValElement != null)
                        {
                            if (!(lastValElement is MultipleValElement))
                            {
                                var multiple = new MultipleValElement();
                                multiple.AddValue(lastValElement);
                                lastValElement = multiple;
                            }
                        }
                        else
                        {
                            if (lastOperation != null)
                            {
                                var valElem = lastOperation.Child(1);
                                if (!(valElem is MultipleValElement))
                                {
                                    var multiple = new MultipleValElement();
                                    multiple.AddValue((ValueElement)valElem);

                                    lastOperation.SetChild(1, valElem);
                                }
                            }
                            else
                            {
                                Compilation.WriteError("Expected value before '='", -1);
                            }
                        }
                    }
                    break;

                    default:
                        Compilation.WriteCritical("BUG: Unknown operator passed through the switch");
                        break;
                    }

                    if (lastOperation == null)
                    {
                        operation.SetChild(0, lastValElement);
                        lastValElement = null;
                        rootOperation  = operation;
                    }
                    else
                    {
                        InsertOperationInTree(ref lastOperation, ref operation, ref rootOperation);
                    }

                    lastOperation = operation;
                }
                    ++pos;
                    break;

                default:
                    pos = ParseExpressionValue(lexemes, pos, flags | ExpressionFlags.AllowDefaultValue
                                               & (~ExpressionFlags.OperationRequired),
                                               out lastValElement);
                    if (lastValElement == null)
                    {
                        if (!flags.HasFlag(ExpressionFlags.AllowAutoDefault))
                        {
                            Compilation.WriteError("Unknown symbol: '" + currentLexeme.Source + "'.",
                                                   currentLexeme.Line);
                        }
                        else     //used default keyword. Caller have to find result
                        {
                            elem = null;
                            return(pos);
                        }
                    }
                    else
                    {
                        if (lastOperation != null)
                        {
                            InsertValInTree(lastOperation, lastValElement);
                            lastValElement = null;
                        }
                    }
                    break;
                }
            }

            if (rootOperation == null)
            {
                if (flags.HasFlag(ExpressionFlags.OperationRequired) && !(lastValElement is FunctionCallElement))
                {
                    Compilation.WriteError("Expression must contain at least one operator", lexemes[pos].Line);
                }
                if (lastValElement == null)
                {
                    Compilation.WriteError("No operation or value in expression", lexemes[pos].Line);
                }
                elem = lastValElement;
            }
            else
            {
                elem = rootOperation;
            }

            return(pos);
        }