Text Parsing

Now that the code has through the formula, it's time to do the leg work and find out what the mass of the compound is.

The search is split into two parts - the first divides up the formula, the second identifies the element.

The search is also a recursive search - it makes more sense to parse the first part of a formula, then parse the rest instead of doubling up the code in order to do the same thing. I'm not a fan of recursive functions as the logic is not always that clear with them, but in this case, it's a good idea to use it

void search(string formula, bool dot)
{
   int mult1 = 1, mult2 = 1, s = 0, p = 0, bs = 0, be = 0, bn = 0;
   bool hasdot = formula.Contains(".") ? true:false;
   bool hasbrace = formula.Contains("(") ? true : false;
   int point = hasdot == true ? formula.IndexOf(".") + 1 : 0;
		
   if (hasbrace == true)
   {
      int k = 0;
      for (k = 0; k < formula.Length; ++k)
      {
         if (formula[k] == '(')
            bs = k;
         if (formula[k] == ')')
            be = k;
      }
      k = formula.IndexOf(")") + 1;
      if (formula[k] >= '0' && formula[k] <= '9')
      {
          int c = 0;
          while (formula[k + c] >= '0' && formula[k + c] <= '9')
             c++;
          bn = Int32.Parse(formula.Substring(k, c));
      }
      else
          bn = 1;
    }

Is there a number outside of a bracket? If there is, what is it? The start and end points of the braces are also found and stored here

			
    if (hasdot == true && dot == true)
    {
       if (formula[point] >= '0' && formula[point] <= '9')
       {
          int c = 0;
          while(formula[point + c] >= '0' && 
                formula[point + c] <= '9')
             c++;
          mult1 = Int32.Parse(formula.Substring(point, c));
          s = point + 1;
       }
     }
     else
     {
        if (formula[0] >= '0' && formula[0] <= '9')
        {
           int c = 0;
           while(formula[c] >= '0' && formula[c] <= '9')
              c++;				
           mult1 = Convert.ToInt32(formula.Substring(0, c));
           s = 1;
         }
     }

Here the number at the start is being found. If nothing is there, mult1 remains at 1 - this is used to multiply the mass found by.

The hard part now starts - first is that it's vital to remember that an element can have more than one character, so let's set up some simple variables to help

string twoelem = "   "; // three spaces
double newmass = 0;
			
if (hasdot == true && dot == false)
   p = formula.IndexOf(".");
else
   p = formula.Length + 1;

The if clause really just sets the length of the string to be searched. The searching is all done with one large loop...

int loop = s;
{
   while (loop < p)
   {
      if (loop + 1 > p || formula[loop] == '#')
         break;

      if (loop == bs)
      {
         while (loop < be)
         {
            if (formula[loop + 1] >= 'a')
            {
               twoelem = formula.Substring(loop, 2);
               loop += 2;
            }
            else
            {
               twoelem = formula.Substring(loop, 1);
               loop++;
            }

            if (formula[loop] >= '0' && formula[loop] <= '9')
            {
               int c = 0;
               while (formula[loop + c] >= '0' && 
                      formula[loop + c] <= '9')
                  c++;
               if (twoelem == "")
               {
                  if (formula[loop + c + 1] < 'a')
                     twoelem = formula.Substring(loop + c, 1);
                  else
                     twoelem = formula.Substring(loop + c, 2);
               }
               mult2 = Int32.Parse(formula.Substring(loop, c));
               loop += c;
            }
            newmass = atommass(twoelem) * mult2 * bn;
            elem.Add(new element(twoelem, newmass));
            newmass = 0;
            mult2 = 1;
         }
      }
      
      if (formula[loop + 1] >= 'a')
      {      
         twoelem = formula.Substring(loop, 2);
         loop += 2;
      }
      else
      {
         twoelem = formula.Substring(loop, 1);
         loop++;
      }

      if (formula[loop] >= '0' && formula[loop] <= '9')
      {
         int c = 0;
         while (formula[loop + c] >= '0' && 
                formula[loop + c] <= '9')
            c++;
            
         if (twoelem == "")
         {
            if (formula[loop + c + 1] < 'a')
               twoelem = formula.Substring(loop + c, 1);
            else
               twoelem = formula.Substring(loop + c, 2);
         }
         mult2 = Int32.Parse(formula.Substring(loop, c));
         loop += c;
      }
      newmass = atommass(twoelem) * mult2 * mult1;
      elem.Add(new element(twoelem, newmass));
      newmass = 0;
      mult2 = 1;
   }
}

And finally, let's do the recursion...

if (dot == false && hasdot == true)
   search(formula, true);