internal IToken Store(IToken t, int token_pos) { m_eLastTokCode = t.GetCode(); t.SetExprPos(token_pos); m_vTokens.Add(t); return(t); }
public static string Dump(this IToken o, params object[] strz) { Global.MUP_VERIFY(strz.Length % 2 == 0); const char DELIM = ';'; var ss = new StringBuilder(); ss.Append($"{Global.g_sCmdCode[(int)o.GetCode()], -9}"); ss.Append($" [ addr = 0x{o.MemoryAddress()}"); for (int i = 0; i < strz.Length; i += 2) { ss.Append($"{DELIM} {strz[i]} = {strz[i + 1]}"); } ss.Append("]"); return(ss.ToString()); }
//--------------------------------------------------------------------------- /* Simulates the effect of the execution of an if-then-else block. */ private void ApplyIfElse(Stack <IToken> a_stOpt) { while (a_stOpt.Any() && a_stOpt.Peek().GetCode() == ECmdCode.cmELSE) { Global.MUP_VERIFY(a_stOpt.Any()); Global.MUP_VERIFY(m_nPos >= 3); Global.MUP_VERIFY(a_stOpt.Peek().GetCode() == ECmdCode.cmELSE); IToken opElse = a_stOpt.Pop(); IToken opIf = a_stOpt.Pop(); Global.MUP_VERIFY(opElse.GetCode() == ECmdCode.cmELSE); Global.MUP_VERIFY(opIf.GetCode() == ECmdCode.cmIF); // If then else hat 3 argumente und erzeugt einen rückgabewert (3-1=2) m_nPos -= 2; m_rpn.Add(new TokenIfThenElse(ECmdCode.cmENDIF)); } }
//--------------------------------------------------------------------------- private void ApplyRemainingOprt(Stack <IToken> stOpt) { while (stOpt.Any() && stOpt.Peek().GetCode() != ECmdCode.cmBO && stOpt.Peek().GetCode() != ECmdCode.cmIO && stOpt.Peek().GetCode() != ECmdCode.cmCBO && stOpt.Peek().GetCode() != ECmdCode.cmIF) { IToken op = stOpt.Peek(); switch (op.GetCode()) { case ECmdCode.cmOPRT_INFIX: case ECmdCode.cmOPRT_BIN: ApplyFunc(stOpt, 2); break; case ECmdCode.cmELSE: ApplyIfElse(stOpt); break; default: Error(EErrorCodes.ecINTERNAL_ERROR); break; } // switch operator token type } // While operator stack not empty }
//--------------------------------------------------------------------------- private IValue ParseFromRPN() { IValue[] pStack = m_vStackBuffer; if (m_rpn.GetSize() == 0) { // Passiert bei leeren strings oder solchen, die nur Leerzeichen enthalten ErrorContext err = new ErrorContext(); err.Expr = m_pTokenReader.GetExpr(); err.Errc = EErrorCodes.ecUNEXPECTED_EOF; err.Pos = 0; throw new ParserError(err); } IList <IToken> pRPN = m_rpn.GetData(); int j = 0; int sidx = -1; int lenRPN = m_rpn.GetSize(); for (int i = 0; i < lenRPN; ++i) { IToken pTok = pRPN[i]; ECmdCode eCode = pTok.GetCode(); switch (eCode) { case ECmdCode.cmSCRIPT_NEWLINE: sidx = -1; continue; case ECmdCode.cmVAL: { IValue pVal = (IValue)pTok; sidx++; Global.MUP_VERIFY(sidx < pStack.Length); pStack[sidx] = pVal; // m_vStackBuffer[sidx] = rVal; //if (pVal.IsVariable()) //{ // // m_vStackBuffer[sidx].Release(); // pStack[sidx] = pVal; //} //else //{ // ref IValue val = ref pStack[sidx]; // if (val.IsVariable()) // m_cache.CreateFromCache(out val); // val = pVal; //} } continue; case ECmdCode.cmIC: { j = 0; ICallback pIdxOprt = (ICallback)pTok; int nArgs = pIdxOprt.GetArgsPresent(); sidx -= nArgs - 1; Global.MUP_VERIFY(sidx >= 0); var arr = new IValue[nArgs + 1]; ref IValue val = ref pStack[--sidx]; Array.Copy(pStack, sidx, arr, 0, nArgs + 1); //int t = sidx + nArgs +1; //arr = new IValue[nArgs+1]; //if (t == 1) // arr[0] = m_vStackBuffer[sidx]; //else if (t != 0) //for (int k = sidx; k < t; k++) // arr[j++] = m_vStackBuffer[k]; pIdxOprt.Eval(ref val, arr); } continue;
//--------------------------------------------------------------------------- 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); } }