Logo Search packages:      
Sourcecode: massxpert version File versions

bool massXpert::Formula::parse ( const QList< Atom * > &  refList,
const QString &  formula,
int  times = 1,
bool  store = false,
bool  reset = false 
) [protected, inherited]

Parses the formula using the reference atom list.

Upon parsing of the formula, a list of AtomCount objects are created in order to be able to account for the mass of the formula.

Parameters:
refList List of reference atoms.
formula Formula to parse.
times Number of times that the formula should be accounted for. Default value is 1.
store Indicates if AtomCount objects created during the parsing of the formula have to be stored, or not. Default value is false.
reset Indicates if AtomCount objects created during the parsing of the formula have to be destroyed before doing another parsing. This parameter is interesting if the caller needs to "accumulate" the accounting of the formula. Default value is false.
Returns:
true if parsing succeeded, false otherwise.

Definition at line 573 of file formula.cpp.

References massXpert::Formula::accountInList(), massXpert::Formula::checkSyntax(), massXpert::AtomCount::count(), massXpert::Atom::isSymbolKnown(), massXpert::Formula::m_atomCountList, massXpert::AtomCount::setCount(), and massXpert::Atom::setSymbol().

Referenced by massXpert::Formula::splitParts().

  {
    QChar curChar;
    QString parsedCount;
    QString parsedSymbol;
    AtomCount *atomCount = 0;

    bool wasDigit = false;
    bool wasUpper = false;
    bool gotUpper = false;

    Q_ASSERT(refList.size());

    // The formula member is a QString that should hold the formula
    // according to this typical schema: "H2O"(water). That means we
    // only want letters(Upper and lower case and number).

    // The member atomCountList might be reset before starting, or if
    // !reset, then the new atom counts are added to the ones
    // preexisting.

    // The formula should thus not be empty, otherwise there is nothing
    // to do. But it is not an error that the formula be empty.
    if (formula.length() == 0)
      return true;

    if (!checkSyntax())
      return false;

    // Also, the first character of the formula should be an Uppercase
    // letter. If not, logically, the formula is incorrect.
    if (formula.at(0).category() != QChar::Letter_Uppercase)
      return false;

    if (reset)
      {
      // We first want to iterate in the atomCountList and make sure
      // we remove all items from it.

      while(!m_atomCountList.isEmpty())
        delete m_atomCountList.takeFirst();
      }

    // And now finally start the real parsing stuff.

    for (int iter = 0 ; iter < formula.length() ; ++iter)
      {
      curChar = formula.at(iter);

      if(curChar.category() == QChar::Number_DecimalDigit)
        {
          // We are parsing a digit.

          parsedCount.append(curChar);

          wasDigit = true;
          wasUpper = false;

          continue;
        }
      else if (curChar.category() == QChar::Letter_Lowercase)
        {
          // Current character is lowercase, which means we are inside
          // of an atom symbol, such as Ca(the 'a') or Nob(either
          // 'o' or 'b'). Thus, gotUpper should be true !

          if (!gotUpper)
            return false;

          // Make use of the parsed numerical character.
          parsedSymbol.append(curChar);

          // Let the people know that we have parsed a lowercase char
          // and not a digit.
          wasUpper = false;
          wasDigit = false;
        }
      else if (curChar.category() == QChar::Letter_Uppercase)
        {
          // Current character is uppercase, which means that we are
          // at the beginning of an atom symbol. Check if there was a
          // symbol being parsed before this one.

          if (parsedSymbol.isEmpty())
            {
            // Start new parsing round.
            parsedSymbol.append(curChar);

            gotUpper = true;
            wasUpper = true;
            wasDigit = false;
            continue;
            }
        
          // There was a symbol being parsed. Create an object.
          atomCount = new AtomCount();
          atomCount->setSymbol(parsedSymbol);
        
          // Now we can prepare the field for the next one.
          parsedSymbol.clear();
          parsedSymbol.append(curChar);

          // Before going on, check if the symbol is correct.
          if (atomCount->isSymbolKnown(refList) == -1)
            {
            delete atomCount;
            
            return false;
            }
        
          // If there was a count being parsed, we have to take it
          // into account.
          if (wasDigit)
            {
            // And now we have to convert the string representation
            // of the atom count for that atom to int. In fact, we
            // have to be able to know that water H2O has TWO
            // hydrogen atoms in it.
            bool isok = true;
            atomCount->setCount(parsedCount.toInt(&isok, 10));

            if(atomCount->count() == 0 && !isok)
              {
                // The atom counts for nothing ! Or was there
                // an error in the conversion ?

                delete atomCount;

                return false;
              }
            
            // But we remember that we have to take into account the
            // times parameter.
            
            atomCount->setCount(atomCount->count() * times);

            // Clear parsedCount for next count parsing round.
            parsedCount.clear();
            }
          else
            atomCount->setCount(1 * times);
        
          // We can now make sure that the atom gets represented
          // in the formula.atomCountList list of
          // AtomCount*. But for this we use a function that
          // will make sure there is not already the same atom
          // symbol in that List, so as not to duplicate the items
          // accounting for a single atom symbol.

          if (store)
            {
            if(!accountInList(atomCount, 0))
              delete atomCount;
            }
          else
            delete atomCount;

          // Let the people know what we got:
        
          wasDigit = false;
          gotUpper = true;
          wasUpper = true;
        }
      // end(curChar.category() == QChar::Letter_Uppercase)
      }
    // end for (int iter = 0 ; iter < formula.length() ; ++iter)

    // At this point we are at then end of the string, and we thus might
    // still have something cooking:

    // Thus we have to check that the last parsed atom
    // symbol is correct. First allocate an AtomCount
    // instance and set the symbol to it.

    atomCount = new AtomCount();
    atomCount->setSymbol(parsedSymbol);

    if (atomCount->isSymbolKnown(refList) == -1)
      {
      delete atomCount;

      return false;
      }

    // And now we have to convert the string representation
    // of the atom count for that atom to int. In fact, we
    // have to be able to know that water H2O has TWO
    // hydrogen atoms in it.

    // If there was a count being parsed, we have to take it
    // into account.
    if (wasDigit)
      {
      // And now we have to convert the string representation
      // of the atom count for that atom to int. In fact, we
      // have to be able to know that water H2O has TWO
      // hydrogen atoms in it.
      bool isok = true;
      atomCount->setCount(parsedCount.toInt(&isok, 10));

      if(atomCount->count() == 0 && !isok)
        {
          // The atom counts for nothing ! Or was there
          // an error in the conversion ?

          delete atomCount;

          return false;
        }
            
      // But we remember that we have to take into account the
      // times parameter.
            
      atomCount->setCount(atomCount->count() * times);
      }
    else
      atomCount->setCount(1 * times);
        
    // Finally, if asked by the caller, we can account for
    // this atom symbol/count also !

    if (store)
      {
      if(!accountInList(atomCount, 0))
        delete atomCount;
      }
    else
      delete atomCount;

    return true;
  }


Generated by  Doxygen 1.6.0   Back to index