Example #1
0
        public void Add(IToken tok)
        {
            m_vRPN.Add(tok);
            if (tok.AsIValue() != null)
            {
                m_nStackPos++;
            }
            else if (tok.AsICallback() != null)
            {
                ICallback pFun = tok.AsICallback();
                Global.MUP_VERIFY(pFun != null);
                m_nStackPos -= pFun.GetArgsPresent() - 1;
            }

            Global.MUP_VERIFY(m_nStackPos >= 0);
            m_nMaxStackPos = Math.Max(m_nStackPos, m_nMaxStackPos);
        }
Example #2
0
        //---------------------------------------------------------------------------

        /*  Simulates the call of a parser function with its corresponding arguments.
         *    \param a_stOpt The operator stack
         *    \param a_stVal The value stack
         *    \param a_iArgCount The number of function arguments
         */
        private void ApplyFunc(Stack <IToken> a_stOpt, int a_iArgCount)
        {
            if (!a_stOpt.Any())
            {
                return;
            }

            IToken    tok  = a_stOpt.Pop();
            ICallback pFun = tok.AsICallback();

            int iArgCount = (pFun.GetArgc() >= 0) ? pFun.GetArgc() : a_iArgCount;

            if (pFun.GetArgc() == -1)
            {
                tok = pFun.SetNumArgsPresent(iArgCount);
            }

            m_nPos -= (iArgCount - 1);
            m_rpn.Add(tok);
        }
Example #3
0
        //---------------------------------------------------------------------------
        private void CreateRPN()
        {
            if (string.IsNullOrEmpty(m_pTokenReader.GetExpr()))
            {
                Error(EErrorCodes.ecUNEXPECTED_EOF, 0);
            }

            // The Stacks take the ownership over the tokens
            Stack <IToken> stOpt = new Stack <IToken>();
            Stack <int>    stArgCount = new Stack <int>();
            Stack <int>    stIdxCount = new Stack <int>();
            IToken         pTok = null, pTokPrev;
            Value          val;

            ReInit();

            for (; ;)
            {
                pTokPrev = pTok;
                pTok     = m_pTokenReader.ReadNextToken();

                ECmdCode eCmd = pTok.GetCode();
                switch (eCmd)
                {
                case ECmdCode.cmVAL:
                    m_nPos++;
                    m_rpn.Add(pTok);
                    break;

                case ECmdCode.cmCBC:
                case ECmdCode.cmIC:
                {
                    ECmdCode eStarter = eCmd - 1;
                    Global.MUP_VERIFY(eStarter == ECmdCode.cmCBO || eStarter == ECmdCode.cmIO);

                    // The argument count for parameterless functions is zero
                    // by default an opening bracket sets parameter count to 1
                    // in preparation of arguments to come. If the last token
                    // was an opening bracket we know better...
                    if (pTokPrev != null && pTokPrev.GetCode() == eStarter)
                    {
                        stArgCount.Push(stArgCount.Pop() - 1);
                    }

                    ApplyRemainingOprt(stOpt);

                    // if opt is "]" and opta is "[" the bracket content has been evaluated.
                    // Now check whether there is an index operator on the stack.
                    if (stOpt.Any() && stOpt.Peek().GetCode() == eStarter)
                    {
                        //
                        // Find out how many dimensions were used in the index operator.
                        //
                        int iArgc = stArgCount.Pop();
                        stOpt.Pop();         // Take opening bracket from stack

                        ICallback PoprtIndex = pTok.AsICallback();
                        Global.MUP_VERIFY(PoprtIndex != null);

                        pTok = PoprtIndex.SetNumArgsPresent(iArgc);
                        m_rpn.Add(pTok);

                        // If this is an index operator there must be something else in the register (the variable to index)
                        Global.MUP_VERIFY(eCmd != ECmdCode.cmIC || m_nPos >= iArgc + 1);

                        // Reduce the index into the value registers accordingly
                        m_nPos -= iArgc;

                        if (eCmd == ECmdCode.cmCBC)
                        {
                            ++m_nPos;
                        }
                    }         // if opening index bracket is on Peek of operator stack
                }
                break;

                case ECmdCode.cmBC:
                {
                    // The argument count for parameterless functions is zero
                    // by default an opening bracket sets parameter count to 1
                    // in preparation of arguments to come. If the last token
                    // was an opening bracket we know better...
                    if (pTokPrev != null && pTokPrev.GetCode() == ECmdCode.cmBO)
                    {
                        stArgCount.Push(stArgCount.Pop() - 1);
                    }

                    ApplyRemainingOprt(stOpt);

                    // if opt is ")" and opta is "(" the bracket content has been evaluated.
                    // Now its time to check if there is either a function or a sign pending.
                    // - Neither the opening nor the closing bracket will be pushed back to
                    //   the operator stack
                    // - Check if a function is standing in front of the opening bracket,
                    //   if so evaluate it afterwards to apply an infix operator.
                    if (stOpt.Any() && stOpt.Peek().GetCode() == ECmdCode.cmBO)
                    {
                        //
                        // Here is the stuff to evaluate a function token
                        //
                        int iArgc = stArgCount.Pop();

                        stOpt.Pop();         // Take opening bracket from stack
                        if (!stOpt.Any())
                        {
                            break;
                        }

                        if ((stOpt.Peek().GetCode() != ECmdCode.cmFUNC) && (stOpt.Peek().GetCode() != ECmdCode.cmOPRT_INFIX))
                        {
                            break;
                        }

                        ICallback pFun = stOpt.Peek().AsICallback();

                        if (pFun.GetArgc() != -1 && iArgc > pFun.GetArgc())
                        {
                            Error(EErrorCodes.ecTOO_MANY_PARAMS, pTok.GetExprPos(), pFun);
                        }

                        if (iArgc < pFun.GetArgc())
                        {
                            Error(EErrorCodes.ecTOO_FEW_PARAMS, pTok.GetExprPos(), pFun);
                        }

                        // Apply function, if present
                        if (stOpt.Any() &&
                            stOpt.Peek().GetCode() != ECmdCode.cmOPRT_INFIX &&
                            stOpt.Peek().GetCode() != ECmdCode.cmOPRT_BIN)
                        {
                            ApplyFunc(stOpt, iArgc);
                        }
                    }
                }
                break;

                case ECmdCode.cmELSE:
                    ApplyRemainingOprt(stOpt);
                    m_rpn.Add(pTok);
                    stOpt.Push(pTok);
                    break;

                case ECmdCode.cmSCRIPT_NEWLINE:
                    ApplyRemainingOprt(stOpt);
                    m_rpn.AddNewline(pTok, m_nPos);
                    stOpt.Clear();
                    m_nPos = 0;
                    break;

                case ECmdCode.cmARG_SEP:
                    if (!stArgCount.Any())
                    {
                        Error(EErrorCodes.ecUNEXPECTED_COMMA, m_pTokenReader.GetPos() - 1);
                    }

                    stArgCount.Push(stArgCount.Pop() + 1);

                    ApplyRemainingOprt(stOpt);
                    break;

                case ECmdCode.cmEOE:
                    ApplyRemainingOprt(stOpt);
                    m_rpn.Finalise();
                    break;

                case ECmdCode.cmIF:
                case ECmdCode.cmOPRT_BIN:
                {
                    while (stOpt.Any() &&
                           stOpt.Peek().GetCode() != ECmdCode.cmBO &&
                           stOpt.Peek().GetCode() != ECmdCode.cmIO &&
                           stOpt.Peek().GetCode() != ECmdCode.cmCBO &&
                           stOpt.Peek().GetCode() != ECmdCode.cmELSE &&
                           stOpt.Peek().GetCode() != ECmdCode.cmIF)
                    {
                        IToken Poprt1 = stOpt.Peek();
                        IToken Poprt2 = pTok;
                        Global.MUP_VERIFY(Poprt1 != null && Poprt2 != null);
                        Global.MUP_VERIFY(Poprt1.AsIPrecedence() != null && Poprt2.AsIPrecedence() != null);

                        int nPrec1 = Poprt1.AsIPrecedence().GetPri(),
                            nPrec2 = Poprt2.AsIPrecedence().GetPri();

                        if (Poprt1.GetCode() == Poprt2.GetCode())
                        {
                            // Deal with operator associativity
                            EOprtAsct eOprtAsct = Poprt1.AsIPrecedence().GetAssociativity();
                            if ((eOprtAsct == EOprtAsct.oaRIGHT && (nPrec1 <= nPrec2)) ||
                                (eOprtAsct == EOprtAsct.oaLEFT && (nPrec1 < nPrec2)))
                            {
                                break;
                            }
                        }
                        else if (nPrec1 < nPrec2)
                        {
                            break;
                        }

                        // apply the operator now
                        // (binary operators are identic to functions with two arguments)
                        ApplyFunc(stOpt, 2);
                    }         // while ( ... )

                    if (pTok.GetCode() == ECmdCode.cmIF)
                    {
                        m_rpn.Add(pTok);
                    }

                    stOpt.Push(pTok);
                }
                break;

                //
                //  Postfix Operators
                //
                case ECmdCode.cmOPRT_POSTFIX:
                    Global.MUP_VERIFY(m_nPos != 0);
                    m_rpn.Add(pTok);
                    break;

                case ECmdCode.cmCBO:
                case ECmdCode.cmIO:
                case ECmdCode.cmBO:
                    stOpt.Push(pTok);
                    stArgCount.Push(1);
                    break;

                //
                // Functions
                //
                case ECmdCode.cmOPRT_INFIX:
                case ECmdCode.cmFUNC:
                {
                    ICallback pFunc = pTok.AsICallback();
                    Global.MUP_VERIFY(pFunc != null);
                    stOpt.Push(pTok);
                }
                break;

                default:
                    Error(EErrorCodes.ecINTERNAL_ERROR);
                    break;
                } // switch Code

                if (s_bDumpStack)
                {
                    StackDump(stOpt);
                }

                if (pTok.GetCode() == ECmdCode.cmEOE)
                {
                    break;
                }
            } // for (all tokens)

            if (s_bDumpRPN)
            {
                m_rpn.AsciiDump();
            }

            if (m_nPos > 1)
            {
                Error(EErrorCodes.ecUNEXPECTED_COMMA, -1);
            }
        }