예제 #1
0
        public List <NovelInstruction> ParseExpression(string text)
        {
            //Trim the expression
            text = text.Trim();

            //Create empty expression object
            NovelExpression novelExpression = new NovelExpression();

            //Declare instructions
            List <NovelInstruction> instructions = new List <NovelInstruction>();

            //For RPN algorithm purpose
            string output = "";
            string buffer = "";

            for (int i = 0; i < text.Length; i++)
            {
                //Check if the i is pointing at operator name
                var operatorIndex = IsOperator(text, i);

                //operatorIndex = -1 means that its regular character
                if (operatorIndex >= 0)
                {
                    //Build expression here based on whats in buffer
                    if (!buffer.Equals(""))
                    {
                        if (IsDeclaredVariable(buffer))
                        {
                            buffer = buffer.Substring(3);

                            if (!Variables.ContainsVariable(buffer))
                            {
                                instructions.Add(new NovelExpandStack(1));
                                Variables.AddVaraible(buffer);
                            }
                            //TODO functions name
                            else
                            {
                                throw new NovelException("Variable or function name " + buffer + " already exists.", ParsedFile, ParsedLine);
                            }
                        }

                        //Handle the operands
                        novelExpression = HandleOperand(novelExpression, buffer);

                        //Push variable to the output
                        output += buffer;
                        buffer  = "";
                    }

                    //Get the new operator
                    var op = Operators[operatorIndex];

                    //Parentheses close operator
                    if (op is NovelCloseCurvedParenthesesOperator)
                    {
                        //Pop all operators till (
                        while (OperatorStack.Count() > 0)
                        {
                            var opFromStack = OperatorStack.Pop();
                            if (opFromStack is NovelOpenCurvedParenthesesOperator)
                            {
                                var parentheses = parenthesesType.Pop();

                                if (parentheses == ParenthesesType.Function)
                                {
                                    novelExpression.Term.Add(new NovelFunctionEndOperator());
                                }

                                break;
                            }
                            else
                            {
                                if (!(opFromStack is NovelOpenCurvedParenthesesOperator ||
                                      opFromStack is NovelCloseCurvedParenthesesOperator))
                                {
                                    novelExpression.Term.Add(opFromStack);
                                }
                            }
                        }
                    }
                    //If every other operator
                    else
                    {
                        //Iteratore over OperatorStack
                        while (OperatorStack.Count() > 0)
                        {
                            //If priority of new operator is lower or equal pop stack operators
                            //
                            if (op.GetPriority() <= OperatorStack.First().GetPriority() &&
                                !(op is NovelOpenCurvedParenthesesOperator))
                            {
                                var opFromStack = OperatorStack.Pop();

                                if (!(opFromStack is NovelOpenCurvedParenthesesOperator ||
                                      opFromStack is NovelCloseCurvedParenthesesOperator))
                                {
                                    novelExpression.Term.Add(opFromStack);
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    //Now put the operator on the stack if not close curved
                    if (!(op is NovelCloseCurvedParenthesesOperator))
                    {
                        //If previous term part was function call
                        if (novelExpression.Term.Count >= 1 &&
                            op is NovelOpenCurvedParenthesesOperator &&
                            novelExpression.Term[novelExpression.Term.Count - 1] is NovelExpressionFunctionCall)
                        {
                            parenthesesType.Push(ParenthesesType.Function);
                            novelExpression.Term.Add(new NovelFunctionStartOperator());
                        }
                        //If normal paretheses
                        else if (op is NovelOpenCurvedParenthesesOperator)
                        {
                            parenthesesType.Push(ParenthesesType.Normal);
                        }

                        OperatorStack.Push(op);
                    }

                    //Move pointer by a length of operator
                    i += op.GetName().Length - 1;
                }
                //If its not an operator
                else
                {
                    if (text[i].Equals(' '))
                    {
                        continue;
                    }
                    else if (text[i].Equals('\t'))
                    {
                        continue;
                    }
                    else if (text[i].Equals('\r'))
                    {
                        continue;
                    }
                    else if (text[i].Equals('\n'))
                    {
                        continue;
                    }

                    //If its a quote
                    if (text[i].Equals('\"'))
                    {
                        int len = text.IndexOf('\"', i + 1) - i + 1;
                        buffer += text.Substring(i, len);
                        i      += len - 1;
                    }
                    //If its not add single character
                    else
                    {
                        buffer += text[i];
                    }
                }
            }

            //Empty buffer first
            if (!buffer.Equals(""))
            {
                novelExpression = HandleOperand(novelExpression, buffer);
            }

            //Empty operator stack
            while (OperatorStack.Count() > 0)
            {
                var opFromStack = OperatorStack.Pop();
                if (!(opFromStack is NovelOpenCurvedParenthesesOperator ||
                      opFromStack is NovelCloseCurvedParenthesesOperator))
                {
                    novelExpression.Term.Add(opFromStack);
                }
            }

            Variables.AddScope();
            int reservedVariables = Variables.GetStackVariables();

            while (novelExpression.Term.Count > 0)
            {
                novelExpression = UnfoldOperations(novelExpression, ref instructions);
                novelExpression = UnfoldArguments(novelExpression, ref instructions);
                //For single variables or literals
                if (novelExpression.Term.Count == 1)
                {
                    var newExpression = new NovelExpression();
                    newExpression.Term.Add(novelExpression.Term[0]);
                    instructions.Add(newExpression);
                    novelExpression.Term.Clear();
                }
            }

            //How many of temporary variables expression has
            reservedVariables = Variables.GetStackVariables() - reservedVariables;

            //Shrink stack to remove them
            if (reservedVariables > 0)
            {
                instructions.Add(new NovelExpandStack(-reservedVariables));
            }

            Variables.RemoveScope();

            foreach (var instruction in instructions)
            {
                string buff = "";
                buff += " " + instruction;
                Console.WriteLine(buff);
            }
            Console.WriteLine("");

            return(instructions);
        }