I've created a code generator generator, which is hosted here.
I need its parser portion reviewed for OOP, OOD, and C++ best practices.
gengenparser.h
#ifndef GENGENPARSER_H
#define GENGENPARSER_H
#include <string>
#include <boost/algorithm/string.hpp>
#include "linecodegenerator.h"
#include "staticcodegetter.h"
#include "codeappender.h"
#include "codejoiner.h"
#include "postparser.h"
enum SingleLineParseMode {
LINEMODE_CODE,
LINEMODE_TEMPLATE
};
enum BlockType {
BLOCK_PREHEADER,
BLOCK_HEADER,
BLOCK_FOOTER,
BLOCK_POSTFOOTER,
BLOCK_CODE,
BLOCK_UNKNOWN
};
enum BlockMode {
BLOCKMODE_CODE,
BLOCKMODE_TEMPLATE
};
static std::string TOKEN_LINEDUMP("$$$");
static std::string TOKEN_INDENTNEXT("$$>");
static std::string TOKEN_INDENTEQUAL("$=>");
static std::string TOKEN_INDENTDEPTHOFTWO("$>>");
static std::string TOKEN_UNINDENTNEXT("<$$");
static std::string TOKEN_UNINDENTEQUAL("<=$");
static std::string TOKEN_UNINDENTDEPTHOFTWO("<<$");
static std::string TOKEN_INLINE_START("{$$");
static std::string TOKEN_INLINE_END("$$}");
static std::string TOKEN_PREHEADER("$$PREHEADER");
static std::string TOKEN_HEADER("$$HEADER");
static std::string TOKEN_FOOTER("$$FOOTER");
static std::string TOKEN_POSTFOOTER("$$POSTFOOTER");
static std::string TOKEN_CODEBLOCK("$$CODE");
static std::string TOKEN_ENDBLOCK("$$END");
class GenGenParser {
private:
LineCodeGenerator* mLinecode;
StaticCodeGetter* mStaticGetter;
PostParser* mPostParser;
CodeAppender mAppender;
unsigned int indentCount;
bool IsStrIn(std::string& str, int pos, std::string& checkStr);
void LineModeParse(std::string& line, int size);
public:
GenGenParser(LineCodeGenerator* linecode, StaticCodeGetter* staticGetter, PostParser* postParser);
void Parse();
void PostParse();
};
#endif // GENGENPARSER_H
gengenparser.cpp
#include "gengenparser.h"
bool GenGenParser::IsStrIn(std::string& str, int pos, std::string& checkStr)
{
int check_str_size = checkStr.length();
int str_size = str.length();
if (pos + check_str_size > str_size) {
return false;
}
for (int i = 0; i < check_str_size; i++) {
if (str[pos + i] != checkStr[i]) {
return false;
}
}
return true;
}
void GenGenParser::LineModeParse(std::string& line, int size)
{
std::string token("");
SingleLineParseMode mode = LINEMODE_CODE;
mLinecode->StartLine();
for (int i = 0; i < size; ++i) {
if (this->IsStrIn(line, i, TOKEN_INLINE_START)) {
i += 2;
if (!token.empty()) {
mLinecode->WriteCodePrintingCode(token);
token.clear();
}
mode = LINEMODE_TEMPLATE;
continue;
} else if (this->IsStrIn(line, i, TOKEN_INLINE_END)) {
i += 2;
if (!token.empty()) {
mLinecode->WriteCode(token);
token.clear();
}
mode = LINEMODE_CODE;
continue;
}
char chr = line[i];
if (mode == LINEMODE_CODE) {
mLinecode->EscapedAppend(token, chr);
} else {
token.push_back(chr);
}
}
mLinecode->WriteCodePrintingCode(token);
mLinecode->EndLine();
mAppender.AppendToCodeBody(mLinecode->CalculateIndent(indentCount) + mLinecode->GetGeneratedCode());
}
GenGenParser::GenGenParser(LineCodeGenerator *linecode, StaticCodeGetter *staticGetter, PostParser *postParser)
{
mLinecode = linecode;
mStaticGetter = staticGetter;
mPostParser = postParser;
indentCount = staticGetter->GetStartingIndent();
}
void GenGenParser::Parse()
{
std::string line;
BlockMode blockMode = BLOCKMODE_TEMPLATE;
BlockType blockType = BLOCK_UNKNOWN;
while (std::getline(std::cin, line)) {
std::string trimmedLine = boost::trim_copy(line);
if (boost::equal(trimmedLine, TOKEN_ENDBLOCK)) {
blockMode = BLOCKMODE_TEMPLATE;
blockType = BLOCK_UNKNOWN;
continue;
} else if (boost::equal(trimmedLine, TOKEN_PREHEADER)) {
blockMode = BLOCKMODE_CODE;
blockType = BLOCK_PREHEADER;
continue;
} else if (boost::equal(trimmedLine, TOKEN_HEADER)) {
blockMode = BLOCKMODE_CODE;
blockType = BLOCK_HEADER;
continue;
} else if (boost::equal(trimmedLine, TOKEN_FOOTER)) {
blockMode = BLOCKMODE_CODE;
blockType = BLOCK_FOOTER;
continue;
} else if (boost::equal(trimmedLine, TOKEN_POSTFOOTER)) {
blockMode = BLOCKMODE_CODE;
blockType = BLOCK_POSTFOOTER;
continue;
} else if (boost::equal(trimmedLine, TOKEN_CODEBLOCK)) {
blockMode = BLOCKMODE_CODE;
blockType = BLOCK_CODE;
continue;
}
if (blockMode == BLOCKMODE_CODE) {
switch (blockType) {
case BLOCK_PREHEADER:
mAppender.AppendToPreHeader(line);
break;
case BLOCK_HEADER:
mAppender.AppendToHeader(line);
break;
case BLOCK_FOOTER:
mAppender.AppendToFooter(line);
break;
case BLOCK_POSTFOOTER:
mAppender.AppendToPostFooter(line);
break;
case BLOCK_CODE:
mAppender.AppendToCodeBody(line);
break;
default:
break;
}
continue;
}
if (this->IsStrIn(line, 0, TOKEN_LINEDUMP)) {
mAppender.AppendToCodeBody(mLinecode->CalculateIndent(indentCount)
+ line.substr(TOKEN_LINEDUMP.length()));
continue;
} else if (this->IsStrIn(line, 0, TOKEN_INDENTNEXT)) {
mAppender.AppendToCodeBody(mLinecode->CalculateIndent(indentCount++)
+ line.substr(TOKEN_INDENTNEXT.length()));
continue;
} else if (this->IsStrIn(line, 0, TOKEN_INDENTEQUAL)) {
mAppender.AppendToCodeBody(mLinecode->CalculateIndent(++indentCount)
+ line.substr(TOKEN_INDENTEQUAL.length()));
continue;
} else if (this->IsStrIn(line, 0, TOKEN_INDENTDEPTHOFTWO)) {
mAppender.AppendToCodeBody(mLinecode->CalculateIndent(++indentCount)
+ line.substr(TOKEN_INDENTDEPTHOFTWO.length()));
indentCount++;
continue;
} else if (this->IsStrIn(line, 0, TOKEN_UNINDENTNEXT)) {
mAppender.AppendToCodeBody(mLinecode->CalculateIndent(indentCount)
+ line.substr(TOKEN_UNINDENTNEXT.length()));
if (indentCount > 0) {
--indentCount;
}
continue;
} else if (this->IsStrIn(line, 0, TOKEN_UNINDENTEQUAL)) {
if (indentCount > 0) {
--indentCount;
}
mAppender.AppendToCodeBody(mLinecode->CalculateIndent(indentCount)
+ line.substr(TOKEN_UNINDENTEQUAL.length()));
continue;
} else if (this->IsStrIn(line, 0, TOKEN_UNINDENTDEPTHOFTWO)) {
if (indentCount > 0) {
--indentCount;
}
mAppender.AppendToCodeBody(mLinecode->CalculateIndent(indentCount)
+ line.substr(TOKEN_UNINDENTDEPTHOFTWO.length()));
if (indentCount > 0) {
--indentCount;
}
continue;
}
this->LineModeParse(line, line.length());
}
}
void GenGenParser::PostParse()
{
CodeJoiner joiner(mAppender, mStaticGetter);
mPostParser->PostParse(joiner.GetCode());
}
codeappender.h
#ifndef CODEAPPENDER_H
#define CODEAPPENDER_H
#include <string>
class CodeAppender {
private:
std::string mStdStrPreHeader;
std::string mStdStrHeader;
std::string mStdStrCodeBody;
std::string mStdStrFooter;
std::string mStdStrPostFooter;
public:
virtual void AppendToPreHeader(const std::string& code);
virtual std::string GetPreHeader();
virtual void AppendToHeader(const std::string& code);
virtual std::string GetHeader();
virtual void AppendToCodeBody(const std::string& code);
virtual std::string GetCodeBody();
virtual void AppendToFooter(const std::string& code);
virtual std::string GetFooter();
virtual void AppendToPostFooter(const std::string& code);
virtual std::string GetPostFooter();
};
#endif // CODEAPPENDER_H
codejoiner.h
#ifndef CODEJOINER_H
#define CODEJOINER_H
#include <string>
#include "codeappender.h"
#include "staticcodegetter.h"
class CodeJoiner {
private:
std::string mStdStrCode;
public:
CodeJoiner(CodeAppender codeAppender, StaticCodeGetter* staticCodeGetter);
virtual std::string GetCode();
};
#endif // CODEJOINER_H
postparser.h
#ifndef POSTPARSER_H
#define POSTPARSER_H
#include <iostream>
#include <string>
class PostParser {
public:
virtual void PostParse(std::string code);
};
#endif // POSTPARSER_H
staticcodegetter.h
#ifndef STATICCODEGETTER_H
#define STATICCODEGETTER_H
#include <string>
class StaticCodeGetter {
public:
virtual std::string GetBeforePreHeader() = 0;
virtual std::string GetAfterPreHeader() = 0;
virtual std::string GetAfterHeader() = 0;
virtual std::string GetBeforeFooter() = 0;
virtual std::string GetAfterFooter() = 0;
virtual std::string GetAfterPostFooter() = 0;
virtual unsigned int GetStartingIndent() = 0;
};
#endif
linecodegenerator
#ifndef LINECODEGENERATOR_H
#define LINECODEGENERATOR_H
#include <string>
class LineCodeGenerator {
public:
virtual void StartLine() = 0;
virtual void EndLine() = 0;
virtual void EscapedAppend(std::string& token, char c) = 0;
virtual void WriteCodePrintingCode(const std::string& escapedCodeToPrint) = 0;
virtual void WriteCode(const std::string& code) = 0;
virtual std::string GetGeneratedCode() = 0;
virtual std::string CalculateIndent(unsigned int amount) = 0;
};
#endif // LINECODEGENERATOR_H