#include #include bool trySubstitute( std::string & line, std::size_t const lineColumn, std::vector const & substitutionIdentifiers, std::vector const & substitutionValues) { for(std::size_t i = 0; i < substitutionIdentifiers.size(); ++i) { if (line.compare(lineColumn, substitutionIdentifiers[i].size(), substitutionIdentifiers[i]) != 0) { continue; } std::string const lineCopy = line; line = lineCopy.substr(0, lineColumn) + substitutionValues[i]; if (lineCopy.size() > lineColumn + substitutionIdentifiers[i].size()) { line += lineCopy.substr(lineColumn + substitutionIdentifiers[i].size(), lineCopy.size()); } return true; } return false; } void Preprocessor::extractComment( std::string & line, std::size_t const lineNumber, std::size_t const lineColumn) { if (line.size() <= lineColumn + 1 || line.compare(lineColumn + 1, std::string::npos, "DEFINE") <= 0) { // No match or empty DEFINE statement line = line.substr(0, lineColumn); } enum CommentParseState { LookForArgumentStart, LookForArgumentEnd }; std::string firstArgument, secondArgument; std::size_t argumentCount = 0, argumentStart = 0; CommentParseState state = LookForArgumentStart; for(std::size_t i = lineColumn + 7; i < line.size(); ++i) { switch(state) { case LookForArgumentStart: if(!Utils::isWhitespaceCharacter(line[i])) { argumentStart = i; state = CommentParseState::LookForArgumentEnd; } break; case LookForArgumentEnd: if (Utils::isWhitespaceCharacter(line[i])) { switch(argumentCount) { case 0: firstArgument = line.substr(argumentStart, i - argumentStart); break; case 1: secondArgument = line.substr(argumentStart, i - argumentStart); break; default: break; } ++argumentCount; state = CommentParseState::LookForArgumentStart; } break; } } switch(state) { case CommentParseState::LookForArgumentStart: break; case CommentParseState::LookForArgumentEnd: switch(argumentCount) { case 0: firstArgument = line.substr(argumentStart); break; case 1: secondArgument = line.substr(argumentStart); break; default: break; } ++argumentCount; break; } if (argumentCount > 0) { substitutionIdentifiers.push_back(firstArgument); substitutionValues.push_back(secondArgument); } line = line.substr(0, lineColumn); } void Preprocessor::processLine(std::string & line, std::size_t const lineNumber) { for(std::size_t i = 0; i < line.size(); ++i) { if (!Utils::isWhitespaceCharacter(line[i])) { if (trySubstitute(line, i, substitutionIdentifiers, substitutionValues)) { continue; } if (line[i] == '#') { extractComment(line, lineNumber, i); return; } } } } void Preprocessor::process(std::vector & lines) { substitutionIdentifiers.clear(); substitutionValues.clear(); for(std::size_t i = 0; i < lines.size(); ++i) { processLine(lines[i], i); } } void Preprocessor::printSubstitutions() const { for(std::size_t i = 0; i < substitutionIdentifiers.size(); ++i) { std::printf( "%s -> %s\n", substitutionIdentifiers[i].c_str(), substitutionValues[i].c_str()); } }