// C++ implementation of Logical Line Counting (Problem A ACM SP 1999)
//
#include <iostream>

using namespace std;

enum State { Prg, Str1, Str2, Cmt1, Cmt2 };

int main()
{
  State s = Prg;
  int num = 1, llines = 0, plines = 0;
  char c; 

  while (true)
  {
    c = cin.get();

    switch (c)
    {
      case '(':
        if (s == Prg)
        {
          c = cin.get();
          if (c=='(')
          {
            s = Cmt2;
            break;
          }
          else cin.unget();
          //else goto body;
        }
	break;
      case ')':
        if (s == Cmt2)
        {
          c = cin.get();
          if (c==')')
          {
            s = Prg;
            break;
          }
          else cin.unget();
          //else goto body;
        }
	break;
      case '@':
         if (s == Cmt2) break;
         if (s == Prg) 
         { 
           s = Cmt1; 
	   while (c != '\n') c = cin.get();
           // then do case '\n';
         }
	 else break;
      case '\n':
         plines++;
         if (s == Str1 || s == Str2)
         {
           cout << "Unterminated string on line " << plines << ".\n";
           s = Prg;
         }
         if (s == Cmt1) s = Prg;
 	 break;
      case '"':
         if (s == Str2) s = Prg;	// end Str2
         else if (s == Prg) s = Str2;	// start Str2
	 break;
      case '\'':
         if (s == Str1) s = Prg;	// end Str1
         else if (s == Prg) s = Str1;	// start Str1
	 break;
      case ';':
         if (s == Prg) llines++;
	 break;
      case '#':
         if (s == Cmt2) cout << "Unterminated block comment at end of program.\n";
         
         cout << "Program " << num << " contains " << llines << 
		" logical lines and " << plines << " physical lines.\n";

         num++; llines = 0; plines = 0; s=Prg;

         c = cin.get();
         if (c == '#') return 1;

	 while (c != '\n') c = cin.get(); // skip white space
	 break;
    } //switch

  } // while

}

