Ejemplo n.º 1
0
  //---------------------------------------------------------------------------
  const IValue& ParserXBase::ParseFromRPN() const
  {
    ptr_val_type *pStack = &m_vStackBuffer[0];
    const ptr_tok_type *pRPN = &(m_rpn.GetData()[0]);

    int sidx = -1;
    std::size_t lenRPN = m_rpn.GetSize();
    for (std::size_t i=0; i<lenRPN; ++i)
    {
      IToken *pTok = pRPN[i].Get();
      ECmdCode eCode = pTok->GetCode();

      switch (eCode)
      {
      case cmSCRIPT_NEWLINE:
           sidx = -1; //-= static_cast<TokenNewline*>(pTok)->GetStackOffset();
           m_nFinalResultIdx = 0;
           continue;

      case cmVAR:
           {
             sidx++;
             assert(sidx<(int)m_vStackBuffer.size());
             pStack[sidx].Reset(static_cast<IValue*>(pTok));
           }
           continue;

      case cmVAL:
           {
             sidx++;
             assert(sidx<(int)m_vStackBuffer.size());
             ptr_val_type &val = pStack[sidx];
             if (val->GetCode()==cmVAR)
               val.Reset(m_cache.CreateFromCache());

             *val = *(static_cast<IValue*>(pTok));
           }
           continue;

      case  cmIC:
            {
              IOprtIndex *pIdxOprt = static_cast<IOprtIndex*>(pTok);
              int nArgs = pIdxOprt->GetArgsPresent();
              sidx -= nArgs - 1;
              assert(sidx>=0);

              ptr_val_type &idx = pStack[sidx];     // Pointer to the first index
              ptr_val_type &val = pStack[--sidx];   // Pointer to the variable or value beeing indexed
              pIdxOprt->At(val, &idx, nArgs);




/*

              // apply the index operator
              ptr_val_type &idx = pStack[sidx--];
              ptr_val_type &val = pStack[sidx];
              MUP_ASSERT(val->GetCode()==cmVAR);
             
              int i;
              try
              {
                i = idx->GetInteger();
                if (i<0)
                  Error(ecINDEX_OUT_OF_BOUNDS, pTok->GetExprPos(), val.Get());
              }
              catch(ParserError &exc)
              {
                if (exc.GetCode()==ecTYPE_CONFLICT)
                  Error(ecTYPE_CONFLICT_IDX, pTok->GetExprPos(), val.Get());
                else 
                  throw;
              }
              val.Reset(new Variable( &(val->At(i)) ) );
*/
            }
            continue;

      case cmOPRT_POSTFIX:
      case cmFUNC:
      case cmOPRT_BIN:
      case cmOPRT_INFIX:
           {
             ICallback *pFun = static_cast<ICallback*>(pTok);
             int nArgs = pFun->GetArgsPresent();
             sidx -= nArgs - 1;
             assert(sidx>=0);

             ptr_val_type &val = pStack[sidx];
             try
             {
               if (val->GetCode()==cmVAR)
               {
                 ptr_val_type buf(m_cache.CreateFromCache());
                 pFun->Eval(buf, &val, nArgs);
                 val = buf;
               }
               else
                 pFun->Eval(val, &val, nArgs);
             }
             catch(ParserError &exc)
             {
               ErrorContext err;
               err.Expr = m_pTokenReader->GetExpr();
               err.Ident = pFun->GetIdent();
               err.Errc = ecEVAL;
               err.Pos = pFun->GetExprPos();
               err.Hint = exc.GetMsg();
               throw ParserError(err);
             }
             catch(MatrixError & /*exc*/)
             {
               ErrorContext err;
               err.Expr = m_pTokenReader->GetExpr();
               err.Ident = pFun->GetIdent();
               err.Errc = ecEVAL;
               err.Pos = pFun->GetExprPos();
               err.Hint = _T("Matrix dimension mismatch");
               throw ParserError(err);
             }
           }
           continue;

      case cmIF:
           MUP_ASSERT(sidx>=0);
           if (pStack[sidx--]->GetBool()==false)
             i+=static_cast<TokenIfThenElse*>(pTok)->GetOffset();
           continue;

      case cmELSE:
      case cmJMP:
           i += static_cast<TokenIfThenElse*>(pTok)->GetOffset();
           continue;

      case cmENDIF:
           continue;

			default:
					Error(ecINTERNAL_ERROR);
      } // switch token
    } // for all RPN tokens

    return *pStack[m_nFinalResultIdx];
  }
Ejemplo n.º 2
0
  /** \brief Calls 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
  */
  void ParserXBase::ApplyFunc(Stack<ptr_tok_type> &a_stOpt,
                              Stack<ptr_val_type> &a_stVal, 
                              int a_iArgCount) const
  { 
    if (a_stOpt.empty())
      return;

    ptr_tok_type tok = a_stOpt.pop();
    ICallback *pFun = tok->AsICallback();

    int iArgCount = (pFun->GetArgc()>=0) ? pFun->GetArgc() : a_iArgCount;
    int iOffset = a_stVal.size() - iArgCount;
    MUP_ASSERT(iOffset>=0);

    // The paramater stack may be empty since functions may not
    // have a parameter. They do always have a return value though.
    // If the param stack is empty create an entry for the function 
    // return value.
    if (iArgCount==0)
      a_stVal.push(ptr_val_type(new Value()));

    MUP_ASSERT((std::size_t)iOffset<a_stVal.size());
    ptr_val_type *pArg = a_stVal.get_data() + iOffset;
    
    //if (pFun->GetArgc()==0)
    //  a_stVal.push(ptr_val_type(new Value()));

    //ptr_val_type *pArg = a_stVal.get_data() + iOffset;

    try
    {
      // Make sure to pass on a volatile flag to the function result
      bool bResultIsVolatile = false;
      for (int i=0; i<iArgCount && bResultIsVolatile==false; ++i)
      {
        if (pArg[i]->IsFlagSet(IToken::flVOLATILE))
          bResultIsVolatile = true;
      }

      // Instead of evaluating the function merely a dummy value of the same type as the function return value
      // is created 
      *pArg = ptr_val_type(new Value());
      pFun->SetNumArgsPresent(iArgCount);
      
      if (bResultIsVolatile)
        (*pArg)->AddFlags(IToken::flVOLATILE);

      m_rpn.Add(tok);
    }
    catch(ParserError &e)
    {
      // This are type related errors caused by undefined
      // variables. They must be ignored if the parser is
      // just checking the presence of expression variables
      if (!m_bIsQueryingExprVar)
      {
        ErrorContext &err = e.GetContext();
        err.Pos   = m_pTokenReader->GetPos();
        err.Expr  = m_pTokenReader->GetExpr();

        if (err.Ident.empty())
          err.Ident = pFun->GetIdent();

        throw;
      }
    }

    if (iArgCount>0)
      a_stVal.pop(iArgCount-1); // remove the arguments
  }
//---------------------------------------------------------------------------
const IValue& ParserXBase::ParseFromRPN() const
{
    ptr_val_type *pStack = &m_vStackBuffer[0];
    if (m_rpn.GetSize()==0)
    {
        // Passiert bei leeren strings oder solchen, die nur Leerzeichen enthalten
        ErrorContext err;
        err.Expr = m_pTokenReader->GetExpr();
        err.Errc = ecUNEXPECTED_EOF;
        err.Pos  = 0;
        throw ParserError(err);
    }

    const ptr_tok_type *pRPN = &(m_rpn.GetData()[0]);

    int sidx = -1;
    std::size_t lenRPN = m_rpn.GetSize();
    for (std::size_t i=0; i<lenRPN; ++i)
    {
        IToken *pTok = pRPN[i].Get();
        ECmdCode eCode = pTok->GetCode();

        switch (eCode)
        {
        case cmSCRIPT_NEWLINE:
            sidx = -1;
            continue;

        case cmVAL:
        {
            IValue *pVal = static_cast<IValue*>(pTok);

            sidx++;
            assert(sidx<(int)m_vStackBuffer.size());
            if (pVal->IsVariable())
            {
                pStack[sidx].Reset(pVal);
            }
            else
            {
                ptr_val_type &val = pStack[sidx];
                if (val->IsVariable())
                    val.Reset(m_cache.CreateFromCache());

                *val = *(static_cast<IValue*>(pTok));
            }
        }
        continue;

        case  cmIC:
        {
            IOprtIndex *pIdxOprt = static_cast<IOprtIndex*>(pTok);
            int nArgs = pIdxOprt->GetArgsPresent();
            sidx -= nArgs - 1;
            assert(sidx>=0);

            ptr_val_type &idx = pStack[sidx];     // Pointer to the first index
            ptr_val_type &val = pStack[--sidx];   // Pointer to the variable or value beeing indexed
            pIdxOprt->At(val, &idx, nArgs);
        }
        continue;

        case cmOPRT_POSTFIX:
        case cmFUNC:
        case cmOPRT_BIN:
        case cmOPRT_INFIX:
        {
            ICallback *pFun = static_cast<ICallback*>(pTok);
            int nArgs = pFun->GetArgsPresent();
            sidx -= nArgs - 1;
            assert(sidx>=0);

            ptr_val_type &val = pStack[sidx];
            try
            {
                if (val->IsVariable())
                {
                    ptr_val_type buf(m_cache.CreateFromCache());
                    pFun->Eval(buf, &val, nArgs);
                    val = buf;
                }
                else
                    pFun->Eval(val, &val, nArgs);
            }
            catch(ParserError &exc)
            {
                // <ibg 20130131> Not too happy about that:
                // Multiarg functions may throw specific error codes when evaluating.
                // These codes would be converted to ecEVAL here. I omit the conversion
                // for certain handpicked errors. (The reason this catch block exists is
                // that not all exceptions contain proper metadata when thrown out of
                // a function.)
                if (exc.GetCode()==ecTOO_FEW_PARAMS || exc.GetCode()==ecDOMAIN_ERROR || exc.GetCode()==ecOVERFLOW)
                    throw;
                // </ibg>

                ErrorContext err;
                err.Expr = m_pTokenReader->GetExpr();
                err.Ident = pFun->GetIdent();
                err.Errc = ecEVAL;
                err.Pos = pFun->GetExprPos();
                err.Hint = exc.GetMsg();
                throw ParserError(err);
            }
            catch(MatrixError & /*exc*/)
            {
                ErrorContext err;
                err.Expr = m_pTokenReader->GetExpr();
                err.Ident = pFun->GetIdent();
                err.Errc = ecMATRIX_DIMENSION_MISMATCH;
                err.Pos = pFun->GetExprPos();
                throw ParserError(err);
            }
        }
        continue;

        case cmIF:
            MUP_ASSERT(sidx>=0);
            if (pStack[sidx--]->GetBool()==false)
                i+=static_cast<TokenIfThenElse*>(pTok)->GetOffset();
            continue;

        case cmELSE:
        case cmJMP:
            i += static_cast<TokenIfThenElse*>(pTok)->GetOffset();
            continue;

        case cmENDIF:
            continue;

        default:
            Error(ecINTERNAL_ERROR);
        } // switch token
    } // for all RPN tokens

    return *pStack[0];
}