#include <iostream>
#include <string>
#include <vector>
#include <fstream>

using namespace std;

char uppercase(char c) {
  if(c <= 'z' && c >= 'a') {
    c -= 'a' - 'A';
  }
  return c;
}

void err(string s) {
  cerr << s << endl;
  exit(1);
}

bool eline(string tag) {
  if(tag == "H1" || tag == "H2" || tag == "P" || tag == "HR") {
    return true;
  }
  return false;
}

void horizline(std::ostream& o) {
  //o << endl;
  for(int i = 0; i<40; i++) {
    o << "-";
  }
  //o << endl;
}

int main(int argc, char ** argv) {

  if(argc < 3) {
    err("bad number of parameters");
  }

  istream *in;
  ostream *out;

  in = new ifstream(argv[1]);
  out = new ofstream(argv[2]);


  vector<string> tagstack;
  vector<char> ctag;
  vector<char> cwsp;

  bool tagtext = false;
  bool wasspace = false;
  bool wasnl = false;

  bool intag = false;

  char c;
  while(in->get(c)) {

    if(!intag) {
      if(c == '<') { // start of tag - '<'
        ctag.erase(ctag.begin(), ctag.end());
        wasnl = false;
        wasspace = true; 
        intag = true;
      } else {

        // write to output

        if(!isspace(c)) {
          if(tagstack.empty()) {
            err("payload w/o tag");
          }

          if(tagstack.back() == "LI" && !tagtext) { // LI -> generate asterisks
            int depth = 0;
            for(auto it = tagstack.begin(); it != tagstack.end(); it++) {
              if(*it == "UL") {
                depth++;
              }
            }
            int spaces = depth*4;
            *out << endl;
            for(int i = 0; i<spaces; i++) {
              *out << ' ';
            }
            *out << "* ";

            for(auto it = cwsp.begin(); it != cwsp.end(); it++) {
              *out << *it;
            }
            cwsp.erase(cwsp.begin(), cwsp.end());
            
          }

          if(tagstack.back() == "H1") { // H1 -> to upper
            *out << uppercase(c);
          } else if (tagstack.back() == "H2") { // H2 -> first letter of word to upper
            if(wasspace) {
              *out << uppercase(c);
            } else {
              *out << c;
            }
          } else if(tagstack.back() == "HR") {
            err("text in HR tag");
          } else if(tagstack.back() == "UL") {
            err("text in UL tag");
          } else {
            *out << c;
          }

          wasspace = false;
          tagtext = true;
        } else { // whitespaces

          if(!tagstack.empty()) { // ignore whitespaces in free space

            if(tagstack.back() != "HR" && tagstack.back() != "UL") {
              char iot = 0;

              if(c == '\n') { // newline
                if(!wasnl) { // first newline - write one space to output
                  iot = ' ';
                }
                wasnl = true;
              } else {
                iot = c;
                wasnl = false;
              }
              if(iot) {
                if(tagstack.back() == "LI" && !tagtext) {
                  cwsp.push_back(iot);
                } else {
                  *out << iot;
                }
              }
            }
            wasspace = true;
          }
        }
      }

    } else { // intag
      if(c == '>') { // end of tag - '>'
        intag = false;

        // parse tag
        if(ctag.size() < 1) {
          err("empty tag");
        }

        if(ctag.at(0) == '/') { // closing tag
          string tag(ctag.begin()+1, ctag.end());
          if(tag.size() == 0) {
            err("empty closing tag");
          }

          if(tagstack.empty()) {
            err("closing tag with no tag open");
          }

          string last = tagstack.back();

          if(last == tag) { // closing tag -- delete from tag stack
            tagstack.pop_back();
          } else {
            err("closing tag that was not opened");
          }

          if(eline(tag)) {
            *out << endl;
            *out << endl;
          }

        } else { // opening tag

          string tag(ctag.begin(), ctag.end());

          // check allowed nesting
          if(!tagstack.empty()) {
            string last = tagstack.back();
            //cout << "nest " << last << " " << tag << " " <<tagtext << endl;
            // only ul can be in li
            if( (last == "LI" && !tagtext) || (last == "UL" && tag == "LI")) {
              // pass
            } else {
              err("bad tag nesting");
            }
          }

          if(eline(tag)) {
            *out << endl;
          }

          // special cases
          if(tag == "HR") {
            horizline(*out);
          }
          // push tag to stack
          tagstack.push_back(tag);

          // clean vector
          ctag.erase(ctag.begin(), ctag.end());
        }
        tagtext = false;
      } else { // push tag contents
        ctag.push_back(uppercase(c));
      }
    }

  // debug
  if(argc > 3) {
    cout<<c << " tagstack ";
    for(auto it = tagstack.begin(); it != tagstack.end(); it++) {
      cout<<*it << ".";
    }
    cout << endl;
  }

  }


  *out << endl;

	return 0;

}