#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <cmath>
#include <stack>
#include <functional>
#include <set>
#include <queue>
#include <string>
#include <memory>
#include <map>
#include <iomanip>
#include <sstream>
#include <cassert>

using std::string;
using std::vector;
using std::stringstream;

class FormatVisitor : public BaseVisitor {
    vector<string> res;
    stringstream s;

 public:
     void Visit(const BaseNode* node) override {
         node->Visit(this);
     };

     void Visit(const ClassDeclarationNode* node) override {
         string shift = s.str();
         s << "class " << node->ClassName() << " {";
         res.push_back(s.str());
         s.str("");
         const vector<BaseNode*>& pub = node->PublicFields();
         size_t len = pub.size();
         if (len > 0) {
             s << shift << "  public:";
             res.push_back(s.str());
             s.str("");
             for (int i = 0; i < len; ++i) {
                 s << "    " << shift;
                 Visit(pub[i]);
                 s << ";";
                 res.push_back(s.str());
                 s.str("");
             }
         }
         const vector<BaseNode*>& prot = node->ProtectedFields();
         len = prot.size();
         if (len > 0) {
             res.push_back(s.str());
             s.str("");
             s << shift << "  protected:";
             res.push_back(s.str());
             s.str("");
             for (int i = 0; i < len; ++i) {
                 s << "    " << shift;
                 Visit(prot[i]);
                 s << ";";
                 res.push_back(s.str());
                 s.str("");
             }
         }
         const vector<BaseNode*>& priv = node->PrivateFields();
         len = priv.size();
         if (len > 0) {
             res.push_back(s.str());
             s.str("");
             s << shift << "  private:";
             res.push_back(s.str());
             s.str("");
             for (int i = 0; i < len; ++i) {
                 s << "    " << shift;
                 Visit(priv[i]);
                 s << ";";
                 res.push_back(s.str());
                 s.str("");
             }
         }
         s << shift << "}";
     };

     void Visit(const VarDeclarationNode* node) override {
         s << node->TypeName() << " " << node->VarName();
     };

     void Visit(const MethodDeclarationNode* node) override {
         s << node->ReturnTypeName() << " " << node->MethodName() << "(";
         const vector<BaseNode*>& arguments = node->Arguments();
         size_t arguments_length = arguments.size();
         if (arguments_length > 0) {
             for (int i = 0; i < arguments_length - 1; ++i) {
                 Visit(arguments[i]);
                 s << ", ";
             }
             Visit(arguments[arguments_length - 1]);
         }
         s << ")";
     }

     const vector<string>& GetFormattedCode() {
         s << ";";
         res.push_back(s.str());
         return res;
     }
};