include <iostream>
#include <cassert>
#include <string>
#include <memory>
#include <vector>
#include <fstream>
#include <sstream>
class FormatVisitor : public BaseVisitor {
public:
void Visit(const BaseNode *node) override {
node->Visit(this);
}
void Visit(const ClassDeclarationNode *node) override {
std::ostringstream line;
line << getCurrentIdent() << "class " << node->ClassName() << " {";
cachedCode.emplace_back(line.str());
ident_++;
if (!node->PublicFields().empty())
runThroughBlock("public:", node->PublicFields());
if (!node->ProtectedFields().empty()) {
cachedCode.emplace_back("");
runThroughBlock("protected:", node->ProtectedFields());
}
if (!node->PrivateFields().empty()) {
cachedCode.emplace_back("");
runThroughBlock("private:", node->PrivateFields());
}
ident_--;
cachedCode.emplace_back(getCurrentIdent() + "};");
};
void Visit(const VarDeclarationNode *node) override {
cachedCode.emplace_back(getCurrentIdent() + node->TypeName()
+ ' ' + node->VarName() + ';');
};
void Visit(const MethodDeclarationNode *node) override {
std::ostringstream line;
line << getCurrentIdent() << node->ReturnTypeName() << ' '
<< node->MethodName() << '(';
for (uint i = 0; i < node->Arguments().size(); ++i) {
if (i != 0) line << ", ";
auto arg = reinterpret_cast<VarDeclarationNode *>(node->Arguments()[i]);
line << arg->TypeName() << ' ' << arg->VarName();
}
line << ");";
cachedCode.emplace_back(line.str());
};
const std::vector<std::string> &GetFormattedCode() const {
return cachedCode;
}
private:
int ident_ = 0;
void runThroughBlock(const std::string &blockName,
const std::vector<BaseNode *> &fields) {
cachedCode.emplace_back(getCurrentIdent() + blockName);
ident_++;
for (auto field : fields)
Visit(field);
ident_--;
}
std::string getCurrentIdent() const {
std::ostringstream res;
for (int i = 0; i < ident_; ++i)
res << " ";
return res.str();
}
std::vector<std::string> cachedCode = std::vector<std::string>();
};