import java.lang.*;
import java.awt.*;



class container {
    ControlObj ReturnObj;
    int position;
}

public class Parse {
  protected String str;
  char array[];
  int ConditionCount=1;
  int StatementCount=1;

  int parseOne = 0;
  int parseMulti = 1;

  boolean ErrStatus=false;
  String ErrStr;

  public Parse(String s) {
    str = new String(s);
    str = str.toLowerCase();
    array = new char[10000];
    str.getChars(0, str.length(), array, 0);
  }

  public ProgramObj go() {

    /*
     *  Empty program
     */
    if (start(array, 0) < 0) return null;

    ProgramObj p = new ProgramObj();
    StmtList list = new StmtList();
    parse(array, 0, str.length()-1, list);
    p.content = list;

    return p;
  }


  void parse(char a[], int from, int end, StmtList list) {

    container con = parseOneStatement(a, from, parseMulti);
    if (con == null) {
      ErrStatus = true;
      ErrStr = "Error in Parsing";
      return;
    }
      

    list.CodeSeg = con.ReturnObj;
    int tmp = start(a, con.position);
    if (tmp > end || tmp < 0) {
      list.next = null;
    } else {
      list.next = new StmtList();
      parse(a, con.position, end, list.next);
    }

  }  /* End parse() */




  container parseOneStatement(char a[], int from, int mode) {

    String ControlName;
    ControlObj obj;

    int pos = start(a, from);
    if (pos < 0) {
      ErrStatus = true;
      ErrStr = "Error in Parsing";
      return null;
    }
    ControlName = Type(a, pos);

    if (ControlName == "if") {
      StmtList List = new StmtList();

      IfObj ifobj = new IfObj();
      ifobj.ConditionNo = ConditionCount++;
      pos = readCondition(a, pos+2); 
      if (pos < 0) {
        ErrStatus = true;
        ErrStr = "Error in Parsing";
        return null;
      }
      pos = parseBlock(a, pos, List);
      if (pos < 0) {
        ErrStatus = true;
        ErrStr = "Error in Parsing";
        return null;
      }
      ifobj.yes = List;

      if (start(a, pos) != -1) {
        pos = start(a, pos);
        if (pos < 0) {
          ErrStatus = true;
          ErrStr = "Error in Parsing";
          return null;
        }
        if (Type(a, pos) == "else") {
          StmtList List2 = new StmtList();

          pos = parseBlock(a, pos+4, List2);
          if (pos < 0) {
            ErrStatus = true;
            ErrStr = "Error in Parsing";
            return null;
          }
          ifobj.no = List2;
        } else {
          ifobj.no = null;
        } 
      }
      
      obj = ifobj;

    } else if (ControlName == "while") {
      StmtList List = new StmtList();

      WhileObj whileobj = new WhileObj();
      whileobj.ConditionNo = ConditionCount++;
      pos = readCondition(a, pos+5);
      if (pos < 0) {
        ErrStatus = true;
        ErrStr = "Error in Parsing";
        return null;
      }
      pos = parseBlock(a, pos, List);
      if (pos < 0) {
        ErrStatus = true;
        ErrStr = "Error in Parsing";
        return null;
      }

      whileobj.content = List;
      obj = whileobj;
     
    } else if (ControlName == "do") {
      StmtList List = new StmtList();

      RepeatObj repeatobj = new RepeatObj();
      repeatobj.ConditionNo = ConditionCount++;
      pos = parseBlock(a, pos+2, List);

      pos = start(a, pos);
      if (pos < 0) {
        ErrStatus = true;
        ErrStr = "Error in Parsing";
        return null;
      }
      if (Type(a, pos) != "while") {
        System.out.println("Error: do not followed by while");
        ErrStatus = true;
        ErrStr = "Error in Parsing";
        return null;
      }
      pos = readCondition(a, pos+5);
      if (pos < 0) {
        ErrStatus = true;
        ErrStr = "Error in Parsing";
        return null;
      }

      pos = start(a, pos);
      if (pos < 0) {
        ErrStatus = true;
        ErrStr = "Error in Parsing";
        return null;
      }
      if (Type(a, pos) != ";") {
        System.out.println("Error: do...while missing \";\"");
        ErrStatus = true;
        ErrStr = "Error in Parsing";
        return null;
      }
      pos++;

      repeatobj.content = List;
      obj = repeatobj;

    } else {
      int flag;

      while (true) {
        flag = 0;
        for (int i=pos; i<str.length(); i++) {
          if (a[i] == ';') {

            pos = start(a, i+1);
            if (pos == -1) {
              flag = 1;
              pos = i+1;
              break;
            }
            String tmp = Type(a, pos);

            if (tmp=="while" || tmp=="if" || tmp=="do" ||
                tmp=="else" || mode==parseOne)
              flag = 1;		/* finish */
            else
              flag = 2;
              
            break;    
          }

          /* { */
          if (a[i] == '}') {
            pos = i+1;
            flag = 1;
            break;		/* finish */
          }
        }

        if (flag == 0) {
          System.out.println("Error inside parseOneStatement\n");
          ErrStatus = true;
          ErrStr = "Error in Parsing";
          return null;
        } else if (flag == 1) {
          break;
        }
 
      }

      obj = new StatementObj();
      ((StatementObj)obj).StatementNo = StatementCount++;

    }

    container con = new container();
    con.ReturnObj = obj;
    con.position = pos;

    return con;

  }  /* end parseOneStatement() */



  int parseBlock(char a[], int from, StmtList list) {
    int head = start(a, from);
    int count = 0;
    int i;

    if (Type(a, head) == "{" /*}*/) {

      for (i=head; i<str.length(); i++) {
        if (a[i] == '{') count++;
        if (a[i] == '}') count--;
        if (count == 0) {
          break;
        }
      }

      if (count != 0) {
        System.out.println("Error inside parseBlock\n");
        ErrStatus = true;
        ErrStr = "Error in Parsing";
        return -1;
      }

      parse(a, head+1, i-1, list);
      return i+1;

    } else {
      container con = parseOneStatement(a, from, parseOne);
      if (con == null) {
        ErrStatus = true;
        ErrStr = "Error in Parsing";
        return -1;
      }
      list.CodeSeg = con.ReturnObj;
      list.next = null;
      return(con.position);
    }


  }  /* end parseBlock */



  boolean NotEnd(char a[], int from) {
    if (start(a, from) != -1) return true;
    else return false;
  }


  int readCondition(char a[], int from) {
    int head = start(a, from);
    if (Type(a, head) != "(" /*)*/) return -1;

    int i=head;
    int count=0;
    while (i<str.length()) {
      if (a[i] == '(') count++;

      if (a[i] == ')') {
        count--;
        if (count == 0) return(i+1);
      }

      i++;
    }

    return -1;

  }



  String Type(char a[], int from) {
    if (str.startsWith("if", from)) return "if";
    if (str.startsWith("while", from)) return "while";
    if (str.startsWith("do", from)) return "do";
    if (str.startsWith("else", from)) return "else";
    if (str.startsWith("{", from)) return ("{");
    if (str.startsWith("}", from)) return ("}");
    if (str.startsWith("(", from)) return ("(");
    if (str.startsWith(")", from)) return (")");
    if (str.startsWith(";", from)) return (";");

    return ("UNKNOWN");
  }

  int start(char a[], int from) {
    if (from >= str.length()) return -1;

    for (int i=from; i<str.length(); i++) {
      switch (a[i]) {
	case ' ':
	case '\t':
	case '\n':
	case '\r':
	  break;
	default:
	  return i;
      }
    }
    return -1;
  }


}
