/** \brief Check if a string position contains a binary operator. */
bool TokenReader::IsOprt(ptr_tok_type &a_Tok)
{
    string_type sTok;
    int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_nPos);
    if (iEnd == m_nPos)
        return false;

    oprt_bin_maptype::reverse_iterator item;
    try
    {
        // Note:
        // All tokens in oprt_bin_maptype are have been sorted by their length
        // Long operators must come first! Otherwise short names (like: "add") that
        // are part of long token names (like: "add123") will be found instead 
        // of the long ones.
        // Length sorting is done with ascending length so we use a reverse iterator here.
        for (item = m_pOprtDef->rbegin(); item != m_pOprtDef->rend(); ++item)
        {
            if (sTok.find(item->first) != 0)
                continue;

            // operator found, check if we expect one...
            if (m_nSynFlags & noOPT)
            {
                // An operator was found but is not expected to occur at
                // this position of the formula, maybe it is an infix 
                // operator, not a binary operator. Both operator types
                // can use the same characters in their identifiers.
                if (IsInfixOpTok(a_Tok))
                    return true;

                // nope, it's no infix operator and we dont expect 
                // an operator
                throw ecUNEXPECTED_OPERATOR;
            }
            else
            {
                a_Tok = ptr_tok_type(item->second->Clone());

                m_nPos += (int)a_Tok->GetIdent().length();
                m_nSynFlags = noBC | noIO | noIC | noOPT | noCOMMA | noEND | noNEWLINE | noPFX | noIF | noELSE;
                return true;
            }
        }

        return false;
    }
    catch (EErrorCodes e)
    {
        ErrorContext err;
        err.Errc = e;
        err.Pos = m_nPos; // - (int)item->first.length();
        err.Ident = item->first;
        err.Expr = m_sExpr;
        throw ParserError(err);
    }
}
Exemplo n.º 2
0
  /** \brief Check if a string position contains a binary operator.
      \param a_Tok  [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
      \return true if an operator token has been found.
  */
  bool ParserTokenReader::IsOprt(token_type &a_Tok)
  {
    const char_type *const szExpr = m_strFormula.c_str();
    string_type strTok;

    int iEnd = ExtractOperatorToken(strTok, m_iPos);
    if (iEnd==m_iPos)
      return false;

    // Check if the operator is a built in operator, if so ignore it here
    const char_type **const pOprtDef = m_pParser->GetOprtDef();
    for (int i=0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i)
    {
      if (string_type(pOprtDef[i])==strTok)
        return false;
    }

    // Note:
    // All tokens in oprt_bin_maptype are have been sorted by their length
    // Long operators must come first! Otherwise short names (like: "add") that
    // are part of long token names (like: "add123") will be found instead 
    // of the long ones.
    // Length sorting is done with ascending length so we use a reverse iterator here.
    funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin();
    for ( ; it!=m_pOprtDef->rend(); ++it)
    {
      const string_type &sID = it->first;
      if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) )
      {
        a_Tok.Set(it->second, strTok);

        // operator was found
        if (m_iSynFlags & noOPT) 
        {
          // An operator was found but is not expected to occur at
          // this position of the formula, maybe it is an infix 
          // operator, not a binary operator. Both operator types
          // can share characters in their identifiers.
          if ( IsInfixOpTok(a_Tok) ) 
            return true;
          else
          {
            // nope, no infix operator
            return false;
            //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); 
          }

        }

        m_iPos += (int)sID.length();
        m_iSynFlags  = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noBC | noASSIGN;
        return true;
      }
    }

    return false;
  }
Exemplo n.º 3
0
  /** \brief Read the next token from the string. */ 
  ParserTokenReader::token_type ParserTokenReader::ReadNextToken()
  {
    assert(m_pParser);

    std::stack<int> FunArgs;
    const char_type *szFormula = m_strFormula.c_str();
    token_type tok;

    // Ignore all non printable characters when reading the expression
    while (szFormula[m_iPos]>0 && szFormula[m_iPos]<=0x20) 
      ++m_iPos;

    if ( IsEOF(tok) )        return SaveBeforeReturn(tok); // Check for end of formula
    if ( IsOprt(tok) )       return SaveBeforeReturn(tok); // Check for user defined binary operator
    if ( IsFunTok(tok) )     return SaveBeforeReturn(tok); // Check for function token
    if ( IsBuiltIn(tok) )    return SaveBeforeReturn(tok); // Check built in operators / tokens
    if ( IsArgSep(tok) )     return SaveBeforeReturn(tok); // Check for function argument separators
    if ( IsValTok(tok) )     return SaveBeforeReturn(tok); // Check for values / constant tokens
    if ( IsVarTok(tok) )     return SaveBeforeReturn(tok); // Check for variable tokens
    if ( IsStrVarTok(tok) )  return SaveBeforeReturn(tok); // Check for string variables
    if ( IsString(tok) )     return SaveBeforeReturn(tok); // Check for String tokens
    if ( IsInfixOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators
    if ( IsPostOpTok(tok) )  return SaveBeforeReturn(tok); // Check for unary operators

    // Check String for undefined variable token. Done only if a 
    // flag is set indicating to ignore undefined variables.
    // This is a way to conditionally avoid an error if 
    // undefined variables occur. 
    // (The GetUsedVar function must suppress the error for
    // undefined variables in order to collect all variable 
    // names including the undefined ones.)
    if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) )  
      return SaveBeforeReturn(tok);

    // Check for unknown token
    // 
    // !!! From this point on there is no exit without an exception possible...
    // 
    string_type strTok;
    int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
    if (iEnd!=m_iPos)
      Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok);

    Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos));
    return token_type(); // never reached
  }
/** \brief Read the next token from the string. */
ptr_tok_type TokenReader::ReadNextToken()
{
    assert(m_pParser);

    SkipCommentsAndWhitespaces();

    int token_pos = m_nPos;
    ptr_tok_type pTok;

    // Check for end of expression
    if (IsEOF(pTok))
        return Store(pTok, token_pos);

    if (IsNewline(pTok))
        return Store(pTok, token_pos);

    if (!(m_nSynFlags & noOPT) && IsOprt(pTok))
        return Store(pTok, token_pos); // Check for user defined binary operator

    if (!(m_nSynFlags & noIFX) && IsInfixOpTok(pTok))
        return Store(pTok, token_pos); // Check for unary operators

    if (IsValTok(pTok))
        return Store(pTok, token_pos); // Check for values / constant tokens

    if (IsBuiltIn(pTok))
        return Store(pTok, token_pos); // Check built in operators / tokens

    if (IsVarOrConstTok(pTok))
        return Store(pTok, token_pos); // Check for variable tokens

    if (IsFunTok(pTok))
        return Store(pTok, token_pos);

    if (!(m_nSynFlags & noPFX) && IsPostOpTok(pTok))
        return Store(pTok, token_pos); // Check for unary operators

    // 2.) We have found no token, maybe there is a token that we don't expect here.
    //     Again call the Identifier functions but this time only those we don't expect 
    //     to find.
    if ((m_nSynFlags & noOPT) && IsOprt(pTok))
        return Store(pTok, token_pos); // Check for user defined binary operator

    if ((m_nSynFlags & noIFX) && IsInfixOpTok(pTok))
        return Store(pTok, token_pos); // Check for unary operators

    if ((m_nSynFlags & noPFX) && IsPostOpTok(pTok))
        return Store(pTok, token_pos); // Check for unary operators
    // </ibg>

    // Now we are in trouble because there is something completely unknown....

    // Check the string for an undefined variable token. This is done 
    // only if a flag is set indicating to ignore undefined variables.
    // This is a way to conditionally avoid an error if undefined variables 
    // occur. The GetExprVar function must supress the error for undefined 
    // variables in order to collect all variable names including the 
    // undefined ones.
    if ((m_pParser->m_bIsQueryingExprVar || m_pParser->m_bAutoCreateVar) && IsUndefVarTok(pTok))
        return Store(pTok, token_pos);

    // Check for unknown token
    // 
    // !!! From this point on there is no exit without an exception possible...
    // 
    string_type sTok;
    int iEnd = ExtractToken(m_pParser->ValidNameChars(), sTok, m_nPos);

    ErrorContext err;
    err.Errc = ecUNASSIGNABLE_TOKEN;
    err.Expr = m_sExpr;
    err.Pos = m_nPos;

    if (iEnd != m_nPos)
        err.Ident = sTok;
    else
        err.Ident = m_sExpr.substr(m_nPos);

    throw ParserError(err);
}
Exemplo n.º 5
0
  /** \brief Check if a built in operator or other token can be found
      \param a_Tok  [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
      \return true if an operator token has been found.
  */
  bool ParserTokenReader::IsBuiltIn(token_type &a_Tok)
  {
    const char_type **const pOprtDef = m_pParser->GetOprtDef(),
                     *const szFormula = m_strFormula.c_str();

    // Compare token with function and operator strings
    // check string for operator/function
    for (int i=0; pOprtDef[i]; i++)
    {
      std::size_t len( std::char_traits<char_type>::length(pOprtDef[i]) );
      if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) )
      {
        switch(i)
        {
        //case cmAND:
        //case cmOR:
        //case cmXOR:
        case cmLAND:
        case cmLOR:
        case cmLT:
        case cmGT:
        case cmLE:
        case cmGE:
        case cmNEQ:  
        case cmEQ:
        case cmADD:
        case cmSUB:
        case cmMUL:
        case cmDIV:
        case cmPOW:
        case cmASSIGN:
              //if (len!=sTok.length())
              //  continue;

              // The assignement operator need special treatment
              if (i==cmASSIGN && m_iSynFlags & noASSIGN)
                Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);

              if (!m_pParser->HasBuiltInOprt()) continue;
              if (m_iSynFlags & noOPT) 
              {
                // Maybe its an infix operator not an operator
                // Both operator types can share characters in 
                // their identifiers
                if ( IsInfixOpTok(a_Tok) ) 
                  return true;

                Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
              }

              m_iSynFlags  = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;
              m_iSynFlags |= ( (i != cmEND) && ( i != cmBC) ) ? noEND : 0;
              break;

		    case cmBO:
              if (m_iSynFlags & noBO)
	              Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
              
              if (m_lastTok.GetCode()==cmFUNC)
                m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;
              else
                m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN| noIF | noELSE;

              ++m_iBrackets;
              break;

		    case cmBC:
              if (m_iSynFlags & noBC)
                Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);

              m_iSynFlags  = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN;

              if (--m_iBrackets<0)
                Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
              break;

        case cmELSE:
              if (m_iSynFlags & noELSE)
                Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);

              m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;
              break;

        case cmIF:
              if (m_iSynFlags & noIF)
                Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);

              m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;
              break;

		    default:      // The operator is listed in c_DefaultOprt, but not here. This is a bad thing...
              Error(ecINTERNAL_ERROR);
        } // switch operator id

        m_iPos += (int)len;
        a_Tok.Set( (ECmdCode)i, pOprtDef[i] );
        return true;
	    } // if operator string found
    } // end of for all operator strings
  
    return false;
  }