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); }
//--------------------------------------------------------------------------- /* 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); }
//--------------------------------------------------------------------------- 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); } }