// Parse a method declaration.
  static String getMethod(SamTokenizer f) throws TokenizerException {
    try {
      // The return type for all methods must be int.
      myCheck(f, "int");

      // methodName stores the name of the method.
      String methodName = f.getWord();
      if (symMap.containsKey(methodName))
        throw new TokenizerException("Error: Duplicate declaration of method " + methodName);
      String asmCode = methodName;

      // The name of the method <-> index of the symbol table of the method in the symTables vector
      symMap.put(methodName, symTables.size());
      symTables.addElement(new LinkedHashMap<String, Integer>());

      // Since there cannot be another method declaration inside of a, the symbol table we are
      // dealing with is
      // always the last element of the symTables vector.
      symTables.lastElement().put(methodName, 0);

      asmCode += ":\n";
      myCheck(f, '(');
      if (!f.check(')')) {
        // No SaM code generated by getFormals
        getFormals(f);
        myCheck(f, ')');
      }
      actMap.put(methodName, params.size());
      for (int i = 1; i <= params.size(); ++i) {
        // Add all formals to the symbol tabel
        symTables.lastElement().put(params.elementAt(params.size() - i), -i);
      }
      asmCode += getBody(f);
      // Clear the params vector and set varCounter back to 2.
      params.clear();
      varCounter = 2;
      return asmCode;
    } catch (Exception e) {
      System.out.println(e.getMessage());
      throw new TokenizerException("Error: Invalid method declaration.");
    }
  }
  // No return value for this function.
  static void getFormals(SamTokenizer f) throws TokenizerException {
    try {
      // The only type for formals is int.
      myCheck(f, "int");
      String paramName = f.getWord();

      // Check if the name already exists.
      if (symTables.lastElement().containsKey(paramName))
        throw new TokenizerException("Error: Duplicate declaration of " + paramName + ".");
      params.add(paramName);
      if (f.check(',')) {
        getFormals(f);
      }
      return;
    } catch (Exception e) {
      System.out.println(e.getMessage());
      throw new TokenizerException("Error: Invalid formals");
    }
  }
  static String getStmt(SamTokenizer f) throws TokenizerException {
    try {
      String asmCode = "";
      Boolean returnFlag1;
      Boolean returnFlag2;

      switch (f.peekAtKind()) {
        case WORD:
          {
            String newWord = f.getWord();
            switch (newWord) {
              case "return":
                {
                  asmCode += getExp(f);
                  myCheck(f, ';');
                  // SaM code for return.
                  asmCode +=
                      "STOREOFF -"
                          + Integer.toString(params.size() + 1)
                          + "\n"
                          + "ADDSP -"
                          + Integer.toString(varCounter - 2)
                          + "\n"
                          + "JUMPIND\n";
                  returnFlags.push(true);
                  return asmCode;
                }
              case "if":
                {
                  // Generate two valid lables for divergence.
                  String label1 = getLabel();
                  String label2 = getLabel();
                  myCheck(f, '(');
                  asmCode += getExp(f);
                  myCheck(f, ')');
                  asmCode += ("JUMPC " + label1 + "\n");
                  // Buffer the statements for if condition.
                  String tempString = getStmt(f);
                  returnFlag1 = returnFlags.pop();
                  myCheck(f, "else");
                  asmCode += getStmt(f);
                  returnFlag2 = returnFlags.pop();
                  // Manage the divergence.
                  asmCode +=
                      ("JUMP " + label2 + "\n" + label1 + ":\n" + tempString + label2 + ":\n");
                  if (returnFlag1 && returnFlag2) returnFlags.push(true);
                  else returnFlags.push(false);
                  return asmCode;
                }
              case "while":
                {
                  String label1 = getLabel();
                  String label2 = getLabel();

                  // Push the label as the return position.
                  labels.push(label2);
                  myCheck(f, '(');
                  asmCode += (label1 + ":\n");
                  asmCode += getExp(f);
                  asmCode += ("ISNIL\n" + "JUMPC " + label2 + "\n");
                  myCheck(f, ')');

                  // Flag indicating that we are in a while loop (possibly nested while loops.)
                  flags.push(true);
                  asmCode += getStmt(f);
                  asmCode += ("JUMP " + label1 + "\n" + label2 + ":\n");

                  // Once finish parsing the while loop, pop out the labels and flags.
                  labels.pop();
                  flags.pop();
                  return asmCode;
                }
              case "break":
                {
                  // flags.empty() indicates that we are not currently in a while loop.
                  if (flags.empty())
                    throw new TokenizerException("Error: Invalid break statement.");
                  myCheck(f, ';');

                  returnFlags.push(false);
                  // Jump to the current inner most return postion.
                  return "JUMP " + labels.peek() + "\n";
                }
              default:
                // Assign statement
                // Check if the variable is already defined.
                if (!symTables.lastElement().containsKey(newWord))
                  throw new TokenizerException("Error: Variable not declared.");
                myCheck(f, '=');
                asmCode += getExp(f);
                myCheck(f, ';');
                // Get the address of the variable from the symbol table.
                int addr = symTables.lastElement().get(newWord);
                asmCode += ("STOREOFF " + Integer.toString(addr) + "\n");
                returnFlags.push(false);
                return asmCode;
            }
          }
        case OPERATOR:
          {
            switch (f.getOp()) {
              case '{':
                {
                  asmCode += getBlock(f);
                  return asmCode;
                }
              case ';':
                returnFlags.push(false);
                return asmCode;
              default:
                throw new TokenizerException("Error: Invalid operator inside a statement.");
            }
          }
        default:
          throw new TokenizerException("Error: Invalid Statement.");
      }
    } catch (Exception e) {
      System.out.println(e.getMessage());
      throw new TokenizerException("Error: Invalid Statement.");
    }
  }