159 lines
3.2 KiB
C++
159 lines
3.2 KiB
C++
#include <preprocessor/preprocessor.hpp>
|
|
#include <utils.hpp>
|
|
|
|
bool trySubstitute(
|
|
std::string & line,
|
|
std::size_t const lineColumn,
|
|
std::vector<std::string> const & substitutionIdentifiers,
|
|
std::vector<std::string> 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<std::string> & 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());
|
|
}
|
|
} |